From 8e599b0daac87f8ec4a86f5e62ebf01d5f4e21f5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 13 Dec 2024 18:29:41 +0100 Subject: [PATCH 0001/2248] de-stabilize bench attribute --- library/core/src/macros/mod.rs | 1 - tests/ui/feature-gates/bench.rs | 2 -- tests/ui/feature-gates/bench.stderr | 40 ++++++++--------------------- tests/ui/lint/expansion-time.rs | 7 ----- tests/ui/lint/expansion-time.stderr | 33 ++---------------------- 5 files changed, 12 insertions(+), 71 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index ab674b58902b5..f10a58618cd81 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1683,7 +1683,6 @@ pub(crate) mod builtin { #[unstable( feature = "test", issue = "50297", - soft, reason = "`bench` is a part of custom test frameworks which are unstable" )] #[allow_internal_unstable(test, rustc_attrs, coverage_attribute)] diff --git a/tests/ui/feature-gates/bench.rs b/tests/ui/feature-gates/bench.rs index 12e646f7a323a..94c8992a8fe68 100644 --- a/tests/ui/feature-gates/bench.rs +++ b/tests/ui/feature-gates/bench.rs @@ -1,9 +1,7 @@ //@ edition:2018 #[bench] //~ ERROR use of unstable library feature `test` - //~| WARN this was previously accepted fn bench() {} use bench as _; //~ ERROR use of unstable library feature `test` - //~| WARN this was previously accepted fn main() {} diff --git a/tests/ui/feature-gates/bench.stderr b/tests/ui/feature-gates/bench.stderr index de78e863012dd..f5fc579b23be3 100644 --- a/tests/ui/feature-gates/bench.stderr +++ b/tests/ui/feature-gates/bench.stderr @@ -1,43 +1,23 @@ -error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable +error[E0658]: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable --> $DIR/bench.rs:3:3 | LL | #[bench] | ^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - = note: `#[deny(soft_unstable)]` on by default + = note: see issue #50297 for more information + = help: add `#![feature(test)]` 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: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable - --> $DIR/bench.rs:7:5 +error[E0658]: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable + --> $DIR/bench.rs:6:5 | LL | use bench as _; | ^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 + = note: see issue #50297 for more information + = help: add `#![feature(test)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors -Future incompatibility report: Future breakage diagnostic: -error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable - --> $DIR/bench.rs:3:3 - | -LL | #[bench] - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - = note: `#[deny(soft_unstable)]` on by default - -Future breakage diagnostic: -error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable - --> $DIR/bench.rs:7:5 - | -LL | use bench as _; - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - = note: `#[deny(soft_unstable)]` on by default - +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/expansion-time.rs b/tests/ui/lint/expansion-time.rs index d0f26a87385c7..c13649c93a1be 100644 --- a/tests/ui/lint/expansion-time.rs +++ b/tests/ui/lint/expansion-time.rs @@ -9,13 +9,6 @@ macro_rules! foo { macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier //~| WARN this was previously accepted -#[warn(soft_unstable)] -mod benches { - #[bench] //~ WARN use of unstable library feature `test` - //~| WARN this was previously accepted - fn foo() {} -} - #[deprecated = "reason"] macro_rules! deprecated { () => {} diff --git a/tests/ui/lint/expansion-time.stderr b/tests/ui/lint/expansion-time.stderr index f65627c2c0878..f24d1b68a8dae 100644 --- a/tests/ui/lint/expansion-time.stderr +++ b/tests/ui/lint/expansion-time.stderr @@ -26,20 +26,6 @@ note: the lint level is defined here LL | #[warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable - --> $DIR/expansion-time.rs:14:7 - | -LL | #[bench] - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 -note: the lint level is defined here - --> $DIR/expansion-time.rs:12:8 - | -LL | #[warn(soft_unstable)] - | ^^^^^^^^^^^^^ - warning: include macro expected single expression in source --> $DIR/expansion-time-include.rs:4:1 | @@ -47,12 +33,12 @@ LL | 2 | ^ | note: the lint level is defined here - --> $DIR/expansion-time.rs:29:8 + --> $DIR/expansion-time.rs:22:8 | LL | #[warn(incomplete_include)] | ^^^^^^^^^^^^^^^^^^ -warning: 4 warnings emitted +warning: 3 warnings emitted Future incompatibility report: Future breakage diagnostic: warning: missing fragment specifier @@ -69,18 +55,3 @@ note: the lint level is defined here LL | #[warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -Future breakage diagnostic: -warning: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable - --> $DIR/expansion-time.rs:14:7 - | -LL | #[bench] - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 -note: the lint level is defined here - --> $DIR/expansion-time.rs:12:8 - | -LL | #[warn(soft_unstable)] - | ^^^^^^^^^^^^^ - From f5c63b9e63b841a3b60731769078571514a1cdad Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 13 Dec 2024 20:14:13 +0100 Subject: [PATCH 0002/2248] the soft_unstable lint cannot have an example that will keep working --- compiler/rustc_lint_defs/src/builtin.rs | 32 +++---------------------- src/tools/lint-docs/src/lib.rs | 1 + 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 54e927df3c42b..a6d437b71a4ee 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2389,37 +2389,11 @@ declare_lint! { } declare_lint! { - /// The `soft_unstable` lint detects unstable features that were - /// unintentionally allowed on stable. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #[cfg(test)] - /// extern crate test; - /// - /// #[bench] - /// fn name(b: &mut test::Bencher) { - /// b.iter(|| 123) - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// The [`bench` attribute] was accidentally allowed to be specified on - /// the [stable release channel]. Turning this to a hard error would have - /// broken some projects. This lint allows those projects to continue to - /// build correctly when [`--cap-lints`] is used, but otherwise signal an - /// error that `#[bench]` should not be used on the stable channel. This - /// is a [future-incompatible] lint to transition this to a hard error in - /// the future. See [issue #64266] for more details. + /// The `soft_unstable` lint detects unstable features that were unintentionally allowed on + /// stable. This is a [future-incompatible] lint to transition this to a hard error in the + /// future. See [issue #64266] for more details. /// /// [issue #64266]: https://github.com/rust-lang/rust/issues/64266 - /// [`bench` attribute]: https://doc.rust-lang.org/nightly/unstable-book/library-features/test.html - /// [stable release channel]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html - /// [`--cap-lints`]: https://doc.rust-lang.org/rustc/lints/levels.html#capping-lints /// [future-incompatible]: ../index.md#future-incompatible-lints pub SOFT_UNSTABLE, Deny, diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index 8c7ff08ccd72c..b54a4dba41c78 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -306,6 +306,7 @@ impl<'a> LintExtractor<'a> { if matches!( lint.name.as_str(), "unused_features" // broken lint + | "soft_unstable" // cannot have a stable example ) { return Ok(()); } From 60ee6fbaa464d4d65313a7919c07113ef6068140 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 31 Oct 2024 11:39:45 +0100 Subject: [PATCH 0003/2248] Update tests. --- example/mini_core.rs | 2 +- example/mini_core_hello_world.rs | 4 ++-- example/mod_bench.rs | 2 +- example/std_example.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index cdd151613df84..685e03c07c189 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -681,7 +681,7 @@ impl Index for [T] { } } -extern { +extern "C" { type VaListImpl; } diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index dcfa34cb729d8..1d51e0a1856ba 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -258,13 +258,13 @@ fn main() { assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42); - extern { + extern "C" { #[linkage = "weak"] static ABC: *const u8; } { - extern { + extern "C" { #[linkage = "weak"] static ABC: *const u8; } diff --git a/example/mod_bench.rs b/example/mod_bench.rs index cae911c1073d5..e8a9cade74745 100644 --- a/example/mod_bench.rs +++ b/example/mod_bench.rs @@ -3,7 +3,7 @@ #![allow(internal_features)] #[link(name = "c")] -extern {} +extern "C" {} #[panic_handler] fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! { diff --git a/example/std_example.rs b/example/std_example.rs index 9e43b4635f0d3..5fa1e0afb0603 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -7,7 +7,7 @@ use std::arch::x86_64::*; use std::io::Write; use std::ops::Coroutine; -extern { +extern "C" { pub fn printf(format: *const i8, ...) -> i32; } 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 0004/2248] 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 0f89f3ffd438d145a0896c6c86de3bf46d7e14df Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 15 Dec 2024 11:03:37 +0000 Subject: [PATCH 0005/2248] Use a C-safe return type for `__rust_[ui]128_*` overflowing intrinsics Combined with [1], this will change the overflowing multiplication operations to return an `extern "C"`-safe type. Link: https://github.com/rust-lang/compiler-builtins/pull/735 [1] --- src/int.rs | 123 +++++++++++++++++++++---------------------- src/intrinsic/mod.rs | 6 ++- 2 files changed, 64 insertions(+), 65 deletions(-) diff --git a/src/int.rs b/src/int.rs index 7b9d1feb8d710..fe6a65bed03b0 100644 --- a/src/int.rs +++ b/src/int.rs @@ -322,36 +322,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { }, } } else { - match new_kind { - Int(I128) | Uint(U128) => { - let func_name = match oop { - OverflowOp::Add => match new_kind { - Int(I128) => "__rust_i128_addo", - Uint(U128) => "__rust_u128_addo", - _ => unreachable!(), - }, - OverflowOp::Sub => match new_kind { - Int(I128) => "__rust_i128_subo", - Uint(U128) => "__rust_u128_subo", - _ => unreachable!(), - }, - OverflowOp::Mul => match new_kind { - Int(I128) => "__rust_i128_mulo", // TODO(antoyo): use __muloti4d instead? - Uint(U128) => "__rust_u128_mulo", - _ => unreachable!(), - }, - }; - return self.operation_with_overflow(func_name, lhs, rhs); - } - _ => match oop { - OverflowOp::Mul => match new_kind { - Int(I32) => "__mulosi4", - Int(I64) => "__mulodi4", - _ => unreachable!(), - }, - _ => unimplemented!("overflow operation for {:?}", new_kind), + let (func_name, width) = match oop { + OverflowOp::Add => match new_kind { + Int(I128) => ("__rust_i128_addo", 128), + Uint(U128) => ("__rust_u128_addo", 128), + _ => unreachable!(), }, - } + OverflowOp::Sub => match new_kind { + Int(I128) => ("__rust_i128_subo", 128), + Uint(U128) => ("__rust_u128_subo", 128), + _ => unreachable!(), + }, + OverflowOp::Mul => match new_kind { + Int(I32) => ("__mulosi4", 32), + Int(I64) => ("__mulodi4", 64), + Int(I128) => ("__rust_i128_mulo", 128), // TODO(antoyo): use __muloti4d instead? + Uint(U128) => ("__rust_u128_mulo", 128), + _ => unreachable!(), + }, + }; + return self.operation_with_overflow(func_name, lhs, rhs, width); }; let intrinsic = self.context.get_builtin_function(name); @@ -364,80 +354,87 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { (res.dereference(self.location).to_rvalue(), overflow) } + /// Non-`__builtin_*` overflow operations with a `fn(T, T, &mut i32) -> T` signature. pub fn operation_with_overflow( &self, func_name: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>, + width: u64, ) -> (RValue<'gcc>, RValue<'gcc>) { let a_type = lhs.get_type(); let b_type = rhs.get_type(); debug_assert!(a_type.dyncast_array().is_some()); debug_assert!(b_type.dyncast_array().is_some()); + let overflow_type = self.i32_type; + let overflow_param_type = overflow_type.make_pointer(); + let res_type = a_type; + + let overflow_value = + self.current_func().new_local(self.location, overflow_type, "overflow"); + let overflow_addr = overflow_value.get_address(self.location); + let param_a = self.context.new_parameter(self.location, a_type, "a"); let param_b = self.context.new_parameter(self.location, b_type, "b"); - let result_field = self.context.new_field(self.location, a_type, "result"); - let overflow_field = self.context.new_field(self.location, self.bool_type, "overflow"); - - let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]); + let param_overflow = + self.context.new_parameter(self.location, overflow_param_type, "overflow"); + + let a_elem_type = a_type.dyncast_array().expect("non-array a value"); + debug_assert!(a_elem_type.is_integral()); + let res_ty = match width { + 32 => self.tcx.types.i32, + 64 => self.tcx.types.i64, + 128 => self.tcx.types.i128, + _ => unreachable!("unexpected integer size"), + }; let layout = self .tcx - .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ret_ty)) + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(res_ty)) .unwrap(); let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) }; let mut fn_abi = FnAbi { - args: vec![arg_abi.clone(), arg_abi.clone()].into_boxed_slice(), + args: vec![arg_abi.clone(), arg_abi.clone(), arg_abi.clone()].into_boxed_slice(), ret: arg_abi, c_variadic: false, - fixed_count: 2, + fixed_count: 3, conv: Conv::C, can_unwind: false, }; fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C { unwind: false }).unwrap(); - let indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); - - let return_type = self - .context - .new_struct_type(self.location, "result_overflow", &[result_field, overflow_field]); - let result = if indirect { - let return_value = - self.current_func().new_local(self.location, return_type.as_type(), "return_value"); - let return_param_type = return_type.as_type().make_pointer(); - let return_param = - self.context.new_parameter(self.location, return_param_type, "return_value"); + let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); + + let result = if ret_indirect { + let res_value = self.current_func().new_local(self.location, res_type, "result_value"); + let res_addr = res_value.get_address(self.location); + let res_param_type = res_type.make_pointer(); + let param_res = self.context.new_parameter(self.location, res_param_type, "result"); + let func = self.context.new_function( self.location, FunctionType::Extern, self.type_void(), - &[return_param, param_a, param_b], + &[param_res, param_a, param_b, param_overflow], func_name, false, ); - self.llbb().add_eval( - self.location, - self.context.new_call(self.location, func, &[ - return_value.get_address(self.location), - lhs, - rhs, - ]), - ); - return_value.to_rvalue() + let _void = + self.context.new_call(self.location, func, &[res_addr, lhs, rhs, overflow_addr]); + res_value.to_rvalue() } else { let func = self.context.new_function( self.location, FunctionType::Extern, - return_type.as_type(), - &[param_a, param_b], + res_type, + &[param_a, param_b, param_overflow], func_name, false, ); - self.context.new_call(self.location, func, &[lhs, rhs]) + self.context.new_call(self.location, func, &[lhs, rhs, overflow_addr]) }; - let overflow = result.access_field(self.location, overflow_field); - let int_result = result.access_field(self.location, result_field); - (int_result, overflow) + + (result, self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue()) } pub fn gcc_icmp( diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 42d189d1b7d38..48606f5f91c0f 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -1001,7 +1001,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { 128 => "__rust_i128_addo", _ => unreachable!(), }; - let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs); + let (int_result, overflow) = + self.operation_with_overflow(func_name, lhs, rhs, width); self.llbb().add_assignment(self.location, res, int_result); overflow }; @@ -1071,7 +1072,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { 128 => "__rust_i128_subo", _ => unreachable!(), }; - let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs); + let (int_result, overflow) = + self.operation_with_overflow(func_name, lhs, rhs, width); self.llbb().add_assignment(self.location, res, int_result); overflow }; From 4600047767f36d12dff51e2b844ed67f81d7adda Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Fri, 17 Jan 2025 09:44:09 -0800 Subject: [PATCH 0006/2248] When LLVM's location discriminator value limit is exceeded, emit locations with dummy spans instead of dropping them entirely Revert most of #133194 (except the test and the comment fixes). Then refix not emitting locations at all when the correct location discriminator value exceeds LLVM's capacity. --- src/debuginfo.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index d3aeb7f3bdeb3..4b84b1dbfd396 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -113,15 +113,15 @@ fn make_mir_scope<'gcc, 'tcx>( let scope_data = &mir.source_scopes[scope]; let parent_scope = if let Some(parent) = scope_data.parent_scope { make_mir_scope(cx, _instance, mir, variables, debug_context, instantiated, parent); - debug_context.scopes[parent].unwrap() + debug_context.scopes[parent] } else { // The root is the function itself. let file = cx.sess().source_map().lookup_source_file(mir.span.lo()); - debug_context.scopes[scope] = Some(DebugScope { + debug_context.scopes[scope] = DebugScope { file_start_pos: file.start_pos, file_end_pos: file.end_position(), - ..debug_context.scopes[scope].unwrap() - }); + ..debug_context.scopes[scope] + }; instantiated.insert(scope); return; }; @@ -130,7 +130,7 @@ fn make_mir_scope<'gcc, 'tcx>( if !vars.contains(scope) && scope_data.inlined.is_none() { // Do not create a DIScope if there are no variables defined in this // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. - debug_context.scopes[scope] = Some(parent_scope); + debug_context.scopes[scope] = parent_scope; instantiated.insert(scope); return; } @@ -157,12 +157,12 @@ fn make_mir_scope<'gcc, 'tcx>( // TODO(tempdragon): dbg_scope: Add support for scope extension here. inlined_at.or(p_inlined_at); - debug_context.scopes[scope] = Some(DebugScope { + debug_context.scopes[scope] = DebugScope { dbg_scope, inlined_at, file_start_pos: loc.file.start_pos, file_end_pos: loc.file.end_position(), - }); + }; instantiated.insert(scope); } @@ -232,12 +232,12 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } // Initialize fn debug context (including scopes). - let empty_scope = Some(DebugScope { + let empty_scope = DebugScope { dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)), inlined_at: None, file_start_pos: BytePos(0), file_end_pos: BytePos(0), - }); + }; let mut fn_debug_context = FunctionDebugContext { scopes: IndexVec::from_elem(empty_scope, mir.source_scopes.as_slice()), inlined_function_scopes: Default::default(), From 49e047f5aa09d8179dce0d36df8a8263b144de81 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 8 Jan 2025 15:00:25 +0000 Subject: [PATCH 0007/2248] Treat undef bytes as equal to any other byte --- src/common.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common.rs b/src/common.rs index f43743fc2a41b..bd5d6ba387cff 100644 --- a/src/common.rs +++ b/src/common.rs @@ -64,6 +64,11 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) } } + fn is_undef(&self, _val: RValue<'gcc>) -> bool { + // FIXME: actually check for undef + false + } + fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> { let local = self.current_func.borrow().expect("func").new_local(None, typ, "undefined"); if typ.is_struct().is_some() { From 301d2478e04264d1336572a810c33108ec0a278f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 14 Dec 2024 09:13:12 +0100 Subject: [PATCH 0008/2248] remove support for the #[start] attribute --- build_system/src/test.rs | 26 ----------------------- example/alloc_example.rs | 7 ++++--- example/mini_core_hello_world.rs | 2 +- example/mod_bench.rs | 36 -------------------------------- src/context.rs | 1 - tests/run/abort1.rs | 7 ++++--- tests/run/abort2.rs | 7 ++++--- tests/run/array.rs | 7 ++++--- tests/run/assign.rs | 7 ++++--- tests/run/closure.rs | 7 ++++--- tests/run/condition.rs | 7 ++++--- tests/run/empty_main.rs | 7 ++++--- tests/run/exit.rs | 7 ++++--- tests/run/exit_code.rs | 7 ++++--- tests/run/fun_ptr.rs | 7 ++++--- tests/run/mut_ref.rs | 7 ++++--- tests/run/operations.rs | 7 ++++--- tests/run/ptr_cast.rs | 7 ++++--- tests/run/return-tuple.rs | 7 ++++--- tests/run/slice.rs | 7 ++++--- tests/run/static.rs | 7 ++++--- tests/run/structs.rs | 7 ++++--- tests/run/tuple.rs | 7 ++++--- 23 files changed, 77 insertions(+), 121 deletions(-) delete mode 100644 example/mod_bench.rs diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 7cc7336612c79..0e790a4befc9b 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -426,19 +426,6 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { run_command_with_env(&command, None, Some(env))?; maybe_run_command_in_vm(&[&cargo_target_dir.join("track-caller-attribute")], env, args)?; - // FIXME: create a function "display_if_not_quiet" or something along the line. - println!("[AOT] mod_bench"); - let mut command = args.config_info.rustc_command_vec(); - command.extend_from_slice(&[ - &"example/mod_bench.rs", - &"--crate-type", - &"bin", - &"--target", - &args.config_info.target_triple, - ]); - run_command_with_env(&command, None, Some(env))?; - // FIXME: the compiled binary is not run. - Ok(()) } @@ -696,19 +683,6 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } -// echo "[BENCH COMPILE] mod_bench" -// -// COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline" -// COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o $cargo_target_dir/mod_bench_llvm_0 -Cpanic=abort" -// COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o $cargo_target_dir/mod_bench_llvm_1 -Cpanic=abort" -// COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o $cargo_target_dir/mod_bench_llvm_2 -Cpanic=abort" -// COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o $cargo_target_dir/mod_bench_llvm_3 -Cpanic=abort" -// -// Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow -// hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3" -// echo "[BENCH RUN] mod_bench" -// hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_* - fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { if !args.is_using_gcc_master_branch() { println!("Not using GCC master branch. Skipping `extended_rand_tests`."); diff --git a/example/alloc_example.rs b/example/alloc_example.rs index 6ed8b9157f21a..9a0b46d5b221a 100644 --- a/example/alloc_example.rs +++ b/example/alloc_example.rs @@ -1,5 +1,6 @@ -#![feature(start, core_intrinsics, alloc_error_handler, lang_items)] +#![feature(core_intrinsics, alloc_error_handler, lang_items)] #![no_std] +#![no_main] #![allow(internal_features)] extern crate alloc; @@ -37,8 +38,8 @@ unsafe extern "C" fn _Unwind_Resume() { core::intrinsics::unreachable(); } -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { let world: Box<&str> = Box::new("Hello World!\0"); unsafe { puts(*world as *const str as *const u8); diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 1d51e0a1856ba..4cbe66c5e4c69 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -1,7 +1,7 @@ // Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs #![feature( - no_core, unboxed_closures, start, lang_items, never_type, linkage, + no_core, unboxed_closures, lang_items, never_type, linkage, extern_types, thread_local )] #![no_core] diff --git a/example/mod_bench.rs b/example/mod_bench.rs deleted file mode 100644 index e8a9cade74745..0000000000000 --- a/example/mod_bench.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![feature(start, core_intrinsics, lang_items)] -#![no_std] -#![allow(internal_features)] - -#[link(name = "c")] -extern "C" {} - -#[panic_handler] -fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! { - core::intrinsics::abort(); -} - -#[lang="eh_personality"] -fn eh_personality(){} - -// Required for rustc_codegen_llvm -#[no_mangle] -unsafe extern "C" fn _Unwind_Resume() { - core::intrinsics::unreachable(); -} - -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { - for i in 2..100_000_000 { - black_box((i + 1) % i); - } - - 0 -} - -#[inline(never)] -fn black_box(i: u32) { - if i != 1 { - core::intrinsics::abort(); - } -} diff --git a/src/context.rs b/src/context.rs index c81c53359fd18..30732c74eb3ef 100644 --- a/src/context.rs +++ b/src/context.rs @@ -513,7 +513,6 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } else { // If the symbol already exists, it is an error: for example, the user wrote // #[no_mangle] extern "C" fn main(..) {..} - // instead of #[start] None } } diff --git a/tests/run/abort1.rs b/tests/run/abort1.rs index 696197d73772f..385e41a68817f 100644 --- a/tests/run/abort1.rs +++ b/tests/run/abort1.rs @@ -3,11 +3,12 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -49,7 +50,7 @@ fn test_fail() -> ! { unsafe { intrinsics::abort() }; } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { test_fail(); } diff --git a/tests/run/abort2.rs b/tests/run/abort2.rs index 714cd6c0f3817..6c66a930e0741 100644 --- a/tests/run/abort2.rs +++ b/tests/run/abort2.rs @@ -3,11 +3,12 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -50,8 +51,8 @@ fn fail() -> i32 { 0 } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { fail(); 0 } diff --git a/tests/run/array.rs b/tests/run/array.rs index c3c08c29c6dba..e18a4ced6bc46 100644 --- a/tests/run/array.rs +++ b/tests/run/array.rs @@ -7,10 +7,11 @@ // 5 // 10 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -28,8 +29,8 @@ fn make_array() -> [u8; 3] { [42, 10, 5] } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let array = [42, 7, 5]; let array2 = make_array(); unsafe { diff --git a/tests/run/assign.rs b/tests/run/assign.rs index 2a47f0c2966e5..4d414c577a657 100644 --- a/tests/run/assign.rs +++ b/tests/run/assign.rs @@ -6,10 +6,11 @@ // 10 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -142,8 +143,8 @@ fn inc(num: isize) -> isize { } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { argc = inc(argc); unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc); diff --git a/tests/run/closure.rs b/tests/run/closure.rs index 46c47bc54ed01..c7a236f74f9e6 100644 --- a/tests/run/closure.rs +++ b/tests/run/closure.rs @@ -8,10 +8,11 @@ // Int argument: 2 // Both args: 11 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -22,8 +23,8 @@ mod libc { } } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let string = "Arg: %d\n\0"; let mut closure = || { unsafe { diff --git a/tests/run/condition.rs b/tests/run/condition.rs index 039ef94eaa717..b02359702ed2e 100644 --- a/tests/run/condition.rs +++ b/tests/run/condition.rs @@ -5,10 +5,11 @@ // stdout: true // 1 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -19,8 +20,8 @@ mod libc { } } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { if argc == 1 { libc::printf(b"true\n\0" as *const u8 as *const i8); diff --git a/tests/run/empty_main.rs b/tests/run/empty_main.rs index e66a859ad698e..042e44080c53a 100644 --- a/tests/run/empty_main.rs +++ b/tests/run/empty_main.rs @@ -3,11 +3,12 @@ // Run-time: // status: 0 -#![feature(auto_traits, lang_items, no_core, start)] +#![feature(auto_traits, lang_items, no_core)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -34,7 +35,7 @@ pub(crate) unsafe auto trait Freeze {} * Code */ -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { 0 } diff --git a/tests/run/exit.rs b/tests/run/exit.rs index bf1cbeef30205..9a7c91c0adb20 100644 --- a/tests/run/exit.rs +++ b/tests/run/exit.rs @@ -3,11 +3,12 @@ // Run-time: // status: 2 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] mod libc { #[link(name = "c")] @@ -41,8 +42,8 @@ pub(crate) unsafe auto trait Freeze {} * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { libc::exit(2); } diff --git a/tests/run/exit_code.rs b/tests/run/exit_code.rs index be7a233efdaaf..c50d2b0d7107c 100644 --- a/tests/run/exit_code.rs +++ b/tests/run/exit_code.rs @@ -3,11 +3,12 @@ // Run-time: // status: 1 -#![feature(auto_traits, lang_items, no_core, start)] +#![feature(auto_traits, lang_items, no_core)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -34,7 +35,7 @@ pub(crate) unsafe auto trait Freeze {} * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { 1 } diff --git a/tests/run/fun_ptr.rs b/tests/run/fun_ptr.rs index ed1bf72bb2754..98b351e504495 100644 --- a/tests/run/fun_ptr.rs +++ b/tests/run/fun_ptr.rs @@ -4,10 +4,11 @@ // status: 0 // stdout: 1 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -26,8 +27,8 @@ fn call_func(func: fn(i16) -> i8, param: i16) -> i8 { func(param) } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { let result = call_func(i16_as_i8, argc as i16) as isize; libc::printf(b"%ld\n\0" as *const u8 as *const i8, result); diff --git a/tests/run/mut_ref.rs b/tests/run/mut_ref.rs index 3ae793382164b..9be64f991ee08 100644 --- a/tests/run/mut_ref.rs +++ b/tests/run/mut_ref.rs @@ -8,10 +8,11 @@ // 11 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -148,8 +149,8 @@ fn update_num(num: &mut isize) { *num = *num + 5; } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let mut test = test(argc); unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field); diff --git a/tests/run/operations.rs b/tests/run/operations.rs index 0e44fc580b8c4..c92d3cc0b8fbf 100644 --- a/tests/run/operations.rs +++ b/tests/run/operations.rs @@ -6,10 +6,11 @@ // 10 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, arbitrary_self_types, rustc_attrs)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -231,8 +232,8 @@ pub fn panic_const_mul_overflow() -> ! { * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 + argc); libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 - argc); diff --git a/tests/run/ptr_cast.rs b/tests/run/ptr_cast.rs index 2b8812ad51c5e..0ba49e7187fca 100644 --- a/tests/run/ptr_cast.rs +++ b/tests/run/ptr_cast.rs @@ -4,10 +4,11 @@ // status: 0 // stdout: 1 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -24,8 +25,8 @@ fn make_array() -> [u8; 3] { [42, 10, 5] } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { let ptr = ONE as *mut usize; let value = ptr as usize; diff --git a/tests/run/return-tuple.rs b/tests/run/return-tuple.rs index f2a5a2e4384df..3cc1e274001e7 100644 --- a/tests/run/return-tuple.rs +++ b/tests/run/return-tuple.rs @@ -6,11 +6,12 @@ // 10 // 42 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] #[lang = "copy"] pub unsafe trait Copy {} @@ -61,8 +62,8 @@ fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u3 ) } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42); unsafe { libc::printf(b"%d\n\0" as *const u8 as *const i8, c); diff --git a/tests/run/slice.rs b/tests/run/slice.rs index fba93fc155495..825fcb8a081e7 100644 --- a/tests/run/slice.rs +++ b/tests/run/slice.rs @@ -4,10 +4,11 @@ // status: 0 // stdout: 5 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -26,8 +27,8 @@ fn index_slice(s: &[u32]) -> u32 { } } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let array = [42, 7, 5]; unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, index_slice(&array)); diff --git a/tests/run/static.rs b/tests/run/static.rs index a17ea2a48936d..80c8782c4b1a6 100644 --- a/tests/run/static.rs +++ b/tests/run/static.rs @@ -9,11 +9,12 @@ // 12 // 1 -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -98,8 +99,8 @@ static mut WITH_REF: WithRef = WithRef { refe: unsafe { &TEST }, }; -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, CONSTANT); libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field); diff --git a/tests/run/structs.rs b/tests/run/structs.rs index d6455667400c9..59b8f358863f2 100644 --- a/tests/run/structs.rs +++ b/tests/run/structs.rs @@ -5,11 +5,12 @@ // stdout: 1 // 2 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -55,8 +56,8 @@ fn one() -> isize { 1 } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let test = Test { field: one(), }; diff --git a/tests/run/tuple.rs b/tests/run/tuple.rs index 8a7d85ae867e8..ed60a56a68c4c 100644 --- a/tests/run/tuple.rs +++ b/tests/run/tuple.rs @@ -4,11 +4,12 @@ // status: 0 // stdout: 3 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -42,8 +43,8 @@ mod libc { * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let test: (isize, isize, isize) = (3, 1, 4); unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.0); From 0692ca3d20787e43a3ff3674c0cc7e7487de6508 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 24 Jan 2025 16:05:26 -0500 Subject: [PATCH 0009/2248] Make CodegenCx and Builder generic Co-authored-by: Oli Scherer --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 7329080ce1f71..34aead1a6300a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -442,7 +442,6 @@ impl WriteBackendMethods for GccCodegenBackend { } fn autodiff( _cgcx: &CodegenContext, - _tcx: TyCtxt<'_>, _module: &ModuleCodegen, _diff_fncs: Vec, _config: &ModuleConfig, From d6d7c1581e211b9847ffc488645ec7bc342990f7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Jan 2025 23:12:17 +0100 Subject: [PATCH 0010/2248] Merge commit '9f33f846ddc06afd7ffd839ee4f18babac3f3204' --- .github/workflows/ci.yml | 10 +++--- .github/workflows/failures.yml | 6 ++-- .github/workflows/gcc12.yml | 2 +- .github/workflows/m68k.yml | 8 ++--- .github/workflows/release.yml | 13 +++++--- build_system/src/build.rs | 10 ++++-- build_system/src/config.rs | 57 ++++++++++++++++++++++++++-------- build_system/src/info.rs | 4 ++- build_system/src/main.rs | 4 +-- build_system/src/test.rs | 7 +++-- libgccjit.version | 2 +- messages.ftl | 3 -- 12 files changed, 85 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73ec6b84a155e..f96912e6b7a83 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,14 +13,14 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: libgccjit_version: - - { gcc: "gcc-13.deb" } - - { gcc: "gcc-13-without-int128.deb" } + - { gcc: "gcc-15.deb" } + - { gcc: "gcc-15-without-int128.deb" } commands: [ "--std-tests", # FIXME: re-enable asm tests when GCC can emit in the right syntax. @@ -108,13 +108,13 @@ jobs: cargo clippy --all-targets --features master -- -D warnings duplicates: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - run: python tools/check_intrinsics_duplicates.py build_system: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Test build system diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index f33d9fcc58257..d080bbfe91fe6 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -13,7 +13,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -56,12 +56,12 @@ jobs: - name: Download artifact if: matrix.libgccjit_version.gcc != 'libgccjit12.so' - run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-13.deb + run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-15.deb - name: Setup path to libgccjit if: matrix.libgccjit_version.gcc != 'libgccjit12.so' run: | - sudo dpkg --force-overwrite -i gcc-13.deb + sudo dpkg --force-overwrite -i gcc-15.deb echo 'gcc-path = "/usr/lib"' > config.toml echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index 4c2ce91e86eef..bb9e020dc6a4c 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -17,7 +17,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index 07bb372b3606d..ed1fc02bd9131 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -17,7 +17,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -47,17 +47,17 @@ jobs: - name: Install packages run: | sudo apt-get update - sudo apt-get install qemu qemu-user-static + sudo apt-get install qemu-system qemu-user-static - name: Download artifact - run: curl -LO https://github.com/cross-cg-gcc-tools/cross-gcc/releases/latest/download/gcc-m68k-13.deb + run: curl -LO https://github.com/cross-cg-gcc-tools/cross-gcc/releases/latest/download/gcc-m68k-15.deb - name: Download VM artifact run: curl -LO https://github.com/cross-cg-gcc-tools/vms/releases/latest/download/debian-m68k.img - name: Setup path to libgccjit run: | - sudo dpkg -i gcc-m68k-13.deb + sudo dpkg -i gcc-m68k-15.deb echo 'gcc-path = "/usr/lib/"' > config.toml - name: Set env diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 60e0943c87dac..886ce90b4713e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -37,11 +37,11 @@ jobs: run: sudo apt-get install ninja-build ripgrep - name: Download artifact - run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-13.deb + run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-15.deb - name: Setup path to libgccjit run: | - sudo dpkg --force-overwrite -i gcc-13.deb + sudo dpkg --force-overwrite -i gcc-15.deb echo 'gcc-path = "/usr/lib/"' > config.toml - name: Set env @@ -76,4 +76,9 @@ jobs: - name: Run y.sh cargo build run: | EMBED_LTO_BITCODE=1 CHANNEL="release" ./y.sh cargo build --release --manifest-path tests/hello-world/Cargo.toml - # TODO: grep the asm output for "call my_func" and fail if it is found. + call_found=$(objdump -dj .text tests/hello-world/target/release/hello_world | grep -c "call .*mylib.*my_func" ) ||: + if [ $call_found -gt 0 ]; then + echo "ERROR: call my_func found in asm" + echo "Test is done with LTO enabled, hence inlining should occur across crates" + exit 1 + fi diff --git a/build_system/src/build.rs b/build_system/src/build.rs index d0ced211a6169..e98377f15a945 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -150,6 +150,8 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu "debug" }; + // We have a different environment variable than RUSTFLAGS to make sure those flags are only + // sent to rustc_codegen_gcc and not the LLVM backend. if let Ok(cg_rustflags) = std::env::var("CG_RUSTFLAGS") { rustflags.push(' '); rustflags.push_str(&cg_rustflags); @@ -184,8 +186,12 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu fn build_codegen(args: &mut BuildArg) -> Result<(), String> { let mut env = HashMap::new(); - env.insert("LD_LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); - env.insert("LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); + let gcc_path = + args.config_info.gcc_path.clone().expect( + "The config module should have emitted an error if the GCC path wasn't provided", + ); + env.insert("LD_LIBRARY_PATH".to_string(), gcc_path.clone()); + env.insert("LIBRARY_PATH".to_string(), gcc_path); if args.config_info.no_default_features { env.insert("RUSTFLAGS".to_string(), "-Csymbol-mangling-version=v0".to_string()); diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 37b4b68950e49..4f9fcc9715140 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -112,7 +112,7 @@ pub struct ConfigInfo { pub sysroot_panic_abort: bool, pub cg_backend_path: String, pub sysroot_path: String, - pub gcc_path: String, + pub gcc_path: Option, config_file: Option, // This is used in particular in rust compiler bootstrap because it doesn't run at the root // of the `cg_gcc` folder, making it complicated for us to get access to local files we need @@ -173,6 +173,14 @@ impl ConfigInfo { "--release-sysroot" => self.sysroot_release_channel = true, "--release" => self.channel = Channel::Release, "--sysroot-panic-abort" => self.sysroot_panic_abort = true, + "--gcc-path" => match args.next() { + Some(arg) if !arg.is_empty() => { + self.gcc_path = Some(arg.into()); + } + _ => { + return Err("Expected a value after `--gcc-path`, found nothing".to_string()); + } + }, "--cg_gcc-path" => match args.next() { Some(arg) if !arg.is_empty() => { self.cg_gcc_path = Some(arg.into()); @@ -260,8 +268,9 @@ impl ConfigInfo { create_symlink(&libgccjit_so, output_dir.join(&format!("{}.0", libgccjit_so_name)))?; } - self.gcc_path = output_dir.display().to_string(); - println!("Using `{}` as path for libgccjit", self.gcc_path); + let gcc_path = output_dir.display().to_string(); + println!("Using `{}` as path for libgccjit", gcc_path); + self.gcc_path = Some(gcc_path); Ok(()) } @@ -273,6 +282,15 @@ impl ConfigInfo { } pub fn setup_gcc_path(&mut self) -> Result<(), String> { + // If the user used the `--gcc-path` option, no need to look at `config.toml` content + // since we already have everything we need. + if let Some(gcc_path) = &self.gcc_path { + println!( + "`--gcc-path` was provided, ignoring config file. Using `{}` as path for libgccjit", + gcc_path + ); + return Ok(()); + } let config_file = match self.config_file.as_deref() { Some(config_file) => config_file.into(), None => self.compute_path("config.toml"), @@ -283,12 +301,15 @@ impl ConfigInfo { self.download_gccjit_if_needed()?; return Ok(()); } - self.gcc_path = match gcc_path { - Some(path) => path, - None => { - return Err(format!("missing `gcc-path` value from `{}`", config_file.display(),)); - } + let Some(gcc_path) = gcc_path else { + return Err(format!("missing `gcc-path` value from `{}`", config_file.display())); }; + println!( + "GCC path retrieved from `{}`. Using `{}` as path for libgccjit", + config_file.display(), + gcc_path + ); + self.gcc_path = Some(gcc_path); Ok(()) } @@ -299,10 +320,17 @@ impl ConfigInfo { ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); - if self.gcc_path.is_empty() && !use_system_gcc { - self.setup_gcc_path()?; - } - env.insert("GCC_PATH".to_string(), self.gcc_path.clone()); + let gcc_path = if !use_system_gcc { + if self.gcc_path.is_none() { + self.setup_gcc_path()?; + } + self.gcc_path.clone().expect( + "The config module should have emitted an error if the GCC path wasn't provided", + ) + } else { + String::new() + }; + env.insert("GCC_PATH".to_string(), gcc_path.clone()); if self.cargo_target_dir.is_empty() { match env.get("CARGO_TARGET_DIR").filter(|dir| !dir.is_empty()) { @@ -381,6 +409,8 @@ impl ConfigInfo { } // This environment variable is useful in case we want to change options of rustc commands. + // We have a different environment variable than RUSTFLAGS to make sure those flags are + // only sent to rustc_codegen_gcc and not the LLVM backend. if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") { rustflags.extend_from_slice(&split_args(&cg_rustflags)?); } @@ -414,7 +444,7 @@ impl ConfigInfo { "{target}:{sysroot}:{gcc_path}", target = self.cargo_target_dir, sysroot = sysroot.display(), - gcc_path = self.gcc_path, + gcc_path = gcc_path, ); env.insert("LIBRARY_PATH".to_string(), ld_library_path.clone()); env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone()); @@ -459,6 +489,7 @@ impl ConfigInfo { --release-sysroot : Build sysroot in release mode --sysroot-panic-abort : Build the sysroot without unwinding support --config-file : Location of the config file to be used + --gcc-path : Location of the GCC root folder --cg_gcc-path : Location of the rustc_codegen_gcc root folder (used when ran from another directory) --no-default-features : Add `--no-default-features` flag to cargo commands diff --git a/build_system/src/info.rs b/build_system/src/info.rs index ea38791d38c9a..bd891de2eb4c0 100644 --- a/build_system/src/info.rs +++ b/build_system/src/info.rs @@ -14,6 +14,8 @@ pub fn run() -> Result<(), String> { } config.no_download = true; config.setup_gcc_path()?; - println!("{}", config.gcc_path); + if let Some(gcc_path) = config.gcc_path { + println!("{}", gcc_path); + } Ok(()) } diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 3a860e2b1360c..393617183061b 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -34,11 +34,11 @@ Options: --help : Displays this help message. Commands: - cargo : Executes a cargo command. + cargo : Executes a cargo command. rustc : Compiles the program using the GCC compiler. clean : Cleans the build directory, removing all compiled files and artifacts. prepare : Prepares the environment for building, including fetching dependencies and setting up configurations. - build : Compiles the project. + build : Compiles the project. test : Runs tests for the project. info : Displays information about the build environment and project configuration. clone-gcc : Clones the GCC compiler from a specified source. diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 0e790a4befc9b..6c29c7d1825b9 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1229,8 +1229,11 @@ pub fn run() -> Result<(), String> { if !args.use_system_gcc { args.config_info.setup_gcc_path()?; - env.insert("LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); - env.insert("LD_LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); + let gcc_path = args.config_info.gcc_path.clone().expect( + "The config module should have emitted an error if the GCC path wasn't provided", + ); + env.insert("LIBRARY_PATH".to_string(), gcc_path.clone()); + env.insert("LD_LIBRARY_PATH".to_string(), gcc_path); } build_if_no_backend(&env, &args)?; diff --git a/libgccjit.version b/libgccjit.version index ff58accec1d4c..417fd5b03935d 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -45648c2edd4ecd862d9f08196d3d6c6ccba79f07 +e607be166673a8de9fc07f6f02c60426e556c5f2 diff --git a/messages.ftl b/messages.ftl index 85fa17a6ba501..882fff8673a19 100644 --- a/messages.ftl +++ b/messages.ftl @@ -5,9 +5,6 @@ codegen_gcc_unknown_ctarget_feature_prefix = codegen_gcc_invalid_minimum_alignment = invalid minimum global alignment: {$err} -codegen_gcc_lto_not_supported = - LTO is not supported. You may get a linker error. - codegen_gcc_forbidden_ctarget_feature = target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason} From 24ce0a2efa314eff96af73f5b6c5d0e3392abf38 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 12 Jan 2025 20:18:45 +0000 Subject: [PATCH 0011/2248] Stabilize `const_black_box` This has been unstably const since [1], but a tracking issue was never created. Per discussion on Zulip [2], there should not be any blockers to making this const-stable. The function does not provide any functionality at compile time but does allow code reuse between const- and non-const functions, so stabilize it here. [1]: https://github.com/rust-lang/rust/pull/92226 [2]: https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/const_black_box --- tests/run/int.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/run/int.rs b/tests/run/int.rs index bfe73c38435a3..58a26801b678c 100644 --- a/tests/run/int.rs +++ b/tests/run/int.rs @@ -3,8 +3,6 @@ // Run-time: // status: 0 -#![feature(const_black_box)] - /* * Code */ From bc6b9bf526b2aafefe5d212cdde85e01b16351ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 27 Jan 2025 23:27:43 +0100 Subject: [PATCH 0012/2248] Add CI success job --- .github/workflows/ci.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f96912e6b7a83..689a7dee435f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,3 +121,23 @@ jobs: run: | cd build_system cargo test + + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success: + needs: [build, duplicates, build_system] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' From 600999a4fe7af3c7eae9349f6530c5c7b12ce1cd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 27 Jan 2025 18:30:17 +0100 Subject: [PATCH 0013/2248] ABI-required target features: warn when they are missing in base CPU (rather than silently enabling them) --- src/gcc_util.rs | 50 +------------------------------------------------ src/lib.rs | 5 +++-- 2 files changed, 4 insertions(+), 51 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 560aff43d6538..4e8c8aaaf5c8a 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -1,10 +1,8 @@ -use std::iter::FromIterator; - #[cfg(feature = "master")] use gccjit::Context; use rustc_codegen_ssa::codegen_attrs::check_tied_features; use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unord::UnordSet; use rustc_session::Session; use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; @@ -45,12 +43,6 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Vec Date: Fri, 10 Jan 2025 04:36:11 +0000 Subject: [PATCH 0014/2248] Do not treat vtable supertraits as distinct when bound with different bound vars --- src/common.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/common.rs b/src/common.rs index bd5d6ba387cff..20a3482aaa27f 100644 --- a/src/common.rs +++ b/src/common.rs @@ -234,7 +234,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { GlobalAlloc::VTable(ty, dyn_ty) => { let alloc = self .tcx - .global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal()))) + .global_alloc(self.tcx.vtable_allocation(( + ty, + dyn_ty.principal().map(|principal| { + self.tcx.instantiate_bound_regions_with_erased(principal) + }), + ))) .unwrap_memory(); let init = const_alloc_to_gcc(self, alloc); self.static_addr_of(init, alloc.inner().align, None) From 12feb0e21fe1cc79ee31951322b3bc587e07befe Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 10 Jan 2025 20:26:10 +0000 Subject: [PATCH 0015/2248] Use ExistentialTraitRef throughout codegen --- src/context.rs | 6 +++--- src/debuginfo.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/context.rs b/src/context.rs index 30732c74eb3ef..570ef938dc44e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::layout::{ FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, }; -use rustc_middle::ty::{self, Instance, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::source_map::respan; use rustc_span::{DUMMY_SP, Span}; @@ -90,7 +90,7 @@ pub struct CodegenCx<'gcc, 'tcx> { pub function_instances: RefCell, Function<'gcc>>>, /// Cache generated vtables pub vtables: - RefCell, Option>), RValue<'gcc>>>, + RefCell, Option>), RValue<'gcc>>>, // TODO(antoyo): improve the SSA API to not require those. /// Mapping from function pointer type to indexes of on stack parameters. @@ -401,7 +401,7 @@ impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> { impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn vtables( &self, - ) -> &RefCell, Option>), RValue<'gcc>>> { + ) -> &RefCell, Option>), RValue<'gcc>>> { &self.vtables } diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 4b84b1dbfd396..86d3de225f71e 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -7,7 +7,7 @@ use rustc_data_structures::sync::Lrc; use rustc_index::bit_set::DenseBitSet; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::{self, Body, SourceScope}; -use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty}; +use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty}; use rustc_session::config::DebugInfo; use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol}; use rustc_target::abi::Size; @@ -214,7 +214,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn create_vtable_debuginfo( &self, _ty: Ty<'tcx>, - _trait_ref: Option>, + _trait_ref: Option>, _vtable: Self::Value, ) { // TODO(antoyo) From adee0849a2971663984f6d7c1612097d4cbbcbd3 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 1 Feb 2025 10:31:25 -0500 Subject: [PATCH 0016/2248] Add success job for all CI workflows --- .github/workflows/ci.yml | 1 - .github/workflows/failures.yml | 2 +- .github/workflows/gcc12.yml | 2 +- .github/workflows/m68k.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/stdarch.yml | 2 +- 6 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 689a7dee435f4..688a9f7d7bf73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,7 +122,6 @@ jobs: cd build_system cargo test - # Summary job for the merge queue. # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! success: diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index d080bbfe91fe6..b9f6f9d84f460 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - build: + success: runs-on: ubuntu-24.04 strategy: diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index bb9e020dc6a4c..0308eec51cdf3 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -16,7 +16,7 @@ env: GCC_EXEC_PREFIX: /usr/lib/gcc/ jobs: - build: + success: runs-on: ubuntu-24.04 strategy: diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index ed1fc02bd9131..e031ad59f4b51 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -16,7 +16,7 @@ env: OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu jobs: - build: + success: runs-on: ubuntu-24.04 strategy: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 886ce90b4713e..4367cbccab115 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - build: + success: runs-on: ubuntu-24.04 strategy: diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index d5ae6144496f1..ea8bec02eef1e 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - build: + success: runs-on: ubuntu-24.04 strategy: From ff2cd0fb6390d775c753733abefab6b81d45eb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 1 Feb 2025 19:13:41 +0100 Subject: [PATCH 0017/2248] Remove duplicated CI triggers There shouldn't be a need to run all CI jobs on all pushes. --- .github/workflows/ci.yml | 1 - .github/workflows/gcc12.yml | 1 - .github/workflows/m68k.yml | 1 - .github/workflows/release.yml | 1 - .github/workflows/stdarch.yml | 1 - 5 files changed, 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 688a9f7d7bf73..bf974f65c1e16 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,6 @@ name: CI on: - - push - pull_request permissions: diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index 0308eec51cdf3..0d49336ea208e 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -1,7 +1,6 @@ name: CI libgccjit 12 on: - - push - pull_request permissions: diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index e031ad59f4b51..af5f084205e52 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -3,7 +3,6 @@ name: m68k CI on: - - push - pull_request permissions: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4367cbccab115..4582cf577fe61 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,6 @@ name: CI with sysroot compiled in release mode on: - - push - pull_request permissions: diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index ea8bec02eef1e..a1df0207d54f6 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -1,7 +1,6 @@ name: stdarch tests with sysroot compiled in release mode on: - - push - pull_request permissions: From befc31c588585db6650d228f50727070e2ccd96b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 1 Feb 2025 12:19:35 -0500 Subject: [PATCH 0018/2248] Move back to a success job so because the required checks only work without a matrix --- .github/workflows/failures.yml | 21 ++++++++++++++++++++- .github/workflows/gcc12.yml | 21 ++++++++++++++++++++- .github/workflows/m68k.yml | 21 ++++++++++++++++++++- .github/workflows/release.yml | 21 ++++++++++++++++++++- .github/workflows/stdarch.yml | 21 ++++++++++++++++++++- 5 files changed, 100 insertions(+), 5 deletions(-) diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index b9f6f9d84f460..ab3e4002e87f6 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - success: + build: runs-on: ubuntu-24.04 strategy: @@ -108,3 +108,22 @@ jobs: echo "Error: 'the compiler unexpectedly panicked' found in output logs. CI Error!!" exit 1 fi + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success_failures: + needs: [build] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index 0308eec51cdf3..33d5d1a52df8e 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -16,7 +16,7 @@ env: GCC_EXEC_PREFIX: /usr/lib/gcc/ jobs: - success: + build: runs-on: ubuntu-24.04 strategy: @@ -85,3 +85,22 @@ jobs: #- name: Run tests #run: | #./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success_gcc12: + needs: [build] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index e031ad59f4b51..a7090338a7f14 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -16,7 +16,7 @@ env: OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu jobs: - success: + build: runs-on: ubuntu-24.04 strategy: @@ -105,3 +105,22 @@ jobs: - name: Run tests run: | ./y.sh test --release --clean --build-sysroot --sysroot-features compiler_builtins/no-f16-f128 ${{ matrix.commands }} + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success_m68k: + needs: [build] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4367cbccab115..7284b7f7398a3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - success: + build: runs-on: ubuntu-24.04 strategy: @@ -82,3 +82,22 @@ jobs: echo "Test is done with LTO enabled, hence inlining should occur across crates" exit 1 fi + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success_release: + needs: [build] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index ea8bec02eef1e..9438e557ecd9e 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - success: + build: runs-on: ubuntu-24.04 strategy: @@ -102,3 +102,22 @@ jobs: # TODO: remove --skip test_mm512_stream_ps when stdarch is updated in rustc. # TODO: remove --skip test_tile_ when it's implemented. STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features --cfg stdarch_intel_sde" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_mm512_stream_ps --skip test_tile_ + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success_stdarch: + needs: [build] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' From ad2be68b490180012d7775a2ae3e0fd8e9cabda4 Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Mon, 27 Jan 2025 19:05:14 +0100 Subject: [PATCH 0019/2248] Make globals always have 2+ chars as suffix As discussed on chat, there currently is the bug where certain suffixes are interpreted by the (m68k) assembler. Example: `move.l #global.w,-44(%fp)` `.w` is interpreted by the assembler as a size hint for `#global`. --- src/context.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index c81c53359fd18..2a33beef63b99 100644 --- a/src/context.rs +++ b/src/context.rs @@ -606,7 +606,10 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { let mut name = String::with_capacity(prefix.len() + 6); name.push_str(prefix); name.push('.'); - name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY)); + // Offset the index by the base so that always at least two characters + // are generated. This avoids cases where the suffix is interpreted as + // size by the assembler (for m68k: .b, .w, .l). + name.push_str(&(idx as u64 + ALPHANUMERIC_ONLY as u64).to_base(ALPHANUMERIC_ONLY)); name } } From 5d12c54b345d6bf6e7d25b904c1b7fbb0287429e Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Mon, 27 Jan 2025 18:49:49 +0100 Subject: [PATCH 0020/2248] Add M68000 entry to arch_to_gcc --- src/gcc_util.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 560aff43d6538..f463ee4061749 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -242,6 +242,7 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> fn arch_to_gcc(name: &str) -> &str { match name { + "M68000" => "68000", "M68020" => "68020", _ => name, } From e0d8fb949cafac87d072e7bb873eeb115fe22706 Mon Sep 17 00:00:00 2001 From: Askar Safin Date: Mon, 3 Feb 2025 06:44:41 +0300 Subject: [PATCH 0021/2248] tree-wide: parallel: Fully removed all `Lrc`, replaced with `Arc` --- src/debuginfo.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 86d3de225f71e..12cbde0ad0d37 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -1,9 +1,9 @@ use std::ops::Range; +use std::sync::Arc; use gccjit::{Location, RValue}; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods}; -use rustc_data_structures::sync::Lrc; use rustc_index::bit_set::DenseBitSet; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::{self, Body, SourceScope}; @@ -172,7 +172,7 @@ fn make_mir_scope<'gcc, 'tcx>( // `lookup_char_pos` return the right information instead. pub struct DebugLoc { /// Information about the original source file. - pub file: Lrc, + pub file: Arc, /// The (1-based) line number. pub line: u32, /// The (1-based) column number. From 4c932ff8379e70893d3cdc835c289547ba3bee26 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 Jan 2025 23:32:44 +0100 Subject: [PATCH 0022/2248] Update repositories URL for repositories moved to `rust-lang` organization --- Readme.md | 4 ++-- build_system/src/clone_gcc.rs | 2 +- doc/add-attribute.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index e92c16ece2f10..d0e4dbba6d355 100644 --- a/Readme.md +++ b/Readme.md @@ -23,7 +23,7 @@ A secondary goal is to check if using the gcc backend will provide any run-time ## Building **This requires a patched libgccjit in order to work. -You need to use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.** +You need to use my [fork of gcc](https://github.com/rust-lang/gcc) which already includes these patches.** ```bash $ cp config.example.toml config.toml @@ -40,7 +40,7 @@ to do a few more things. To build it (most of these instructions come from [here](https://gcc.gnu.org/onlinedocs/jit/internals/index.html), so don't hesitate to take a look there if you encounter an issue): ```bash -$ git clone https://github.com/antoyo/gcc +$ git clone https://github.com/rust-lang/gcc $ sudo apt install flex libmpfr-dev libgmp-dev libmpc3 libmpc-dev $ mkdir gcc-build gcc-install $ cd gcc-build diff --git a/build_system/src/clone_gcc.rs b/build_system/src/clone_gcc.rs index e28ee873eb6be..b49dd47f35219 100644 --- a/build_system/src/clone_gcc.rs +++ b/build_system/src/clone_gcc.rs @@ -61,7 +61,7 @@ pub fn run() -> Result<(), String> { return Ok(()); }; - let result = git_clone("https://github.com/antoyo/gcc", Some(&args.out_path), false)?; + let result = git_clone("https://github.com/rust-lang/gcc", Some(&args.out_path), false)?; if result.ran_clone { let gcc_commit = args.config_info.get_gcc_commit()?; println!("Checking out GCC commit `{}`...", gcc_commit); diff --git a/doc/add-attribute.md b/doc/add-attribute.md index ae3bcc5e2ebe2..267c181952556 100644 --- a/doc/add-attribute.md +++ b/doc/add-attribute.md @@ -14,4 +14,4 @@ Finally, you need to update this repository by calling the relevant API you adde To test it, build `gcc`, run `cargo update -p gccjit` and then you can test the generated output for a given Rust crate. -[gccjit.rs]: https://github.com/antoyo/gccjit.rs +[gccjit.rs]: https://github.com/rust-lang/gccjit.rs From beb24b3301e6f9b831f16ddd542930024ffe8239 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 4 Feb 2025 15:15:28 +0100 Subject: [PATCH 0023/2248] intrinsics: unify rint, roundeven, nearbyint in a single round_ties_even intrinsic --- src/intrinsic/mod.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 48606f5f91c0f..83d0db0fb54a9 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -84,14 +84,11 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::ceilf64 => "ceil", sym::truncf32 => "truncf", sym::truncf64 => "trunc", - sym::rintf32 => "rintf", - sym::rintf64 => "rint", - sym::nearbyintf32 => "nearbyintf", - sym::nearbyintf64 => "nearbyint", + // We match the LLVM backend and lower this to `rint`. + sym::round_ties_even_f32 => "rintf", + sym::round_ties_even_f64 => "rint", sym::roundf32 => "roundf", sym::roundf64 => "round", - sym::roundevenf32 => "roundevenf", - sym::roundevenf64 => "roundeven", sym::abort => "abort", _ => return None, }; From 819ab9b0656e3efbabdf680856d957ec746bc58a Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 2 Nov 2024 17:49:42 -0700 Subject: [PATCH 0024/2248] cg_gcc: Directly use rustc_abi instead of reexports --- src/abi.rs | 6 +++--- src/builder.rs | 2 +- src/consts.rs | 2 +- src/context.rs | 2 +- src/debuginfo.rs | 4 ++-- src/declare.rs | 2 +- src/int.rs | 7 +++---- src/intrinsic/mod.rs | 14 +++++++------- src/intrinsic/simd.rs | 2 +- src/type_.rs | 2 +- src/type_of.rs | 7 ++++--- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 14fc23593f0e6..d94fc5525288d 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::config; -use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; +use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; use crate::builder::Builder; use crate::context::CodegenCx; @@ -132,10 +132,10 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if cx.sess().opts.optimize == config::OptLevel::No { return ty; } - if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) { + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NoAlias) { ty = ty.make_restrict() } - if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NonNull) { + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { non_null_args.push(arg_index as i32 + 1); } ty diff --git a/src/builder.rs b/src/builder.rs index 89e5cf1b8c6b6..bba19d0625832 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -29,7 +29,7 @@ use rustc_middle::ty::layout::{ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_span::Span; use rustc_span::def_id::DefId; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, WasmCAbi, X86Abi}; use crate::common::{SignType, TypeReflection, type_is_pointer}; diff --git a/src/consts.rs b/src/consts.rs index 1631ecfeecf3f..fb0ca31c54334 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,6 +1,7 @@ #[cfg(feature = "master")] use gccjit::{FnAttribute, VarAttribute, Visibility}; use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type}; +use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, }; @@ -14,7 +15,6 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; -use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange}; use crate::base; use crate::context::CodegenCx; diff --git a/src/context.rs b/src/context.rs index 570ef938dc44e..1e1f577bb3a15 100644 --- a/src/context.rs +++ b/src/context.rs @@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell}; use gccjit::{ Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, Location, RValue, Type, }; +use rustc_abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods}; @@ -18,7 +19,6 @@ use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::source_map::respan; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_target::spec::{ HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi, }; diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 86d3de225f71e..3f6fdea9fb8cf 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -1,6 +1,7 @@ use std::ops::Range; use gccjit::{Location, RValue}; +use rustc_abi::Size; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods}; use rustc_data_structures::sync::Lrc; @@ -10,8 +11,7 @@ use rustc_middle::mir::{self, Body, SourceScope}; use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty}; use rustc_session::config::DebugInfo; use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol}; -use rustc_target::abi::Size; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use crate::builder::Builder; use crate::context::CodegenCx; diff --git a/src/declare.rs b/src/declare.rs index 442488b7fd650..7cdbe3c0c6290 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -4,7 +4,7 @@ use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type}; use rustc_codegen_ssa::traits::BaseTypeCodegenMethods; use rustc_middle::ty::Ty; use rustc_span::Symbol; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use crate::abi::{FnAbiGcc, FnAbiGccExt}; use crate::context::CodegenCx; diff --git a/src/int.rs b/src/int.rs index fe6a65bed03b0..4a1db8d662a9f 100644 --- a/src/int.rs +++ b/src/int.rs @@ -3,12 +3,11 @@ //! 128-bit integers on 32-bit platforms and thus require to be handled manually. use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp}; +use rustc_abi::{Endian, ExternAbi}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp}; use rustc_middle::ty::{self, Ty}; -use rustc_target::abi::Endian; -use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}; -use rustc_target::spec; +use rustc_target::callconv::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}; use crate::builder::{Builder, ToGccComp}; use crate::common::{SignType, TypeReflection}; @@ -401,7 +400,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { conv: Conv::C, can_unwind: false, }; - fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C { unwind: false }).unwrap(); + fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }).unwrap(); let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 48606f5f91c0f..a1123fafe2f30 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -7,6 +7,9 @@ use std::iter; #[cfg(feature = "master")] use gccjit::FunctionType; use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp}; +#[cfg(feature = "master")] +use rustc_abi::ExternAbi; +use rustc_abi::HasDataLayout; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -25,11 +28,8 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{Span, Symbol, sym}; -use rustc_target::abi::HasDataLayout; -use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; use rustc_target::spec::PanicStrategy; -#[cfg(feature = "master")] -use rustc_target::spec::abi::Abi; #[cfg(feature = "master")] use crate::abi::FnAbiGccExt; @@ -1238,7 +1238,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( tcx.types.unit, false, rustc_hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )), ); // `unsafe fn(*mut i8, *mut i8) -> ()` @@ -1249,7 +1249,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( tcx.types.unit, false, rustc_hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )), ); // `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32` @@ -1258,7 +1258,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( tcx.types.i32, false, rustc_hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )); let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen); cx.rust_try_fn.set(Some(rust_try)); diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 1be452e5d05de..12a7dab155b47 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -3,6 +3,7 @@ use std::iter::FromIterator; use gccjit::{BinaryOp, RValue, ToRValue, Type}; #[cfg(feature = "master")] use gccjit::{ComparisonOp, UnaryOp}; +use rustc_abi::{Align, Size}; use rustc_codegen_ssa::base::compare_simd_types; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; #[cfg(feature = "master")] @@ -17,7 +18,6 @@ use rustc_middle::mir::BinOp; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, Symbol, sym}; -use rustc_target::abi::{Align, Size}; use crate::builder::Builder; #[cfg(not(feature = "master"))] diff --git a/src/type_.rs b/src/type_.rs index 4ea5544721dea..cb08723431a9a 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -4,13 +4,13 @@ use std::convert::TryInto; #[cfg(feature = "master")] use gccjit::CType; use gccjit::{RValue, Struct, Type}; +use rustc_abi::{AddressSpace, Align, Integer, Size}; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, DerivedTypeCodegenMethods, TypeMembershipCodegenMethods, }; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, ty}; -use rustc_target::abi::{AddressSpace, Align, Integer, Size}; use crate::common::TypeReflection; use crate::context::CodegenCx; diff --git a/src/type_of.rs b/src/type_of.rs index 0efdf36da485e..8b8b54753e7fd 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -3,7 +3,9 @@ use std::fmt::Write; use gccjit::{Struct, Type}; use rustc_abi as abi; use rustc_abi::Primitive::*; -use rustc_abi::{BackendRepr, FieldsShape, Integer, PointeeInfo, Size, Variants}; +use rustc_abi::{ + BackendRepr, FieldsShape, Integer, PointeeInfo, Reg, Size, TyAbiInterface, Variants, +}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods, }; @@ -11,8 +13,7 @@ use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; -use rustc_target::abi::TyAbiInterface; -use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; +use rustc_target::callconv::{CastTarget, FnAbi}; use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::context::CodegenCx; From 2214ba9f1a9a3d88098ae34912d5c646b57f59a6 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 5 Feb 2025 12:16:57 -0500 Subject: [PATCH 0025/2248] Run the CI on push on the master branch --- .github/workflows/ci.yml | 5 ++++- .github/workflows/failures.yml | 5 ++++- .github/workflows/gcc12.yml | 5 ++++- .github/workflows/m68k.yml | 5 ++++- .github/workflows/release.yml | 5 ++++- .github/workflows/stdarch.yml | 5 ++++- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf974f65c1e16..ef024258ffc86 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,10 @@ name: CI on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index ab3e4002e87f6..bc42eb1468ea2 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -2,7 +2,10 @@ name: Failures on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index d6b7e5a2a13a5..da9a1506855c3 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -1,7 +1,10 @@ name: CI libgccjit 12 on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index 90fa5acc3fb03..21731f7087e2c 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -3,7 +3,10 @@ name: m68k CI on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2f6e3b4753191..47a40286554e4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,10 @@ name: CI with sysroot compiled in release mode on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 350e099d88701..4b9f48e7b1835 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -1,7 +1,10 @@ name: stdarch tests with sysroot compiled in release mode on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read From 09d907627b6f86fae8cc926a353a44bd723ccf59 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 7 Feb 2025 16:48:39 +0100 Subject: [PATCH 0026/2248] fix backslashes in path used for `asm_tests` --- build_system/src/test.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index efd7b2b8df3a1..096b4c4a71549 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -542,20 +542,21 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string()); - let extra = - if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" }; - - let rustc_args = &format!( - r#"-Zpanic-abort-tests \ - -Zcodegen-backend="{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}" \ - --sysroot "{sysroot_dir}" -Cpanic=abort{extra}"#, + let codegen_backend_path = format!( + "{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}", pwd = std::env::current_dir() .map_err(|error| format!("`current_dir` failed: {:?}", error))? .display(), channel = args.config_info.channel.as_str(), dylib_ext = args.config_info.dylib_ext, - sysroot_dir = args.config_info.sysroot_path, - extra = extra, + ); + + let extra = + if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" }; + + let rustc_args = format!( + "-Zpanic-abort-tests -Zcodegen-backend={codegen_backend_path} --sysroot {} -Cpanic=abort{extra}", + args.config_info.sysroot_path ); run_command_with_env( From 21b60aad987f5e61658901675cd64a5736ee5eef Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 7 Feb 2025 14:47:21 +0000 Subject: [PATCH 0027/2248] Remove Linkage::Private This is the same as Linkage::Internal except that it doesn't emit any symbol. Some backends may not support it and it isn't all that useful anyway. --- src/base.rs | 2 -- src/mono_item.rs | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/base.rs b/src/base.rs index c9701fb9885c1..f2fc098004470 100644 --- a/src/base.rs +++ b/src/base.rs @@ -51,7 +51,6 @@ pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { Linkage::WeakODR => unimplemented!(), Linkage::Appending => unimplemented!(), Linkage::Internal => GlobalKind::Internal, - Linkage::Private => GlobalKind::Internal, Linkage::ExternalWeak => GlobalKind::Imported, // TODO(antoyo): should be weak linkage. Linkage::Common => unimplemented!(), } @@ -68,7 +67,6 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { Linkage::WeakODR => unimplemented!(), Linkage::Appending => unimplemented!(), Linkage::Internal => FunctionType::Internal, - Linkage::Private => FunctionType::Internal, Linkage::ExternalWeak => unimplemented!(), Linkage::Common => unimplemented!(), } diff --git a/src/mono_item.rs b/src/mono_item.rs index 239902df7f048..a2df7b2596fcf 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -61,10 +61,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // compiler-rt, then we want to implicitly compile everything with hidden // visibility as we're going to link this object all over the place but // don't want the symbols to get exported. - if linkage != Linkage::Internal - && linkage != Linkage::Private - && self.tcx.is_compiler_builtins(LOCAL_CRATE) - { + if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { #[cfg(feature = "master")] decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); } else { From a90648d25533cd67d978d611dcddeb6f4b6caa39 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 7 Feb 2025 14:52:07 +0000 Subject: [PATCH 0028/2248] Remove Linkage::Appending It can only be used for certain LLVM internal variables like llvm.global_ctors which users are not allowed to define. --- src/base.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/base.rs b/src/base.rs index f2fc098004470..962f4b161d788 100644 --- a/src/base.rs +++ b/src/base.rs @@ -49,7 +49,6 @@ pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { Linkage::LinkOnceODR => unimplemented!(), Linkage::WeakAny => unimplemented!(), Linkage::WeakODR => unimplemented!(), - Linkage::Appending => unimplemented!(), Linkage::Internal => GlobalKind::Internal, Linkage::ExternalWeak => GlobalKind::Imported, // TODO(antoyo): should be weak linkage. Linkage::Common => unimplemented!(), @@ -65,7 +64,6 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { Linkage::LinkOnceODR => unimplemented!(), Linkage::WeakAny => FunctionType::Exported, // FIXME(antoyo): should be similar to linkonce. Linkage::WeakODR => unimplemented!(), - Linkage::Appending => unimplemented!(), Linkage::Internal => FunctionType::Internal, Linkage::ExternalWeak => unimplemented!(), Linkage::Common => unimplemented!(), From 83f7576a770d394c79c8ef28e1687e3ad0f747d9 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 4 Feb 2025 22:56:30 -0800 Subject: [PATCH 0029/2248] compiler: remove reexports from rustc_target::callconv --- src/abi.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/abi.rs b/src/abi.rs index d94fc5525288d..717baebcd8cd6 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -1,6 +1,7 @@ #[cfg(feature = "master")] use gccjit::FnAttribute; use gccjit::{ToLValue, ToRValue, Type}; +use rustc_abi::{Reg, RegKind}; use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeCodegenMethods}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; @@ -8,7 +9,7 @@ use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::config; -use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; +use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode}; use crate::builder::Builder; use crate::context::CodegenCx; From 180f350fc67eed3142fdc7b2e7e6955e4922642e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 8 Feb 2025 22:12:13 +0000 Subject: [PATCH 0030/2248] Rustfmt --- src/builder.rs | 21 +- src/intrinsic/llvm.rs | 22 +- src/intrinsic/simd.rs | 466 +++++++++++++++++++++--------------------- 3 files changed, 259 insertions(+), 250 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index bba19d0625832..1c3d6cc899a63 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -155,14 +155,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // NOTE: not sure why, but we have the wrong type here. let int_type = compare_exchange.get_param(2).to_rvalue().get_type(); let src = self.context.new_bitcast(self.location, src, int_type); - self.context.new_call(self.location, compare_exchange, &[ - dst, - expected, - src, - weak, - order, - failure_order, - ]) + self.context.new_call( + self.location, + compare_exchange, + &[dst, expected, src, weak, order, failure_order], + ) } pub fn assign(&self, lvalue: LValue<'gcc>, value: RValue<'gcc>) { @@ -1076,9 +1073,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let align = dest.val.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); cg_elem.val.store(self, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align)); - let next = self.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[ - self.const_usize(1), - ]); + let next = self.inbounds_gep( + self.backend_type(cg_elem.layout), + current.to_rvalue(), + &[self.const_usize(1)], + ); self.llbb().add_assignment(self.location, current, next); self.br(header_bb); diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 231307def291f..2d731f88d7d36 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -687,11 +687,12 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( let field2 = builder.context.new_field(None, args[1].get_type(), "carryResult"); let struct_type = builder.context.new_struct_type(None, "addcarryResult", &[field1, field2]); - return_value = - builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[ - return_value, - last_arg.dereference(None).to_rvalue(), - ]); + return_value = builder.context.new_struct_constructor( + None, + struct_type.as_type(), + None, + &[return_value, last_arg.dereference(None).to_rvalue()], + ); } } "__builtin_ia32_stmxcsr" => { @@ -716,11 +717,12 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( let field2 = builder.context.new_field(None, return_value.get_type(), "success"); let struct_type = builder.context.new_struct_type(None, "rdrand_result", &[field1, field2]); - return_value = - builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[ - random_number, - success_variable.to_rvalue(), - ]); + return_value = builder.context.new_struct_constructor( + None, + struct_type.as_type(), + None, + &[random_number, success_variable.to_rvalue()], + ); } "fma" => { let f16_type = builder.context.new_c_type(CType::Float16); diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 12a7dab155b47..84cd5b002fbb6 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -62,11 +62,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { - require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { - span, - name, - ty: arg_tys[1] - }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let expected_int_bits = (len.max(8) - 1).next_power_of_two(); @@ -140,14 +139,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType { - span, - name, - in_len, - in_ty, - ret_ty, - out_len - }); + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); require!( bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, InvalidMonomorphization::ReturnIntegerType { span, name, ret_ty, out_ty } @@ -269,23 +271,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let lo_nibble = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &lo_nibble_elements); - let mask = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &vec![ - bx.context - .new_rvalue_from_int( - bx.u8_type, 0x0f - ); - byte_vector_type_size - as _ - ]); - - let four_vec = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &vec![ - bx.context - .new_rvalue_from_int( - bx.u8_type, 4 - ); - byte_vector_type_size - as _ - ]); + let mask = bx.context.new_rvalue_from_vector( + None, + long_byte_vector_type, + &vec![bx.context.new_rvalue_from_int(bx.u8_type, 0x0f); byte_vector_type_size as _], + ); + + let four_vec = bx.context.new_rvalue_from_vector( + None, + long_byte_vector_type, + &vec![bx.context.new_rvalue_from_int(bx.u8_type, 4); byte_vector_type_size as _], + ); // Step 2: Byte-swap the input. let swapped = simd_bswap(bx, args[0].immediate()); @@ -388,21 +384,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); - require!(out_len == n, InvalidMonomorphization::ReturnLength { - span, - name, - in_len: n, - ret_ty, - out_len - }); - require!(in_elem == out_ty, InvalidMonomorphization::ReturnElement { - span, - name, - in_elem, - in_ty, - ret_ty, - out_ty - }); + require!( + out_len == n, + InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len } + ); + require!( + in_elem == out_ty, + InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty } + ); let vector = args[2].immediate(); @@ -411,13 +400,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( #[cfg(feature = "master")] if name == sym::simd_insert { - require!(in_elem == arg_tys[2], InvalidMonomorphization::InsertedType { - span, - name, - in_elem, - in_ty, - out_ty: arg_tys[2] - }); + require!( + in_elem == arg_tys[2], + InvalidMonomorphization::InsertedType { + span, + name, + in_elem, + in_ty, + out_ty: arg_tys[2] + } + ); let vector = args[0].immediate(); let index = args[1].immediate(); let value = args[2].immediate(); @@ -431,13 +423,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( #[cfg(feature = "master")] if name == sym::simd_extract { - require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType { - span, - name, - in_elem, - in_ty, - ret_ty - }); + require!( + ret_ty == in_elem, + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } + ); let vector = args[0].immediate(); return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue()); } @@ -445,18 +434,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_select { let m_elem_ty = in_elem; let m_len = in_len; - require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { - span, - name, - ty: arg_tys[1] - }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); - require!(m_len == v_len, InvalidMonomorphization::MismatchedLengths { - span, - name, - m_len, - v_len - }); + require!( + m_len == v_len, + InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len } + ); match *m_elem_ty.kind() { ty::Int(_) => {} _ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }), @@ -468,25 +454,27 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType { - span, - name, - in_len, - in_ty, - ret_ty, - out_len - }); + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); match *in_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); - require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { - span, - name, - ty: in_elem - }); + require!( + metadata.is_unit(), + InvalidMonomorphization::CastWidePointer { span, name, ty: in_elem } + ); } _ => { return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem }) @@ -497,11 +485,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); - require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { - span, - name, - ty: out_elem - }); + require!( + metadata.is_unit(), + InvalidMonomorphization::CastWidePointer { span, name, ty: out_elem } + ); } _ => { return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem }) @@ -524,14 +511,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType { - span, - name, - in_len, - in_ty, - ret_ty, - out_len - }); + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); match *in_elem.kind() { ty::RawPtr(_, _) => {} @@ -560,14 +550,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType { - span, - name, - in_len, - in_ty, - ret_ty, - out_len - }); + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); match *in_elem.kind() { ty::Uint(ty::UintTy::Usize) => {} @@ -596,14 +589,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_cast || name == sym::simd_as { require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType { - span, - name, - in_len, - in_ty, - ret_ty, - out_len - }); + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); // casting cares about nominal type, not just structural type if in_elem == out_elem { return Ok(args[0].immediate()); @@ -629,14 +625,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match (in_style, out_style) { (Style::Unsupported, Style::Unsupported) => { - require!(false, InvalidMonomorphization::UnsupportedCast { - span, - name, - in_ty, - in_elem, - ret_ty, - out_elem - }); + require!( + false, + InvalidMonomorphization::UnsupportedCast { + span, + name, + in_ty, + in_elem, + ret_ty, + out_elem + } + ); } _ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)), } @@ -914,45 +913,47 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // All types must be simd vector types require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); - require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { - span, - name, - ty: arg_tys[1] - }); - require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { - span, - name, - ty: arg_tys[2] - }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); // Of the same length: let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::SecondArgumentLength { - span, - name, - in_len, - in_ty, - arg_ty: arg_tys[1], - out_len - }); - require!(in_len == out_len2, InvalidMonomorphization::ThirdArgumentLength { - span, - name, - in_len, - in_ty, - arg_ty: arg_tys[2], - out_len: out_len2 - }); + require!( + in_len == out_len, + InvalidMonomorphization::SecondArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[1], + out_len + } + ); + require!( + in_len == out_len2, + InvalidMonomorphization::ThirdArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[2], + out_len: out_len2 + } + ); // The return type must match the first argument type - require!(ret_ty == in_ty, InvalidMonomorphization::ExpectedReturnType { - span, - name, - in_ty, - ret_ty - }); + require!( + ret_ty == in_ty, + InvalidMonomorphization::ExpectedReturnType { span, name, in_ty, ret_ty } + ); // This counts how many pointers fn ptr_count(t: Ty<'_>) -> usize { @@ -979,15 +980,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( (ptr_count(element_ty1), non_ptr(element_ty1)) } _ => { - require!(false, InvalidMonomorphization::ExpectedElementType { - span, - name, - expected_element: element_ty1, - second_arg: arg_tys[1], - in_elem, - in_ty, - mutability: ExpectedPointerMutability::Not, - }); + require!( + false, + InvalidMonomorphization::ExpectedElementType { + span, + name, + expected_element: element_ty1, + second_arg: arg_tys[1], + in_elem, + in_ty, + mutability: ExpectedPointerMutability::Not, + } + ); unreachable!(); } }; @@ -1000,12 +1004,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match *element_ty2.kind() { ty::Int(_) => (), _ => { - require!(false, InvalidMonomorphization::ThirdArgElementType { - span, - name, - expected_element: element_ty2, - third_arg: arg_tys[2] - }); + require!( + false, + InvalidMonomorphization::ThirdArgElementType { + span, + name, + expected_element: element_ty2, + third_arg: arg_tys[2] + } + ); } } @@ -1029,36 +1036,40 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // All types must be simd vector types require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); - require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { - span, - name, - ty: arg_tys[1] - }); - require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { - span, - name, - ty: arg_tys[2] - }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); // Of the same length: let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx()); - require!(in_len == element_len1, InvalidMonomorphization::SecondArgumentLength { - span, - name, - in_len, - in_ty, - arg_ty: arg_tys[1], - out_len: element_len1 - }); - require!(in_len == element_len2, InvalidMonomorphization::ThirdArgumentLength { - span, - name, - in_len, - in_ty, - arg_ty: arg_tys[2], - out_len: element_len2 - }); + require!( + in_len == element_len1, + InvalidMonomorphization::SecondArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[1], + out_len: element_len1 + } + ); + require!( + in_len == element_len2, + InvalidMonomorphization::ThirdArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[2], + out_len: element_len2 + } + ); // This counts how many pointers fn ptr_count(t: Ty<'_>) -> usize { @@ -1086,15 +1097,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( (ptr_count(element_ty1), non_ptr(element_ty1)) } _ => { - require!(false, InvalidMonomorphization::ExpectedElementType { - span, - name, - expected_element: element_ty1, - second_arg: arg_tys[1], - in_elem, - in_ty, - mutability: ExpectedPointerMutability::Mut, - }); + require!( + false, + InvalidMonomorphization::ExpectedElementType { + span, + name, + expected_element: element_ty1, + second_arg: arg_tys[1], + in_elem, + in_ty, + mutability: ExpectedPointerMutability::Mut, + } + ); unreachable!(); } }; @@ -1106,12 +1120,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match *element_ty2.kind() { ty::Int(_) => (), _ => { - require!(false, InvalidMonomorphization::ThirdArgElementType { - span, - name, - expected_element: element_ty2, - third_arg: arg_tys[2] - }); + require!( + false, + InvalidMonomorphization::ThirdArgElementType { + span, + name, + expected_element: element_ty2, + third_arg: arg_tys[2] + } + ); } } @@ -1278,13 +1295,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ($name:ident : $vec_op:expr, $float_reduce:ident, $ordered:expr, $op:ident, $identity:expr) => { if name == sym::$name { - require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType { - span, - name, - in_elem, - in_ty, - ret_ty - }); + require!( + ret_ty == in_elem, + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } + ); return match *in_elem.kind() { ty::Int(_) | ty::Uint(_) => { let r = bx.vector_reduce_op(args[0].immediate(), $vec_op); @@ -1350,13 +1364,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( macro_rules! minmax_red { ($name:ident: $int_red:ident, $float_red:ident) => { if name == sym::$name { - require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType { - span, - name, - in_elem, - in_ty, - ret_ty - }); + require!( + ret_ty == in_elem, + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } + ); return match *in_elem.kind() { ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())), ty::Float(_) => Ok(bx.$float_red(args[0].immediate())), @@ -1380,13 +1391,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ($name:ident : $op:expr, $boolean:expr) => { if name == sym::$name { let input = if !$boolean { - require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType { - span, - name, - in_elem, - in_ty, - ret_ty - }); + require!( + ret_ty == in_elem, + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } + ); args[0].immediate() } else { match *in_elem.kind() { From cb499a29a8d26cf58e4b26ea70fd49c9486e7528 Mon Sep 17 00:00:00 2001 From: c8ef Date: Tue, 11 Feb 2025 03:17:38 +0800 Subject: [PATCH 0031/2248] remove some intrinsics (#625) --- src/builder.rs | 10 +--------- src/intrinsic/llvm.rs | 42 +----------------------------------------- 2 files changed, 2 insertions(+), 50 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 89e5cf1b8c6b6..8268819c5faed 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -371,16 +371,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let previous_arg_count = args.len(); let orig_args = args; let args = { - let function_address_names = self.function_address_names.borrow(); - let original_function_name = function_address_names.get(&func_ptr); func_ptr = llvm::adjust_function(self.context, &func_name, func_ptr, args); - llvm::adjust_intrinsic_arguments( - self, - gcc_func, - args.into(), - &func_name, - original_function_name, - ) + llvm::adjust_intrinsic_arguments(self, gcc_func, args.into(), &func_name) }; let args_adjusted = args.len() != previous_arg_count; let args = self.check_ptr_call("call", func_ptr, &args); diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 231307def291f..afa434ce74e39 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use gccjit::{CType, Context, Function, FunctionPtrType, RValue, ToRValue, UnaryOp}; +use gccjit::{CType, Context, Function, FunctionPtrType, RValue, ToRValue}; use rustc_codegen_ssa::traits::BuilderMethods; use crate::builder::Builder; @@ -43,7 +43,6 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( gcc_func: FunctionPtrType<'gcc>, mut args: Cow<'b, [RValue<'gcc>]>, func_name: &str, - original_function_name: Option<&String>, ) -> Cow<'b, [RValue<'gcc>]> { // TODO: this might not be a good way to workaround the missing tile builtins. if func_name == "__builtin_trap" { @@ -541,33 +540,6 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let c = builder.context.new_rvalue_from_vector(None, arg3_type, &[new_args[2]; 2]); args = vec![a, b, c, new_args[3]].into(); } - "__builtin_ia32_vfmaddsubpd256" - | "__builtin_ia32_vfmaddsubps" - | "__builtin_ia32_vfmaddsubps256" - | "__builtin_ia32_vfmaddsubpd" => { - if let Some(original_function_name) = original_function_name { - match &**original_function_name { - "llvm.x86.fma.vfmsubadd.pd.256" - | "llvm.x86.fma.vfmsubadd.ps" - | "llvm.x86.fma.vfmsubadd.ps.256" - | "llvm.x86.fma.vfmsubadd.pd" => { - // NOTE: since both llvm.x86.fma.vfmsubadd.ps and llvm.x86.fma.vfmaddsub.ps maps to - // __builtin_ia32_vfmaddsubps, only add minus if this comes from a - // subadd LLVM intrinsic, e.g. _mm256_fmsubadd_pd. - let mut new_args = args.to_vec(); - let arg3 = &mut new_args[2]; - *arg3 = builder.context.new_unary_op( - None, - UnaryOp::Minus, - arg3.get_type(), - *arg3, - ); - args = new_args.into(); - } - _ => (), - } - } - } "__builtin_ia32_ldmxcsr" => { // The builtin __builtin_ia32_ldmxcsr takes an integer value while llvm.x86.sse.ldmxcsr takes a pointer, // so dereference the pointer. @@ -913,16 +885,6 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.ctlz.v4i64" => "__builtin_ia32_vplzcntq_256_mask", "llvm.ctlz.v2i64" => "__builtin_ia32_vplzcntq_128_mask", "llvm.ctpop.v32i16" => "__builtin_ia32_vpopcountw_v32hi", - "llvm.x86.fma.vfmsub.sd" => "__builtin_ia32_vfmsubsd3", - "llvm.x86.fma.vfmsub.ss" => "__builtin_ia32_vfmsubss3", - "llvm.x86.fma.vfmsubadd.pd" => "__builtin_ia32_vfmaddsubpd", - "llvm.x86.fma.vfmsubadd.pd.256" => "__builtin_ia32_vfmaddsubpd256", - "llvm.x86.fma.vfmsubadd.ps" => "__builtin_ia32_vfmaddsubps", - "llvm.x86.fma.vfmsubadd.ps.256" => "__builtin_ia32_vfmaddsubps256", - "llvm.x86.fma.vfnmadd.sd" => "__builtin_ia32_vfnmaddsd3", - "llvm.x86.fma.vfnmadd.ss" => "__builtin_ia32_vfnmaddss3", - "llvm.x86.fma.vfnmsub.sd" => "__builtin_ia32_vfnmsubsd3", - "llvm.x86.fma.vfnmsub.ss" => "__builtin_ia32_vfnmsubss3", "llvm.x86.avx512.conflict.d.512" => "__builtin_ia32_vpconflictsi_512_mask", "llvm.x86.avx512.conflict.d.256" => "__builtin_ia32_vpconflictsi_256_mask", "llvm.x86.avx512.conflict.d.128" => "__builtin_ia32_vpconflictsi_128_mask", @@ -1000,8 +962,6 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.fshr.v32i16" => "__builtin_ia32_vpshrdv_v32hi", "llvm.fshr.v16i16" => "__builtin_ia32_vpshrdv_v16hi", "llvm.fshr.v8i16" => "__builtin_ia32_vpshrdv_v8hi", - "llvm.x86.fma.vfmadd.sd" => "__builtin_ia32_vfmaddsd3", - "llvm.x86.fma.vfmadd.ss" => "__builtin_ia32_vfmaddss3", "llvm.x86.rdrand.64" => "__builtin_ia32_rdrand64_step", // The above doc points to unknown builtins for the following, so override them: From 65da92e77c60a7144145b02719272b2c99419705 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 10 Feb 2025 11:19:02 -0800 Subject: [PATCH 0032/2248] cg_gcc: stop caring about compiling for unknown targets --- src/int.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/int.rs b/src/int.rs index 4a1db8d662a9f..f3552d9b12fcb 100644 --- a/src/int.rs +++ b/src/int.rs @@ -400,7 +400,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { conv: Conv::C, can_unwind: false, }; - fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }).unwrap(); + fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }); let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); From e0175f8b8b183b412dcf2f1aad827575a57df63b Mon Sep 17 00:00:00 2001 From: blyxyas Date: Mon, 10 Feb 2025 20:58:27 +0100 Subject: [PATCH 0033/2248] Document how to benchmark with lintcheck --perf Introducing a new chapter to the book, known as "Benchmarking Clippy". It explains the benchmarking capabilities of lintcheck --perf and gives a concrete example on how benchmark and compare a PR with master --- book/src/SUMMARY.md | 1 + .../infrastructure/benchmarking.md | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 book/src/development/infrastructure/benchmarking.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 19328fdd3cd47..39fe7358ed87a 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -30,6 +30,7 @@ - [Updating the Changelog](development/infrastructure/changelog_update.md) - [Release a New Version](development/infrastructure/release.md) - [The Clippy Book](development/infrastructure/book.md) + - [Benchmarking Clippy](development/infrastructure/benchmarking.md) - [Proposals](development/proposals/README.md) - [Roadmap 2021](development/proposals/roadmap-2021.md) - [Syntax Tree Patterns](development/proposals/syntax-tree-patterns.md) diff --git a/book/src/development/infrastructure/benchmarking.md b/book/src/development/infrastructure/benchmarking.md new file mode 100644 index 0000000000000..0c5ecfc76279f --- /dev/null +++ b/book/src/development/infrastructure/benchmarking.md @@ -0,0 +1,55 @@ +# Benchmarking Clippy + +Benchmarking Clippy is similar to using our Lintcheck tool, in fact, it even +uses the same tool! Just by adding a `--perf` flag it will transform Lintcheck +into a very simple but powerful benchmarking tool! + +It requires having the [`perf` tool][perf] installed, as `perf` is what's actually +profiling Clippy under the hood. + +The lintcheck `--perf` tool generates a series of `perf.data` in the +`target/lintcheck/sources/-` directories. Each `perf.data` +corresponds to the package which is contained. + +Lintcheck uses the `-g` flag, meaning that you can get stack traces for richer +analysis, including with tools such as [flamegraph][flamegraph-perf] +(or [`flamegraph-rs`][flamegraph-rs]). + +Currently, we only measure instruction count, as it's the most reproducible metric +and rustc-perf also considers it the main number to focus on. + +## Benchmarking a PR + +Having a benchmarking tool directly implemented into lintcheck gives us the +ability to benchmark any given PR just by making a before and after + +Here's the way you can get into any PR, benchmark it, and then benchmark +`master`. + +The first `perf.data` will not have any numbers appended, but any subsequent +benchmark will be written to `perf.data.number` with a number growing for 0. +All benchmarks are compressed so that you can + +```bash +git fetch upstream pull//head: +git switch BRANCHNAME + +# Bench +cargo lintcheck --perf + +# Get last common commit, checkout that +LAST_COMMIT=$(git log BRANCHNAME..master --oneline | tail -1 | cut -c 1-11) +git switch -c temporary $LAST_COMMIT + +# We're now on master + +# Bench +cargo lintcheck --perf +perf diff ./target/lintcheck/sources/CRATE/perf.data ./target/lintcheck/sources/CRATE/perf.data.0 +``` + + +[perf]: https://perfwiki.github.io/main/ +[flamegraph-perf]: https://github.com/brendangregg/FlameGraph +[flamegraph-rs]: https://github.com/flamegraph-rs/flamegraph +[rustc-perf]: \ No newline at end of file From 0ee39a20150da33524df4d6471bc65b76e33816d Mon Sep 17 00:00:00 2001 From: blyxyas Date: Mon, 10 Feb 2025 23:29:19 +0100 Subject: [PATCH 0034/2248] Several improvements on lintcheck perf (desc.) - Now lintcheck perf deletes target directory after benchmarking, benchmarking with a cache isn't very useful or telling of any precise outcome. - Support for benchmarking several times without having to do a cargo clean. Now we can benchmark a PR and master (or a single change in the same commit) without having to move the perf.data files into an external directory. - Compress perf.data to allow for allowing multiple stacks and occupy much less space --- lintcheck/src/main.rs | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs index 8d0d41ab9450f..ab86f6ad6f917 100644 --- a/lintcheck/src/main.rs +++ b/lintcheck/src/main.rs @@ -120,14 +120,16 @@ impl Crate { if config.perf { cmd = Command::new("perf"); + let perf_data_filename = get_perf_data_filename(&self.path); cmd.args(&[ "record", "-e", "instructions", // Only count instructions "-g", // Enable call-graph, useful for flamegraphs and produces richer reports "--quiet", // Do not tamper with lintcheck's normal output + "--compression-level=22", "-o", - "perf.data", + &perf_data_filename, "--", "cargo", ]); @@ -165,7 +167,7 @@ impl Crate { return Vec::new(); } - if !config.fix { + if !config.fix && !config.perf { cmd.arg("--message-format=json"); } @@ -203,6 +205,11 @@ impl Crate { return Vec::new(); } + // We don't want to keep target directories if benchmarking + if config.perf { + let _ = fs::remove_dir_all(&shared_target_dir); + } + // get all clippy warnings and ICEs let mut entries: Vec = Message::parse_stream(stdout.as_bytes()) .filter_map(|msg| match msg { @@ -441,6 +448,35 @@ fn lintcheck(config: LintcheckConfig) { fs::write(&config.lintcheck_results_path, text).unwrap(); } +/// Traverse a directory looking for `perf.data.` files, and adds one +/// to the most recent of those files, returning the new most recent `perf.data` +/// file name. +fn get_perf_data_filename(source_path: &Path) -> String { + if source_path.join("perf.data").exists() { + let mut max_number = 0; + fs::read_dir(source_path) + .unwrap() + .filter_map(Result::ok) + .filter(|path| { + path.file_name() + .as_os_str() + .to_string_lossy() // We don't care about data loss, as we're checking for equality + .starts_with("perf.data") + }) + .for_each(|path| { + let file_name = path.file_name(); + let file_name = file_name.as_os_str().to_str().unwrap().split('.').next_back().unwrap(); + if let Ok(parsed_file_name) = file_name.parse::() { + if parsed_file_name >= max_number { + max_number = parsed_file_name + 1; + } + } + }); + return format!("perf.data.{max_number}"); + } + String::from("perf.data") +} + /// Returns the path to the Clippy project directory #[must_use] fn clippy_project_root() -> &'static Path { From 4035fc2b72e51534a573169accecbcc978f20238 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Mon, 10 Feb 2025 23:50:15 +0100 Subject: [PATCH 0035/2248] Follow remark guidelines --- book/src/development/infrastructure/benchmarking.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/development/infrastructure/benchmarking.md b/book/src/development/infrastructure/benchmarking.md index 0c5ecfc76279f..a3ebce922f6c9 100644 --- a/book/src/development/infrastructure/benchmarking.md +++ b/book/src/development/infrastructure/benchmarking.md @@ -16,7 +16,7 @@ analysis, including with tools such as [flamegraph][flamegraph-perf] (or [`flamegraph-rs`][flamegraph-rs]). Currently, we only measure instruction count, as it's the most reproducible metric -and rustc-perf also considers it the main number to focus on. +and [rustc-perf][rustc-perf] also considers it the main number to focus on. ## Benchmarking a PR @@ -52,4 +52,4 @@ perf diff ./target/lintcheck/sources/CRATE/perf.data ./target/lintcheck/sources/ [perf]: https://perfwiki.github.io/main/ [flamegraph-perf]: https://github.com/brendangregg/FlameGraph [flamegraph-rs]: https://github.com/flamegraph-rs/flamegraph -[rustc-perf]: \ No newline at end of file +[rustc-perf]: https://github.com/rust-lang/rustc-perf From d7f2227e63c9f496837530f338fc864532907704 Mon Sep 17 00:00:00 2001 From: Askar Safin Date: Tue, 11 Feb 2025 09:47:13 +0300 Subject: [PATCH 0036/2248] compiler/rustc_codegen_gcc/src/back/lto.rs: delete "unsafe impl Sync/Send" --- src/back/lto.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index e419bd1809900..cb4caec8c326c 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -710,10 +710,6 @@ pub struct ThinBuffer { context: Arc, } -// TODO: check if this makes sense to make ThinBuffer Send and Sync. -unsafe impl Send for ThinBuffer {} -unsafe impl Sync for ThinBuffer {} - impl ThinBuffer { pub(crate) fn new(context: &Arc) -> Self { Self { context: Arc::clone(context) } From 7bca1f2675d9f63b09ed9641e9aefe05b8ccc675 Mon Sep 17 00:00:00 2001 From: Sky Date: Tue, 11 Feb 2025 11:49:14 -0500 Subject: [PATCH 0037/2248] Fix missing const for inherent pointer `replace` methods --- library/core/src/ptr/mut_ptr.rs | 3 ++- library/core/src/ptr/non_null.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index d1b0104c0fa92..c102e21026c82 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1577,8 +1577,9 @@ impl *mut T { /// /// [`ptr::replace`]: crate::ptr::replace() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_stable(feature = "const_inherent_ptr_replace", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] - pub unsafe fn replace(self, src: T) -> T + pub const unsafe fn replace(self, src: T) -> T where T: Sized, { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d93069d384edd..4c7f0817cf384 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1169,7 +1169,8 @@ impl NonNull { /// [`ptr::replace`]: crate::ptr::replace() #[inline(always)] #[stable(feature = "non_null_convenience", since = "1.80.0")] - pub unsafe fn replace(self, src: T) -> T + #[rustc_const_stable(feature = "const_inherent_ptr_replace", since = "CURRENT_RUSTC_VERSION")] + pub const unsafe fn replace(self, src: T) -> T where T: Sized, { From c817210c70bed03133395890a09908ae06e44c94 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 12 Feb 2025 15:22:13 +0100 Subject: [PATCH 0038/2248] handle NaN in unordered comparisons --- src/builder.rs | 45 +++++++++++++++++++++++++++++++++++++- tests/failing-ui-tests.txt | 1 - tests/run/float.rs | 32 +++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 tests/run/float.rs diff --git a/src/builder.rs b/src/builder.rs index 8268819c5faed..fc2f6862c1612 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1284,7 +1284,50 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { - self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs) + // LLVM has a concept of "unordered compares", where eg ULT returns true if either the two + // arguments are unordered (i.e. either is NaN), or the lhs is less than the rhs. GCC does + // not natively have this concept, so in some cases we must manually handle NaNs + let must_handle_nan = match op { + RealPredicate::RealPredicateFalse => unreachable!(), + RealPredicate::RealOEQ => false, + RealPredicate::RealOGT => false, + RealPredicate::RealOGE => false, + RealPredicate::RealOLT => false, + RealPredicate::RealOLE => false, + RealPredicate::RealONE => false, + RealPredicate::RealORD => unreachable!(), + RealPredicate::RealUNO => unreachable!(), + RealPredicate::RealUEQ => false, + RealPredicate::RealUGT => true, + RealPredicate::RealUGE => true, + RealPredicate::RealULT => true, + RealPredicate::RealULE => true, + RealPredicate::RealUNE => false, + RealPredicate::RealPredicateTrue => unreachable!(), + }; + + let cmp = self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs); + + if must_handle_nan { + let is_nan = self.context.new_binary_op( + self.location, + BinaryOp::LogicalOr, + self.cx.bool_type, + // compare a value to itself to check whether it is NaN + self.context.new_comparison(self.location, ComparisonOp::NotEquals, lhs, lhs), + self.context.new_comparison(self.location, ComparisonOp::NotEquals, rhs, rhs), + ); + + self.context.new_binary_op( + self.location, + BinaryOp::LogicalOr, + self.cx.bool_type, + is_nan, + cmp, + ) + } else { + cmp + } } /* Miscellaneous instructions */ diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 082958bfe1f85..579ac3749e95a 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -5,7 +5,6 @@ tests/ui/asm/x86_64/multiple-clobber-abi.rs tests/ui/functions-closures/parallel-codegen-closures.rs tests/ui/linkage-attr/linkage1.rs tests/ui/lto/dylib-works.rs -tests/ui/numbers-arithmetic/saturating-float-casts.rs tests/ui/sepcomp/sepcomp-cci.rs tests/ui/sepcomp/sepcomp-extern.rs tests/ui/sepcomp/sepcomp-fns-backwards.rs diff --git a/tests/run/float.rs b/tests/run/float.rs new file mode 100644 index 0000000000000..e0a57e6fed1a8 --- /dev/null +++ b/tests/run/float.rs @@ -0,0 +1,32 @@ +// Compiler: +// +// Run-time: +// status: 0 + +#![feature(const_black_box)] + +/* + * Code + */ + +fn main() { + use std::hint::black_box; + + macro_rules! check { + ($ty:ty, $expr:expr) => {{ + const EXPECTED: $ty = $expr; + assert_eq!($expr, EXPECTED); + }}; + } + + check!(i32, (black_box(0.0f32) as i32)); + + check!(u64, (black_box(f32::NAN) as u64)); + check!(u128, (black_box(f32::NAN) as u128)); + + check!(i64, (black_box(f64::NAN) as i64)); + check!(u64, (black_box(f64::NAN) as u64)); + + check!(i16, (black_box(f32::MIN) as i16)); + check!(i16, (black_box(f32::MAX) as i16)); +} From 4f59a687f136ac0ce29ad68ea02066e06fb9fc88 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 12 Feb 2025 19:54:51 -0500 Subject: [PATCH 0039/2248] Support sysv64 and ms ABIs --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/abi.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/context.rs | 8 +++++++- src/declare.rs | 25 ++++++++++++++----------- src/lib.rs | 4 ++-- 6 files changed, 74 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 636e75b94a3f2..832603aa79252 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72fd91f4adbf02b53cfc73c97bc33c5f253009043f30c56a5ec08dd5c8094dc8" +checksum = "2895ddec764de7ac76fe6c056050c4801a80109c066f177a00a9cc8dee02b29b" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fb7b8f48a75e2cfe78c3d9a980b32771c34ffd12d196021ab3f98c49fbd2f0d" +checksum = "ac133db68db8a6a8b2c51ef4b18d8ea16682d5814c4641272fe37bbbc223d5f3" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 63d37358561e6..b50f2a626d57c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ master = ["gccjit/master"] default = ["master"] [dependencies] -gccjit = "2.4" +gccjit = "2.5" #gccjit = { git = "https://github.com/rust-lang/gccjit.rs" } # Local copy. diff --git a/src/abi.rs b/src/abi.rs index 14fc23593f0e6..35e9b356741e8 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -9,6 +9,8 @@ use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::config; use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; +#[cfg(feature = "master")] +use rustc_target::callconv::Conv; use crate::builder::Builder; use crate::context::CodegenCx; @@ -104,6 +106,8 @@ pub trait FnAbiGccExt<'gcc, 'tcx> { // TODO(antoyo): return a function pointer type instead? fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc>; fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; + #[cfg(feature = "master")] + fn gcc_cconv(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Option>; } impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { @@ -226,4 +230,46 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { ); pointer_type } + + #[cfg(feature = "master")] + fn gcc_cconv(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Option> { + conv_to_fn_attribute(self.conv, &cx.tcx.sess.target.arch) + } +} + +#[cfg(feature = "master")] +pub fn conv_to_fn_attribute<'gcc>(conv: Conv, _arch: &str) -> Option> { + // TODO: handle the calling conventions returning None. + let attribute = match conv { + Conv::C + | Conv::Rust + | Conv::CCmseNonSecureCall + | Conv::CCmseNonSecureEntry + | Conv::RiscvInterrupt { .. } => return None, + Conv::Cold => return None, + Conv::PreserveMost => return None, + Conv::PreserveAll => return None, + /*Conv::GpuKernel => { + if arch == "amdgpu" { + return None + } else if arch == "nvptx64" { + return None + } else { + panic!("Architecture {arch} does not support GpuKernel calling convention"); + } + }*/ + Conv::AvrInterrupt => return None, + Conv::AvrNonBlockingInterrupt => return None, + Conv::ArmAapcs => return None, + Conv::Msp430Intr => return None, + Conv::PtxKernel => return None, + Conv::X86Fastcall => return None, + Conv::X86Intr => return None, + Conv::X86Stdcall => return None, + Conv::X86ThisCall => return None, + Conv::X86VectorCall => return None, + Conv::X86_64SysV => FnAttribute::SysvAbi, + Conv::X86_64Win64 => FnAttribute::MsAbi, + }; + Some(attribute) } diff --git a/src/context.rs b/src/context.rs index 2a33beef63b99..38d012c8ca6d6 100644 --- a/src/context.rs +++ b/src/context.rs @@ -23,6 +23,8 @@ use rustc_target::spec::{ HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi, }; +#[cfg(feature = "master")] +use crate::abi::conv_to_fn_attribute; use crate::callee::get_fn; use crate::common::SignType; @@ -509,7 +511,11 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn declare_c_main(&self, fn_type: Self::Type) -> Option { let entry_name = self.sess().target.entry_name.as_ref(); if !self.functions.borrow().contains_key(entry_name) { - Some(self.declare_entry_fn(entry_name, fn_type, ())) + #[cfg(feature = "master")] + let conv = conv_to_fn_attribute(self.sess().target.entry_abi, &self.sess().target.arch); + #[cfg(not(feature = "master"))] + let conv = None; + Some(self.declare_entry_fn(entry_name, fn_type, conv)) } else { // If the symbol already exists, it is an error: for example, the user wrote // #[no_mangle] extern "C" fn main(..) {..} diff --git a/src/declare.rs b/src/declare.rs index 442488b7fd650..d4a4d7f4b82f6 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -58,7 +58,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { variadic: bool, ) -> Function<'gcc> { self.linkage.set(FunctionType::Extern); - declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, params, variadic) + declare_raw_fn(self, name, None, return_type, params, variadic) } pub fn declare_global( @@ -92,7 +92,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { &self, name: &str, _fn_type: Type<'gcc>, - callconv: (), /*llvm::CCallConv*/ + #[cfg(feature = "master")] callconv: Option>, + #[cfg(not(feature = "master"))] callconv: Option<()>, ) -> RValue<'gcc> { // TODO(antoyo): use the fn_type parameter. let const_string = self.context.new_type::().make_pointer().make_pointer(); @@ -123,14 +124,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { #[cfg(feature = "master")] fn_attributes, } = fn_abi.gcc_type(self); - let func = declare_raw_fn( - self, - name, - (), /*fn_abi.llvm_cconv()*/ - return_type, - &arguments_type, - is_c_variadic, - ); + #[cfg(feature = "master")] + let conv = fn_abi.gcc_cconv(self); + #[cfg(not(feature = "master"))] + let conv = None; + let func = declare_raw_fn(self, name, conv, return_type, &arguments_type, is_c_variadic); self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices); #[cfg(feature = "master")] for fn_attr in fn_attributes { @@ -162,7 +160,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { fn declare_raw_fn<'gcc>( cx: &CodegenCx<'gcc, '_>, name: &str, - _callconv: (), /*llvm::CallConv*/ + #[cfg(feature = "master")] callconv: Option>, + #[cfg(not(feature = "master"))] _callconv: Option<()>, return_type: Type<'gcc>, param_types: &[Type<'gcc>], variadic: bool, @@ -192,6 +191,10 @@ fn declare_raw_fn<'gcc>( let name = &mangle_name(name); let func = cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, name, variadic); + #[cfg(feature = "master")] + if let Some(attribute) = callconv { + func.add_attribute(attribute); + } cx.functions.borrow_mut().insert(name.to_string(), func); #[cfg(feature = "master")] diff --git a/src/lib.rs b/src/lib.rs index f6ad0c79de545..68e0bc061add7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -187,10 +187,10 @@ impl CodegenBackend for GccCodegenBackend { crate::DEFAULT_LOCALE_RESOURCE } - fn init(&self, sess: &Session) { + fn init(&self, _sess: &Session) { #[cfg(feature = "master")] { - let target_cpu = target_cpu(sess); + let target_cpu = target_cpu(_sess); // Get the second TargetInfo with the correct CPU features by setting the arch. let context = Context::default(); From feb78f904e9e66e4fed9fe2e7e6363bb79d22be5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 6 Feb 2025 20:08:29 +0000 Subject: [PATCH 0040/2248] Implement and use BikeshedGuaranteedNoDrop for union/unsafe field validity --- example/mini_core.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/mini_core.rs b/example/mini_core.rs index 5a4ee0a198cef..2ff1d757fd4e0 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -54,6 +54,9 @@ impl LegacyReceiver for Box {} #[lang = "copy"] pub trait Copy {} +#[lang = "bikeshed_guaranteed_no_drop"] +pub trait BikeshedGuaranteedNoDrop {} + impl Copy for bool {} impl Copy for u8 {} impl Copy for u16 {} From 3ecc012f6f59419fbdfddd9bac3a4b21d2275078 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 12 Feb 2025 22:05:29 +0100 Subject: [PATCH 0041/2248] fix clobbered or lateout registers overlapping with input registers --- libgccjit.version | 2 +- src/asm.rs | 74 ++++++++++++++++++++++++-------------- tests/failing-ui-tests.txt | 1 - tests/run/asm.rs | 31 ++++++++++++++++ 4 files changed, 80 insertions(+), 28 deletions(-) diff --git a/libgccjit.version b/libgccjit.version index 417fd5b03935d..dfdc222c00fcb 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -e607be166673a8de9fc07f6f02c60426e556c5f2 +d6f5a708104a98199ac0f01a3b6b279a0f7c66d3 diff --git a/src/asm.rs b/src/asm.rs index 415f8affab901..9f4b84d22c08a 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -36,7 +36,8 @@ use crate::type_of::LayoutGccExt; // // 3. Clobbers. GCC has a separate list of clobbers, and clobbers don't have indexes. // Contrary, Rust expresses clobbers through "out" operands that aren't tied to -// a variable (`_`), and such "clobbers" do have index. +// a variable (`_`), and such "clobbers" do have index. Input operands cannot also +// be clobbered. // // 4. Furthermore, GCC Extended Asm does not support explicit register constraints // (like `out("eax")`) directly, offering so-called "local register variables" @@ -161,6 +162,16 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // Also, we don't emit any asm operands immediately; we save them to // the one of the buffers to be emitted later. + let mut input_registers = vec![]; + + for op in rust_operands { + if let InlineAsmOperandRef::In { reg, .. } = *op { + if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) { + input_registers.push(reg_name); + } + } + } + // 1. Normal variables (and saving operands to buffers). for (rust_idx, op) in rust_operands.iter().enumerate() { match *op { @@ -183,25 +194,39 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { continue; } (Register(reg_name), None) => { - // `clobber_abi` can add lots of clobbers that are not supported by the target, - // such as AVX-512 registers, so we just ignore unsupported registers - let is_target_supported = - reg.reg_class().supported_types(asm_arch, true).iter().any( - |&(_, feature)| { - if let Some(feature) = feature { - self.tcx - .asm_target_features(instance.def_id()) - .contains(&feature) - } else { - true // Register class is unconditionally supported - } - }, - ); - - if is_target_supported && !clobbers.contains(®_name) { - clobbers.push(reg_name); + if input_registers.contains(®_name) { + // the `clobber_abi` operand is converted into a series of + // `lateout("reg") _` operands. Of course, a user could also + // explicitly define such an output operand. + // + // GCC does not allow input registers to be clobbered, so if this out register + // is also used as an in register, do not add it to the clobbers list. + // it will be treated as a lateout register with `out_place: None` + if !late { + bug!("input registers can only be used as lateout regisers"); + } + ("r", dummy_output_type(self.cx, reg.reg_class())) + } else { + // `clobber_abi` can add lots of clobbers that are not supported by the target, + // such as AVX-512 registers, so we just ignore unsupported registers + let is_target_supported = + reg.reg_class().supported_types(asm_arch, true).iter().any( + |&(_, feature)| { + if let Some(feature) = feature { + self.tcx + .asm_target_features(instance.def_id()) + .contains(&feature) + } else { + true // Register class is unconditionally supported + } + }, + ); + + if is_target_supported && !clobbers.contains(®_name) { + clobbers.push(reg_name); + } + continue; } - continue; } }; @@ -230,13 +255,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => { - let constraint = - if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) { - constraint - } else { - // left for the next pass - continue; - }; + let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) else { + // left for the next pass + continue; + }; // Rustc frontend guarantees that input and output types are "compatible", // so we can just use input var's type for the output variable. diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 579ac3749e95a..0babc748f98b9 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -1,7 +1,6 @@ tests/ui/allocator/no_std-alloc-error-handler-custom.rs tests/ui/allocator/no_std-alloc-error-handler-default.rs tests/ui/asm/may_unwind.rs -tests/ui/asm/x86_64/multiple-clobber-abi.rs tests/ui/functions-closures/parallel-codegen-closures.rs tests/ui/linkage-attr/linkage1.rs tests/ui/lto/dylib-works.rs diff --git a/tests/run/asm.rs b/tests/run/asm.rs index 4e05d026868e7..9ede19a061f39 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -174,6 +174,37 @@ fn asm() { mem_cpy(array2.as_mut_ptr(), array1.as_ptr(), 3); } assert_eq!(array1, array2); + + // in and clobber registers cannot overlap. This tests that the lateout register without an + // output place (indicated by the `_`) is not added to the list of clobbered registers + let x = 8; + let y: i32; + unsafe { + asm!( + "mov rax, rdi", + in("rdi") x, + lateout("rdi") _, + out("rax") y, + ); + } + assert_eq!((x, y), (8, 8)); + + // sysv64 is the default calling convention on unix systems. The rdi register is + // used to pass arguments in the sysv64 calling convention, so this register will be clobbered + #[cfg(unix)] + { + let x = 16; + let y: i32; + unsafe { + asm!( + "mov rax, rdi", + in("rdi") x, + out("rax") y, + clobber_abi("sysv64"), + ); + } + assert_eq!((x, y), (16, 16)); + } } #[cfg(not(target_arch = "x86_64"))] From fd526a248c05b846507291a6281c06e10c2d05f7 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 13 Jan 2025 15:52:08 +0000 Subject: [PATCH 0042/2248] Make `-O` mean `-C opt-level=3` --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index ce88ac390216a..6455bcec6851b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -476,7 +476,7 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { Some(level) => match level { OptLevel::No => OptimizationLevel::None, OptLevel::Less => OptimizationLevel::Limited, - OptLevel::Default => OptimizationLevel::Standard, + OptLevel::More => OptimizationLevel::Standard, OptLevel::Aggressive => OptimizationLevel::Aggressive, OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited, }, From 5e0c773e8000c56fa1c258b57b2b64e453a3f57a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 5 Feb 2025 03:43:54 -0800 Subject: [PATCH 0043/2248] Set both `nuw` and `nsw` in slice size calculation There's an old note in the code to do this, and now that LLVM-C has an API for it, we might as well. --- src/builder.rs | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 1c3d6cc899a63..b8e37b604801f 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -665,6 +665,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { a + b } + // TODO(antoyo): should we also override the `unchecked_` versions? fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { self.gcc_sub(a, b) } @@ -832,31 +833,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { set_rvalue_location(self, self.gcc_not(a)) } - fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - set_rvalue_location(self, self.gcc_add(a, b)) - } - - fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - set_rvalue_location(self, self.gcc_add(a, b)) - } - - fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - set_rvalue_location(self, self.gcc_sub(a, b)) - } - - fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - // TODO(antoyo): should generate poison value? - set_rvalue_location(self, self.gcc_sub(a, b)) - } - - fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - set_rvalue_location(self, self.gcc_mul(a, b)) - } - - fn unchecked_umul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - set_rvalue_location(self, self.gcc_mul(a, b)) - } - fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. set_rvalue_location(self, lhs + rhs) From 53aa977e4bd4f5d79303061c1a6b6dbeb8cbf51c Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 13 Feb 2025 19:44:42 +0100 Subject: [PATCH 0044/2248] refactor and support reg_byte registers --- src/asm.rs | 215 +++++++++++++++++++++++++---------------------- tests/run/asm.rs | 22 +++++ 2 files changed, 136 insertions(+), 101 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 9f4b84d22c08a..dbdf37ee6c9ef 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -611,114 +611,127 @@ fn estimate_template_length( } /// Converts a register class to a GCC constraint code. -fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { - let constraint = match reg { - // For vector registers LLVM wants the register name to match the type size. +fn reg_to_gcc(reg_or_reg_class: InlineAsmRegOrRegClass) -> ConstraintOrRegister { + match reg_or_reg_class { InlineAsmRegOrRegClass::Reg(reg) => { - match reg { - InlineAsmReg::X86(_) => { - // TODO(antoyo): add support for vector register. - // - // // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119 - return ConstraintOrRegister::Register(match reg.name() { - // Some of registers' names does not map 1-1 from rust to gcc - "st(0)" => "st", + ConstraintOrRegister::Register(explicit_reg_to_gcc(reg)) + } + InlineAsmRegOrRegClass::RegClass(reg_class) => { + ConstraintOrRegister::Constraint(reg_class_to_gcc(reg_class)) + } + } +} - name => name, - }); +fn explicit_reg_to_gcc(reg: InlineAsmReg) -> &'static str { + // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119 + match reg { + InlineAsmReg::X86(reg) => { + // TODO(antoyo): add support for vector register. + match reg.reg_class() { + X86InlineAsmRegClass::reg_byte => { + // GCC does not support the `b` suffix, so we just strip it + // see https://github.com/rust-lang/rustc_codegen_gcc/issues/485 + reg.name().trim_end_matches('b') } + _ => match reg.name() { + // Some of registers' names does not map 1-1 from rust to gcc + "st(0)" => "st", - _ => unimplemented!(), + name => name, + }, } } - // They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html - InlineAsmRegOrRegClass::RegClass(reg) => match reg { - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r", - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w", - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x", - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { - unreachable!("clobber-only") - } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t", - InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d", - InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r", - InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w", - InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e", - InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", - InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => { - unreachable!("clobber-only") - } - InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", - InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", - InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r" - InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r", - // https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for - // "define_constraint". - InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h", - InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r", - InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l", - - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v", - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { - unreachable!("clobber-only") - } - InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => { - unreachable!("clobber-only") - } - InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r", - InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q", - InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q", - InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg) - | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x", - InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v", - InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk", - InlineAsmRegClass::X86( - X86InlineAsmRegClass::kreg0 - | X86InlineAsmRegClass::x87_reg - | X86InlineAsmRegClass::mmx_reg - | X86InlineAsmRegClass::tmm_reg, - ) => unreachable!("clobber-only"), - InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { - bug!("GCC backend does not support SPIR-V") - } - InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a", - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v", - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => { - unreachable!("clobber-only") - } - InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), - InlineAsmRegClass::Err => unreachable!(), - }, - }; - ConstraintOrRegister::Constraint(constraint) + _ => unimplemented!(), + } +} + +/// They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html +fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { + match reg_class { + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r", + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w", + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x", + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + unreachable!("clobber-only") + } + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e", + InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => { + unreachable!("clobber-only") + } + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", + InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r" + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r", + // https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for + // "define_constraint". + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h", + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r", + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l", + + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v", + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { + unreachable!("clobber-only") + } + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => { + unreachable!("clobber-only") + } + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r", + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q", + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q", + InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg) + | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x", + InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v", + InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk", + InlineAsmRegClass::X86( + X86InlineAsmRegClass::kreg0 + | X86InlineAsmRegClass::x87_reg + | X86InlineAsmRegClass::mmx_reg + | X86InlineAsmRegClass::tmm_reg, + ) => unreachable!("clobber-only"), + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("GCC backend does not support SPIR-V") + } + InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => { + unreachable!("clobber-only") + } + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), + InlineAsmRegClass::Err => unreachable!(), + } } /// Type to use for outputs that are discarded. It doesn't really matter what diff --git a/tests/run/asm.rs b/tests/run/asm.rs index 9ede19a061f39..2dbf43be664dc 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -205,6 +205,28 @@ fn asm() { } assert_eq!((x, y), (16, 16)); } + + // the `b` suffix for registers in the `reg_byte` register class is not supported in GCC + // and needs to be stripped in order to use these registers. + unsafe { + core::arch::asm!( + "", + out("al") _, + out("bl") _, + out("cl") _, + out("dl") _, + out("sil") _, + out("dil") _, + out("r8b") _, + out("r9b") _, + out("r10b") _, + out("r11b") _, + out("r12b") _, + out("r13b") _, + out("r14b") _, + out("r15b") _, + ); + } } #[cfg(not(target_arch = "x86_64"))] From 9c3b5cf9859a971839d3d116f07b955f163f6d07 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Wed, 19 Feb 2025 03:39:15 +0900 Subject: [PATCH 0045/2248] more natural suggestions for `cmp_owned` --- clippy_lints/src/operators/cmp_owned.rs | 2 +- tests/ui/cmp_owned/with_suggestion.fixed | 9 +++++++++ tests/ui/cmp_owned/with_suggestion.rs | 9 +++++++++ tests/ui/cmp_owned/with_suggestion.stderr | 14 +++++++++++++- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/operators/cmp_owned.rs b/clippy_lints/src/operators/cmp_owned.rs index cf6b8992973a7..9b2cfd91b8535 100644 --- a/clippy_lints/src/operators/cmp_owned.rs +++ b/clippy_lints/src/operators/cmp_owned.rs @@ -98,7 +98,7 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) let arg_snip = snippet(cx, arg_span, ".."); let expr_snip; let eq_impl; - if with_deref.is_implemented() { + if with_deref.is_implemented() && !arg_ty.peel_refs().is_str() { expr_snip = format!("*{arg_snip}"); eq_impl = with_deref; } else { diff --git a/tests/ui/cmp_owned/with_suggestion.fixed b/tests/ui/cmp_owned/with_suggestion.fixed index eb01633a25fd5..85d0991bef05d 100644 --- a/tests/ui/cmp_owned/with_suggestion.fixed +++ b/tests/ui/cmp_owned/with_suggestion.fixed @@ -74,3 +74,12 @@ impl ToOwned for Baz { Baz } } + +fn issue_8103() { + let foo1 = String::from("foo"); + let _ = foo1 == "foo"; + //~^ cmp_owned + let foo2 = "foo"; + let _ = foo1 == foo2; + //~^ cmp_owned +} diff --git a/tests/ui/cmp_owned/with_suggestion.rs b/tests/ui/cmp_owned/with_suggestion.rs index 82409f27b129c..2393757d76f2b 100644 --- a/tests/ui/cmp_owned/with_suggestion.rs +++ b/tests/ui/cmp_owned/with_suggestion.rs @@ -74,3 +74,12 @@ impl ToOwned for Baz { Baz } } + +fn issue_8103() { + let foo1 = String::from("foo"); + let _ = foo1 == "foo".to_owned(); + //~^ cmp_owned + let foo2 = "foo"; + let _ = foo1 == foo2.to_owned(); + //~^ cmp_owned +} diff --git a/tests/ui/cmp_owned/with_suggestion.stderr b/tests/ui/cmp_owned/with_suggestion.stderr index ca2ab44847274..dd9ffa70897ab 100644 --- a/tests/ui/cmp_owned/with_suggestion.stderr +++ b/tests/ui/cmp_owned/with_suggestion.stderr @@ -37,5 +37,17 @@ error: this creates an owned instance just for comparison LL | "abc".chars().filter(|c| c.to_owned() != 'X'); | ^^^^^^^^^^^^ help: try: `*c` -error: aborting due to 6 previous errors +error: this creates an owned instance just for comparison + --> tests/ui/cmp_owned/with_suggestion.rs:80:21 + | +LL | let _ = foo1 == "foo".to_owned(); + | ^^^^^^^^^^^^^^^^ help: try: `"foo"` + +error: this creates an owned instance just for comparison + --> tests/ui/cmp_owned/with_suggestion.rs:83:21 + | +LL | let _ = foo1 == foo2.to_owned(); + | ^^^^^^^^^^^^^^^ help: try: `foo2` + +error: aborting due to 8 previous errors From 51911a745de6fab88f7eb75b2b8bea9787c5a153 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 14 Feb 2025 20:25:43 -0800 Subject: [PATCH 0046/2248] Emit `trunc nuw` for unchecked shifts and `to_immediate_scalar` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - For shifts this shrinks the IR by no longer needing an `assume` while still providing the UB information - Having this on the `i8`→`i1` truncations will hopefully help with some places that have to load `i8`s or pass those in LLVM structs without range information --- src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builder.rs b/src/builder.rs index b8e37b604801f..76846692459d5 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1694,7 +1694,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value { if scalar.is_bool() { - return self.trunc(val, self.cx().type_i1()); + return self.unchecked_utrunc(val, self.cx().type_i1()); } val } From 9ebb68ddda0247df044241daaf4856144c9c0998 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 15 Feb 2025 16:07:18 -0800 Subject: [PATCH 0047/2248] Rework `OperandRef::extract_field` to stop calling `to_immediate_scalar` on things which are already immediates That means it stops trying to truncate things that are already `i1`s. --- src/builder.rs | 12 ++++++++---- src/intrinsic/mod.rs | 11 ++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 76846692459d5..c8b7616e64509 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -989,10 +989,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { OperandValue::Ref(place.val) } else if place.layout.is_gcc_immediate() { let load = self.load(place.layout.gcc_type(self), place.val.llval, place.val.align); - if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr { - scalar_load_metadata(self, load, scalar); - } - OperandValue::Immediate(self.to_immediate(load, place.layout)) + OperandValue::Immediate( + if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr { + scalar_load_metadata(self, load, scalar); + self.to_immediate_scalar(load, *scalar) + } else { + load + }, + ) } else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr { let b_offset = a.size(self).align_to(b.align(self).abi); diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index a1123fafe2f30..5322b731d8bb5 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -9,7 +9,7 @@ use gccjit::FunctionType; use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp}; #[cfg(feature = "master")] use rustc_abi::ExternAbi; -use rustc_abi::HasDataLayout; +use rustc_abi::{BackendRepr, HasDataLayout}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -181,14 +181,19 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc sym::volatile_load | sym::unaligned_volatile_load => { let tp_ty = fn_args.type_at(0); let ptr = args[0].immediate(); + let layout = self.layout_of(tp_ty); let load = if let PassMode::Cast { cast: ref ty, pad_i32: _ } = fn_abi.ret.mode { let gcc_ty = ty.gcc_type(self); self.volatile_load(gcc_ty, ptr) } else { - self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr) + self.volatile_load(layout.gcc_type(self), ptr) }; // TODO(antoyo): set alignment. - self.to_immediate(load, self.layout_of(tp_ty)) + if let BackendRepr::Scalar(scalar) = layout.backend_repr { + self.to_immediate_scalar(load, scalar) + } else { + load + } } sym::volatile_store => { let dst = args[0].deref(self.cx()); From be635722bd4264f0fd0de4cccb9ca4f9f74fafd9 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 25 Jan 2025 20:15:24 -0600 Subject: [PATCH 0048/2248] Remove `BackendRepr::Uninhabited`, replaced with an `uninhabited: bool` field in `LayoutData`. Also update comments that refered to BackendRepr::Uninhabited. --- src/intrinsic/mod.rs | 2 +- src/type_of.rs | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 5322b731d8bb5..433868e238a4c 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -315,7 +315,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let layout = self.layout_of(tp_ty).layout; let _use_integer_compare = match layout.backend_repr() { Scalar(_) | ScalarPair(_, _) => true, - Uninhabited | Vector { .. } => false, + Vector { .. } => false, Memory { .. } => { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), diff --git a/src/type_of.rs b/src/type_of.rs index 8b8b54753e7fd..bac4fc51300a2 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -84,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( false, ); } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} + BackendRepr::Memory { .. } => {} } let name = match *layout.ty.kind() { @@ -179,19 +179,16 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { fn is_gcc_immediate(&self) -> bool { match self.backend_repr { BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, - BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { - false - } + BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false, } } fn is_gcc_scalar_pair(&self) -> bool { match self.backend_repr { BackendRepr::ScalarPair(..) => true, - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } - | BackendRepr::Memory { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => { + false + } } } From 12dd4a190866a94b1802b3b5d9b60055308e15bb Mon Sep 17 00:00:00 2001 From: ltdk Date: Sat, 22 Feb 2025 14:59:07 -0500 Subject: [PATCH 0049/2248] Stabilise c_str_module --- library/alloc/src/ffi/mod.rs | 2 +- library/core/src/ffi/mod.rs | 2 +- library/std/src/ffi/mod.rs | 2 +- library/std/src/lib.rs | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/ffi/mod.rs b/library/alloc/src/ffi/mod.rs index 695d7ad07cf76..05a2763a22596 100644 --- a/library/alloc/src/ffi/mod.rs +++ b/library/alloc/src/ffi/mod.rs @@ -87,5 +87,5 @@ pub use self::c_str::CString; #[stable(feature = "alloc_c_string", since = "1.64.0")] pub use self::c_str::{FromVecWithNulError, IntoStringError, NulError}; -#[unstable(feature = "c_str_module", issue = "112134")] +#[stable(feature = "c_str_module", since = "CURRENT_RUSTC_VERSION")] pub mod c_str; diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 9bae5fd466a18..c9c73a25d899e 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -20,7 +20,7 @@ pub use self::c_str::FromBytesUntilNulError; pub use self::c_str::FromBytesWithNulError; use crate::fmt; -#[unstable(feature = "c_str_module", issue = "112134")] +#[stable(feature = "c_str_module", since = "CURRENT_RUSTC_VERSION")] pub mod c_str; #[unstable( diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 860ec3a6be16e..6e1ec72dbdb3e 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -161,7 +161,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[unstable(feature = "c_str_module", issue = "112134")] +#[stable(feature = "c_str_module", since = "CURRENT_RUSTC_VERSION")] pub mod c_str; #[stable(feature = "core_c_void", since = "1.30.0")] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 0661b3d770e48..998bf32a6cef7 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -327,7 +327,6 @@ #![feature(array_chunks)] #![feature(bstr)] #![feature(bstr_internals)] -#![feature(c_str_module)] #![feature(char_internals)] #![feature(clone_to_uninit)] #![feature(core_intrinsics)] From 6be84b1f3863c93f87946a1efd86120966d703dc Mon Sep 17 00:00:00 2001 From: ltdk Date: Sat, 22 Feb 2025 15:10:03 -0500 Subject: [PATCH 0050/2248] Somehow these stability attributes were able to be omitted before? --- library/alloc/src/ffi/c_str.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index fd93045a5ac4d..87625193b02aa 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -821,6 +821,7 @@ impl From>> for CString { } } +#[stable(feature = "c_string_from_str", since = "1.85.0")] impl FromStr for CString { type Err = NulError; @@ -833,6 +834,7 @@ impl FromStr for CString { } } +#[stable(feature = "c_string_from_str", since = "1.85.0")] impl TryFrom for String { type Error = IntoStringError; From f04bfae764c90270dddeb5d0cf1e8254fb0098ce Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Sun, 23 Feb 2025 11:57:16 +0900 Subject: [PATCH 0051/2248] correct version attribute for `io_other_error` --- clippy_lints/src/methods/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 291ddc1ce1712..f84f544ddba2e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4478,7 +4478,7 @@ declare_clippy_lint! { /// ```no_run /// let _ = std::io::Error::other("bad".to_string()); /// ``` - #[clippy::version = "1.86.0"] + #[clippy::version = "1.87.0"] pub IO_OTHER_ERROR, style, "calling `std::io::Error::new(std::io::ErrorKind::Other, _)`" From 3fe0b3d4d04dd86cbe22770217f3b42a8856d382 Mon Sep 17 00:00:00 2001 From: Mu001999 Date: Sun, 23 Feb 2025 11:29:35 +0800 Subject: [PATCH 0052/2248] not lint break with label and unsafe block --- compiler/rustc_parse/src/parser/expr.rs | 14 ++++++++------ tests/ui/lint/break-with-label-and-unsafe-block.rs | 11 +++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 tests/ui/lint/break-with-label-and-unsafe-block.rs diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e0e6c2177da54..21e01ff535a8c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1859,13 +1859,15 @@ impl<'a> Parser<'a> { let mut expr = self.parse_expr_opt()?; if let Some(expr) = &mut expr { if label.is_some() - && matches!( - expr.kind, + && match &expr.kind { ExprKind::While(_, _, None) - | ExprKind::ForLoop { label: None, .. } - | ExprKind::Loop(_, None, _) - | ExprKind::Block(_, None) - ) + | ExprKind::ForLoop { label: None, .. } + | ExprKind::Loop(_, None, _) => true, + ExprKind::Block(block, None) => { + matches!(block.rules, BlockCheckMode::Default) + } + _ => false, + } { self.psess.buffer_lint( BREAK_WITH_LABEL_AND_LOOP, diff --git a/tests/ui/lint/break-with-label-and-unsafe-block.rs b/tests/ui/lint/break-with-label-and-unsafe-block.rs new file mode 100644 index 0000000000000..a76a576147556 --- /dev/null +++ b/tests/ui/lint/break-with-label-and-unsafe-block.rs @@ -0,0 +1,11 @@ +//@ check-pass + +#![deny(break_with_label_and_loop)] + +unsafe fn foo() -> i32 { 42 } + +fn main () { + 'label: loop { + break 'label unsafe { foo() } + }; +} From 3d41095af9752891b315cda30a4a91ee7db0763b Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sun, 23 Feb 2025 10:51:22 +0100 Subject: [PATCH 0053/2248] Put shebang at the top of pretty-print --- compiler/rustc_ast_pretty/src/pprust/state.rs | 19 +++++++++++++++++++ tests/pretty/shebang-at-top.pp | 12 ++++++++++++ tests/pretty/shebang-at-top.rs | 6 ++++++ 3 files changed, 37 insertions(+) create mode 100644 tests/pretty/shebang-at-top.pp create mode 100644 tests/pretty/shebang-at-top.rs diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 0bf5de3ef8985..0d6c695108204 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -243,6 +243,11 @@ pub fn print_crate<'a>( let mut s = State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann }; + // We need to print shebang before anything else + // otherwise the resulting code will not compile + // and shebang will be useless. + s.maybe_print_shebang(); + if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) { // We need to print `#![no_std]` (and its feature gate) so that // compiling pretty-printed source won't inject libstd again. @@ -574,6 +579,20 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere self.word(st) } + fn maybe_print_shebang(&mut self) { + if let Some(cmnt) = self.peek_comment() { + // Comment is a shebang if it's: + // Isolated, starts with #! and doesn't continue with `[` + // See [rustc_lexer::strip_shebang] and [gather_comments] from pprust/state.rs for details + if cmnt.style == CommentStyle::Isolated + && cmnt.lines.first().map_or(false, |l| l.starts_with("#!")) + { + let cmnt = self.next_comment().unwrap(); + self.print_comment(cmnt); + } + } + } + fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true) } diff --git a/tests/pretty/shebang-at-top.pp b/tests/pretty/shebang-at-top.pp new file mode 100644 index 0000000000000..a279725263640 --- /dev/null +++ b/tests/pretty/shebang-at-top.pp @@ -0,0 +1,12 @@ +#!/usr/bin/env rust +#![feature(prelude_import)] +#![no_std] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +//@ pretty-mode:expanded +//@ pp-exact:shebang-at-top.pp +//@ pretty-compare-only + +fn main() {} diff --git a/tests/pretty/shebang-at-top.rs b/tests/pretty/shebang-at-top.rs new file mode 100644 index 0000000000000..8bfa925fa1ab1 --- /dev/null +++ b/tests/pretty/shebang-at-top.rs @@ -0,0 +1,6 @@ +#!/usr/bin/env rust +//@ pretty-mode:expanded +//@ pp-exact:shebang-at-top.pp +//@ pretty-compare-only + +fn main() {} From 517766c9740d54ac0778bc78225edb63647dc0e1 Mon Sep 17 00:00:00 2001 From: Dinu Blanovschi Date: Sun, 23 Feb 2025 14:18:52 +0100 Subject: [PATCH 0054/2248] Update as_conversions.rs --- clippy_lints/src/as_conversions.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs index 78102772927c0..27e304a848e33 100644 --- a/clippy_lints/src/as_conversions.rs +++ b/clippy_lints/src/as_conversions.rs @@ -12,17 +12,17 @@ declare_clippy_lint! { /// regardless of whether good alternatives exist or not. If you want more /// precise lints for `as`, please consider using these separate lints: /// - /// - clippy::cast_lossless - /// - clippy::cast_possible_truncation - /// - clippy::cast_possible_wrap - /// - clippy::cast_precision_loss - /// - clippy::cast_sign_loss - /// - clippy::char_lit_as_u8 - /// - clippy::fn_to_numeric_cast - /// - clippy::fn_to_numeric_cast_with_truncation - /// - clippy::ptr_as_ptr - /// - clippy::unnecessary_cast - /// - invalid_reference_casting + /// - `clippy::cast_lossless` + /// - `clippy::cast_possible_truncation` + /// - `clippy::cast_possible_wrap` + /// - `clippy::cast_precision_loss` + /// - `clippy::cast_sign_loss` + /// - `clippy::char_lit_as_u8` + /// - `clippy::fn_to_numeric_cast` + /// - `clippy::fn_to_numeric_cast_with_truncation` + /// - `clippy::ptr_as_ptr` + /// - `clippy::unnecessary_cast` + /// - `invalid_reference_casting` /// /// There is a good explanation the reason why this lint should work in this /// way and how it is useful [in this From aa038c2d95bb041a170cb1bbea8ef0fd2fd14ca4 Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 6 Feb 2025 21:59:36 +0800 Subject: [PATCH 0055/2248] Add `new_regular` and `new_allocator` to `ModuleCodegen` --- src/back/lto.rs | 9 ++++----- src/base.rs | 11 +++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index cb4caec8c326c..e5221c7da3197 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -632,17 +632,16 @@ pub unsafe fn optimize_thin_module( Arc::new(SyncContext::new(context)) } }; - let module = ModuleCodegen { - module_llvm: GccContext { + let module = ModuleCodegen::new_regular( + thin_module.name().to_string(), + GccContext { context, should_combine_object_files, // TODO(antoyo): use the correct relocation model here. relocation_model: RelocModel::Pic, temp_dir: None, }, - name: thin_module.name().to_string(), - kind: ModuleKind::Regular, - }; + ); /*{ let target = &*module.module_llvm.tm; let llmod = module.module_llvm.llmod(); diff --git a/src/base.rs b/src/base.rs index 962f4b161d788..9b495174a3fab 100644 --- a/src/base.rs +++ b/src/base.rs @@ -4,10 +4,10 @@ use std::sync::Arc; use std::time::Instant; use gccjit::{CType, Context, FunctionType, GlobalKind}; +use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::DebugInfoCodegenMethods; -use rustc_codegen_ssa::{ModuleCodegen, ModuleKind}; use rustc_middle::dep_graph; use rustc_middle::mir::mono::Linkage; #[cfg(feature = "master")] @@ -237,16 +237,15 @@ pub fn compile_codegen_unit( } } - ModuleCodegen { - name: cgu_name.to_string(), - module_llvm: GccContext { + ModuleCodegen::new_regular( + cgu_name.to_string(), + GccContext { context: Arc::new(SyncContext::new(context)), relocation_model: tcx.sess.relocation_model(), should_combine_object_files: false, temp_dir: None, }, - kind: ModuleKind::Regular, - } + ) } (module, cost) From 9b8701d27ebc49b2ade98d910b411d6f0a57a0ac Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 6 Feb 2025 22:00:19 +0800 Subject: [PATCH 0056/2248] Save pre-link bitcode to `ModuleCodegen` --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 6455bcec6851b..9d91aab72ab3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -393,7 +393,7 @@ impl WriteBackendMethods for GccCodegenBackend { unsafe fn optimize( _cgcx: &CodegenContext, _dcx: DiagCtxtHandle<'_>, - module: &ModuleCodegen, + module: &mut ModuleCodegen, config: &ModuleConfig, ) -> Result<(), FatalError> { module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level)); From 15f0dca5317ac3cac7be8f509761fa6248fad0c0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 23 Feb 2025 17:34:50 +0100 Subject: [PATCH 0057/2248] remove support for rustc_intrinsic_must_be_overridden from the compiler --- example/mini_core.rs | 65 +++++++++-------------------------------- tests/run/abort1.rs | 5 +--- tests/run/abort2.rs | 5 +--- tests/run/assign.rs | 5 +--- tests/run/mut_ref.rs | 5 +--- tests/run/operations.rs | 5 +--- tests/run/static.rs | 5 +--- 7 files changed, 19 insertions(+), 76 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 2ff1d757fd4e0..3dad35bc4ce47 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -591,70 +591,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 { diff --git a/tests/run/abort1.rs b/tests/run/abort1.rs index 385e41a68817f..fe46d9ae41849 100644 --- a/tests/run/abort1.rs +++ b/tests/run/abort1.rs @@ -36,10 +36,7 @@ mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } /* diff --git a/tests/run/abort2.rs b/tests/run/abort2.rs index 6c66a930e0741..4123f4f4beebc 100644 --- a/tests/run/abort2.rs +++ b/tests/run/abort2.rs @@ -36,10 +36,7 @@ mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } /* diff --git a/tests/run/assign.rs b/tests/run/assign.rs index 4d414c577a657..286155852d50f 100644 --- a/tests/run/assign.rs +++ b/tests/run/assign.rs @@ -59,10 +59,7 @@ mod libc { mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } #[lang = "panic"] diff --git a/tests/run/mut_ref.rs b/tests/run/mut_ref.rs index 9be64f991ee08..b0215860406e5 100644 --- a/tests/run/mut_ref.rs +++ b/tests/run/mut_ref.rs @@ -61,10 +61,7 @@ mod libc { mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } #[lang = "panic"] diff --git a/tests/run/operations.rs b/tests/run/operations.rs index c92d3cc0b8fbf..8ba7a4c5ed8ce 100644 --- a/tests/run/operations.rs +++ b/tests/run/operations.rs @@ -67,10 +67,7 @@ mod libc { mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } #[lang = "panic"] diff --git a/tests/run/static.rs b/tests/run/static.rs index 80c8782c4b1a6..c3c8121b1e195 100644 --- a/tests/run/static.rs +++ b/tests/run/static.rs @@ -49,10 +49,7 @@ mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } mod libc { From e92466e22a6f98f7be019a6709b8f120cc5981a3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 24 Feb 2025 08:07:11 +0000 Subject: [PATCH 0058/2248] Remove an unnecessary lifetime --- src/common.rs | 4 ++-- src/consts.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common.rs b/src/common.rs index 20a3482aaa27f..0ee13498ccade 100644 --- a/src/common.rs +++ b/src/common.rs @@ -59,7 +59,7 @@ pub fn type_is_pointer(typ: Type<'_>) -> bool { typ.get_pointee().is_some() } -impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { +impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { fn const_null(&self, typ: Type<'gcc>) -> RValue<'gcc> { if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) } } @@ -263,7 +263,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } } - fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value { + fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> Self::Value { const_alloc_to_gcc(self, alloc) } diff --git a/src/consts.rs b/src/consts.rs index fb0ca31c54334..c514b7a428bc6 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -302,9 +302,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } } -pub fn const_alloc_to_gcc<'gcc, 'tcx>( - cx: &CodegenCx<'gcc, 'tcx>, - alloc: ConstAllocation<'tcx>, +pub fn const_alloc_to_gcc<'gcc>( + cx: &CodegenCx<'gcc, '_>, + alloc: ConstAllocation<'_>, ) -> RValue<'gcc> { let alloc = alloc.inner(); let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); From 71c189a2effd3ea4e8d4653b938c9d90cdb78845 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 24 Feb 2025 11:31:43 +0000 Subject: [PATCH 0059/2248] Generalize BaseTypeCodegenMethods --- src/type_.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/type_.rs b/src/type_.rs index cb08723431a9a..4e0a250b5509a 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -123,7 +123,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } } -impl<'gcc, 'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { +impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { fn type_i8(&self) -> Type<'gcc> { self.i8_type } From 334eb82117cddee4813e860e54d1aa9db91da461 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 24 Feb 2025 12:23:45 +0000 Subject: [PATCH 0060/2248] Remove an unused lifetime param --- src/abi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/abi.rs b/src/abi.rs index 717baebcd8cd6..9fe6baa3d2573 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -16,7 +16,7 @@ use crate::context::CodegenCx; use crate::intrinsic::ArgAbiExt; use crate::type_of::LayoutGccExt; -impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { +impl AbiBuilderMethods for Builder<'_, '_, '_> { fn get_param(&mut self, index: usize) -> Self::Value { let func = self.current_func(); let param = func.get_param(index as i32); From 78481458d172e0a85dc56a08f315d7fc6c1757cc Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 25 Feb 2025 09:20:10 +0100 Subject: [PATCH 0061/2248] remove `simd_fpow` and `simd_fpowi` --- src/intrinsic/simd.rs | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 84cd5b002fbb6..8b454ab2a4241 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -772,8 +772,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( sym::simd_floor => "floor", sym::simd_fma => "fma", sym::simd_relaxed_fma => "fma", // FIXME: this should relax to non-fused multiply-add when necessary - sym::simd_fpowi => "__builtin_powi", - sym::simd_fpow => "pow", sym::simd_fsin => "sin", sym::simd_fsqrt => "sqrt", sym::simd_round => "round", @@ -788,24 +786,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let mut vector_elements = vec![]; for i in 0..in_len { let index = bx.context.new_rvalue_from_long(bx.ulong_type, i as i64); - // we have to treat fpowi specially, since fpowi's second argument is always an i32 let mut arguments = vec![]; - if name == sym::simd_fpowi { - arguments = vec![ - bx.extract_element(args[0].immediate(), index).to_rvalue(), - args[1].immediate(), - ]; - } else { - for arg in args { - let mut element = bx.extract_element(arg.immediate(), index).to_rvalue(); - // FIXME: it would probably be better to not have casts here and use the proper - // instructions. - if let Some(typ) = cast_type { - element = bx.context.new_cast(None, element, typ); - } - arguments.push(element); + for arg in args { + let mut element = bx.extract_element(arg.immediate(), index).to_rvalue(); + // FIXME: it would probably be better to not have casts here and use the proper + // instructions. + if let Some(typ) = cast_type { + element = bx.context.new_cast(None, element, typ); } - }; + arguments.push(element); + } let mut result = bx.context.new_call(None, function, &arguments); if cast_type.is_some() { result = bx.context.new_cast(None, result, elem_ty); @@ -829,8 +819,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( | sym::simd_floor | sym::simd_fma | sym::simd_relaxed_fma - | sym::simd_fpow - | sym::simd_fpowi | sym::simd_fsin | sym::simd_fsqrt | sym::simd_round From 44f27329c0095fe5d13fe07d8a7a6fb183f68877 Mon Sep 17 00:00:00 2001 From: duncan Date: Wed, 22 Jan 2025 14:27:27 +0000 Subject: [PATCH 0062/2248] fix testing for packages with multiple targets fix test running by invoking cargo per package remove hack_recover_crate_name make clippy happy fix testing for packages with multiple targets fix test running by invoking cargo per package remove hack_recover_crate_name make clippy happy fix testing for packages with multiple targets fix bad merge replace TargetKind::fmt with TargetKind::as_cargo_target to clarify intention dedupulicate requested test runs replace ParseFromLine with CargoParser formatting - remove trailing space formatting for rustfmt CI --- .../project-model/src/cargo_workspace.rs | 17 +++ .../crates/rust-analyzer/src/command.rs | 39 ++++-- .../crates/rust-analyzer/src/discover.rs | 12 +- .../crates/rust-analyzer/src/flycheck.rs | 12 +- .../src/hack_recover_crate_name.rs | 25 ---- .../rust-analyzer/src/handlers/request.rs | 121 ++++++++++-------- .../crates/rust-analyzer/src/lib.rs | 1 - .../crates/rust-analyzer/src/main_loop.rs | 22 ++-- .../crates/rust-analyzer/src/test_runner.rs | 80 ++++++++---- 9 files changed, 186 insertions(+), 143 deletions(-) delete mode 100644 src/tools/rust-analyzer/crates/rust-analyzer/src/hack_recover_crate_name.rs diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 40ab8c53faeb8..1a9501c0638bc 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -224,6 +224,7 @@ pub enum TargetKind { Example, Test, Bench, + /// Cargo calls this kind `custom-build` BuildScript, Other, } @@ -252,6 +253,22 @@ impl TargetKind { pub fn is_proc_macro(self) -> bool { matches!(self, TargetKind::Lib { is_proc_macro: true }) } + + /// If this is a valid cargo target, returns the name cargo uses in command line arguments + /// and output, otherwise None. + /// https://docs.rs/cargo_metadata/latest/cargo_metadata/enum.TargetKind.html + pub fn as_cargo_target(self) -> Option<&'static str> { + match self { + TargetKind::Bin => Some("bin"), + TargetKind::Lib { is_proc_macro: true } => Some("proc-macro"), + TargetKind::Lib { is_proc_macro: false } => Some("lib"), + TargetKind::Example => Some("example"), + TargetKind::Test => Some("test"), + TargetKind::Bench => Some("bench"), + TargetKind::BuildScript => Some("custom-build"), + TargetKind::Other => None, + } + } } #[derive(Default, Clone, Debug, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs index b19a1b8d16700..8e2d3d52b8770 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs @@ -13,24 +13,33 @@ use crossbeam_channel::Sender; use process_wrap::std::{StdChildWrapper, StdCommandWrap}; use stdx::process::streaming_output; -/// Cargo output is structured as a one JSON per line. This trait abstracts parsing one line of -/// cargo output into a Rust data type. -pub(crate) trait ParseFromLine: Sized + Send + 'static { - fn from_line(line: &str, error: &mut String) -> Option; - fn from_eof() -> Option; +/// Cargo output is structured as one JSON per line. This trait abstracts parsing one line of +/// cargo output into a Rust data type +pub(crate) trait CargoParser: Send + 'static { + fn from_line(&self, line: &str, error: &mut String) -> Option; + fn from_eof(&self) -> Option; } struct CargoActor { + parser: Box>, sender: Sender, stdout: ChildStdout, stderr: ChildStderr, } -impl CargoActor { - fn new(sender: Sender, stdout: ChildStdout, stderr: ChildStderr) -> Self { - CargoActor { sender, stdout, stderr } +impl CargoActor { + fn new( + parser: impl CargoParser, + sender: Sender, + stdout: ChildStdout, + stderr: ChildStderr, + ) -> Self { + let parser = Box::new(parser); + CargoActor { parser, sender, stdout, stderr } } +} +impl CargoActor { fn run(self) -> io::Result<(bool, String)> { // We manually read a line at a time, instead of using serde's // stream deserializers, because the deserializer cannot recover @@ -47,7 +56,7 @@ impl CargoActor { let mut read_at_least_one_stderr_message = false; let process_line = |line: &str, error: &mut String| { // Try to deserialize a message from Cargo or Rustc. - if let Some(t) = T::from_line(line, error) { + if let Some(t) = self.parser.from_line(line, error) { self.sender.send(t).unwrap(); true } else { @@ -68,7 +77,7 @@ impl CargoActor { } }, &mut || { - if let Some(t) = T::from_eof() { + if let Some(t) = self.parser.from_eof() { self.sender.send(t).unwrap(); } }, @@ -116,8 +125,12 @@ impl fmt::Debug for CommandHandle { } } -impl CommandHandle { - pub(crate) fn spawn(mut command: Command, sender: Sender) -> std::io::Result { +impl CommandHandle { + pub(crate) fn spawn( + mut command: Command, + parser: impl CargoParser, + sender: Sender, + ) -> std::io::Result { command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null()); let program = command.get_program().into(); @@ -134,7 +147,7 @@ impl CommandHandle { let stdout = child.0.stdout().take().unwrap(); let stderr = child.0.stderr().take().unwrap(); - let actor = CargoActor::::new(sender, stdout, stderr); + let actor = CargoActor::::new(parser, sender, stdout, stderr); let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) .name("CommandHandle".to_owned()) .spawn(move || actor.run()) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs index 0c111319bb41b..09de309ce9564 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use tracing::{info_span, span::EnteredSpan}; -use crate::command::{CommandHandle, ParseFromLine}; +use crate::command::{CargoParser, CommandHandle}; pub(crate) const ARG_PLACEHOLDER: &str = "{arg}"; @@ -66,7 +66,7 @@ impl DiscoverCommand { cmd.args(args); Ok(DiscoverHandle { - _handle: CommandHandle::spawn(cmd, self.sender.clone())?, + _handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone())?, span: info_span!("discover_command").entered(), }) } @@ -115,8 +115,10 @@ impl DiscoverProjectMessage { } } -impl ParseFromLine for DiscoverProjectMessage { - fn from_line(line: &str, _error: &mut String) -> Option { +struct DiscoverProjectParser; + +impl CargoParser for DiscoverProjectParser { + fn from_line(&self, line: &str, _error: &mut String) -> Option { // can the line even be deserialized as JSON? let Ok(data) = serde_json::from_str::(line) else { let err = DiscoverProjectData::Error { error: line.to_owned(), source: None }; @@ -131,7 +133,7 @@ impl ParseFromLine for DiscoverProjectMessage { Some(msg) } - fn from_eof() -> Option { + fn from_eof(&self) -> Option { None } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs index 2309f94a7429b..1e46d9ba56d5f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs @@ -17,7 +17,7 @@ pub(crate) use cargo_metadata::diagnostic::{ use toolchain::Tool; use triomphe::Arc; -use crate::command::{CommandHandle, ParseFromLine}; +use crate::command::{CargoParser, CommandHandle}; #[derive(Clone, Debug, Default, PartialEq, Eq)] pub(crate) enum InvocationStrategy { @@ -324,7 +324,7 @@ impl FlycheckActor { tracing::debug!(?command, "will restart flycheck"); let (sender, receiver) = unbounded(); - match CommandHandle::spawn(command, sender) { + match CommandHandle::spawn(command, CargoCheckParser, sender) { Ok(command_handle) => { tracing::debug!(command = formatted_command, "did restart flycheck"); self.command_handle = Some(command_handle); @@ -550,8 +550,10 @@ enum CargoCheckMessage { Diagnostic { diagnostic: Diagnostic, package_id: Option> }, } -impl ParseFromLine for CargoCheckMessage { - fn from_line(line: &str, error: &mut String) -> Option { +struct CargoCheckParser; + +impl CargoParser for CargoCheckParser { + fn from_line(&self, line: &str, error: &mut String) -> Option { let mut deserializer = serde_json::Deserializer::from_str(line); deserializer.disable_recursion_limit(); if let Ok(message) = JsonMessage::deserialize(&mut deserializer) { @@ -580,7 +582,7 @@ impl ParseFromLine for CargoCheckMessage { None } - fn from_eof() -> Option { + fn from_eof(&self) -> Option { None } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/hack_recover_crate_name.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/hack_recover_crate_name.rs deleted file mode 100644 index d7285653c5fa5..0000000000000 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/hack_recover_crate_name.rs +++ /dev/null @@ -1,25 +0,0 @@ -//! Currently cargo does not emit crate name in the `cargo test --format=json`, which needs to be changed. This -//! module contains a way to recover crate names in a very hacky and wrong way. - -// FIXME(hack_recover_crate_name): Remove this module. - -use std::sync::{Mutex, MutexGuard, OnceLock}; - -use ide_db::FxHashMap; - -static STORAGE: OnceLock>> = OnceLock::new(); - -fn get_storage() -> MutexGuard<'static, FxHashMap> { - STORAGE.get_or_init(|| Mutex::new(FxHashMap::default())).lock().unwrap() -} - -pub(crate) fn insert_name(name_with_crate: String) { - let Some((_, name_without_crate)) = name_with_crate.split_once("::") else { - return; - }; - get_storage().insert(name_without_crate.to_owned(), name_with_crate); -} - -pub(crate) fn lookup_name(name_without_crate: String) -> Option { - get_storage().get(&name_without_crate).cloned() -} diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index b91a5dbd4166f..1410138da82ef 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -36,7 +36,6 @@ use crate::{ config::{Config, RustfmtConfig, WorkspaceSymbolConfig}, diagnostics::convert_diagnostic, global_state::{FetchWorkspaceRequest, GlobalState, GlobalStateSnapshot}, - hack_recover_crate_name, line_index::LineEndings, lsp::{ ext::{ @@ -196,20 +195,48 @@ pub(crate) fn handle_view_item_tree( Ok(res) } -// cargo test requires the real package name which might contain hyphens but -// the test identifier passed to this function is the namespace form where hyphens -// are replaced with underscores so we have to reverse this and find the real package name -fn find_package_name(namespace_root: &str, cargo: &CargoWorkspace) -> Option { +// cargo test requires: +// - the package name - the root of the test identifier supplied to this handler can be +// a package or a target inside a package. +// - the target name - if the test identifier is a target, it's needed in addition to the +// package name to run the right test +// - real names - the test identifier uses the namespace form where hyphens are replaced with +// underscores. cargo test requires the real name. +// - the target kind e.g. bin or lib +fn find_test_target(namespace_root: &str, cargo: &CargoWorkspace) -> Option { cargo.packages().find_map(|p| { let package_name = &cargo[p].name; - if package_name.replace('-', "_") == namespace_root { - Some(package_name.clone()) - } else { - None + for target in cargo[p].targets.iter() { + let target_name = &cargo[*target].name; + if target_name.replace('-', "_") == namespace_root { + return Some(TestTarget { + package: package_name.clone(), + target: target_name.clone(), + kind: cargo[*target].kind, + }); + } } + None }) } +fn get_all_targets(cargo: &CargoWorkspace) -> Vec { + cargo + .packages() + .flat_map(|p| { + let package_name = &cargo[p].name; + cargo[p].targets.iter().map(|target| { + let target_name = &cargo[*target].name; + TestTarget { + package: package_name.clone(), + target: target_name.clone(), + kind: cargo[*target].kind, + } + }) + }) + .collect() +} + pub(crate) fn handle_run_test( state: &mut GlobalState, params: lsp_ext::RunTestParams, @@ -217,53 +244,41 @@ pub(crate) fn handle_run_test( if let Some(_session) = state.test_run_session.take() { state.send_notification::(()); } - // We detect the lowest common ancestor of all included tests, and - // run it. We ignore excluded tests for now, the client will handle - // it for us. - let lca = match params.include { - Some(tests) => tests - .into_iter() - .reduce(|x, y| { - let mut common_prefix = "".to_owned(); - for (xc, yc) in x.chars().zip(y.chars()) { - if xc != yc { - break; - } - common_prefix.push(xc); - } - common_prefix - }) - .unwrap_or_default(), - None => "".to_owned(), - }; - let (namespace_root, test_path) = if lca.is_empty() { - (None, None) - } else if let Some((namespace_root, path)) = lca.split_once("::") { - (Some(namespace_root), Some(path)) - } else { - (Some(lca.as_str()), None) - }; + let mut handles = vec![]; for ws in &*state.workspaces { if let ProjectWorkspaceKind::Cargo { cargo, .. } = &ws.kind { - let test_target = if let Some(namespace_root) = namespace_root { - if let Some(package_name) = find_package_name(namespace_root, cargo) { - TestTarget::Package(package_name) - } else { - TestTarget::Workspace - } - } else { - TestTarget::Workspace + // need to deduplicate `include` to avoid redundant test runs + let tests = match params.include { + Some(ref include) => include + .iter() + .unique() + .filter_map(|test| { + let (root, remainder) = match test.split_once("::") { + Some((root, remainder)) => (root.to_owned(), Some(remainder)), + None => (test.clone(), None), + }; + if let Some(target) = find_test_target(&root, cargo) { + Some((target, remainder)) + } else { + tracing::error!("Test target not found for: {test}"); + None + } + }) + .collect_vec(), + None => get_all_targets(cargo).into_iter().map(|target| (target, None)).collect(), }; - let handle = CargoTestHandle::new( - test_path, - state.config.cargo_test_options(None), - cargo.workspace_root(), - test_target, - state.test_run_sender.clone(), - )?; - handles.push(handle); + for (target, path) in tests { + let handle = CargoTestHandle::new( + path, + state.config.cargo_test_options(None), + cargo.workspace_root(), + target, + state.test_run_sender.clone(), + )?; + handles.push(handle); + } } } // Each process send finished signal twice, once for stdout and once for stderr @@ -287,9 +302,7 @@ pub(crate) fn handle_discover_test( } None => (snap.analysis.discover_test_roots()?, None), }; - for t in &tests { - hack_recover_crate_name::insert_name(t.id.clone()); - } + Ok(lsp_ext::DiscoverTestResults { tests: tests .into_iter() diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs index 27d6225cdb7e2..daf75e86e6409 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs @@ -15,7 +15,6 @@ mod command; mod diagnostics; mod discover; mod flycheck; -mod hack_recover_crate_name; mod line_index; mod main_loop; mod mem_docs; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index f5d9469f2622f..e63572d81a5ae 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -26,7 +26,6 @@ use crate::{ file_id_to_url, url_to_file_id, FetchBuildDataResponse, FetchWorkspaceRequest, FetchWorkspaceResponse, GlobalState, }, - hack_recover_crate_name, handlers::{ dispatch::{NotificationDispatcher, RequestDispatcher}, request::empty_diagnostic_report, @@ -37,7 +36,7 @@ use crate::{ }, lsp_ext, reload::{BuildDataProgress, ProcMacroProgress, ProjectWorkspaceProgress}, - test_runner::{CargoTestMessage, TestState}, + test_runner::{CargoTestMessage, CargoTestOutput, TestState}, }; pub fn main_loop(config: Config, connection: Connection) -> anyhow::Result<()> { @@ -659,9 +658,7 @@ impl GlobalState { .filter_map(|f| snapshot.analysis.discover_tests_in_file(f).ok()) .flatten() .collect::>(); - for t in &tests { - hack_recover_crate_name::insert_name(t.id.clone()); - } + Task::DiscoverTest(lsp_ext::DiscoverTestResults { tests: tests .into_iter() @@ -958,30 +955,29 @@ impl GlobalState { } fn handle_cargo_test_msg(&mut self, message: CargoTestMessage) { - match message { - CargoTestMessage::Test { name, state } => { + match message.output { + CargoTestOutput::Test { name, state } => { let state = match state { TestState::Started => lsp_ext::TestState::Started, TestState::Ignored => lsp_ext::TestState::Skipped, TestState::Ok => lsp_ext::TestState::Passed, TestState::Failed { stdout } => lsp_ext::TestState::Failed { message: stdout }, }; - let Some(test_id) = hack_recover_crate_name::lookup_name(name) else { - return; - }; + let test_id = format!("{}::{name}", message.target.target); + self.send_notification::( lsp_ext::ChangeTestStateParams { test_id, state }, ); } - CargoTestMessage::Suite => (), - CargoTestMessage::Finished => { + CargoTestOutput::Suite => (), + CargoTestOutput::Finished => { self.test_run_remaining_jobs = self.test_run_remaining_jobs.saturating_sub(1); if self.test_run_remaining_jobs == 0 { self.send_notification::(()); self.test_run_session = None; } } - CargoTestMessage::Custom { text } => { + CargoTestOutput::Custom { text } => { self.send_notification::(text); } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs index 3edfb812cf5cf..f245c6ac4bf69 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs @@ -3,12 +3,13 @@ use crossbeam_channel::Sender; use paths::AbsPath; +use project_model::TargetKind; use serde::Deserialize as _; use serde_derive::Deserialize; use toolchain::Tool; use crate::{ - command::{CommandHandle, ParseFromLine}, + command::{CargoParser, CommandHandle}, flycheck::CargoOptions, }; @@ -25,9 +26,15 @@ pub(crate) enum TestState { }, } +#[derive(Debug)] +pub(crate) struct CargoTestMessage { + pub target: TestTarget, + pub output: CargoTestOutput, +} + #[derive(Debug, Deserialize)] #[serde(tag = "type", rename_all = "camelCase")] -pub(crate) enum CargoTestMessage { +pub(crate) enum CargoTestOutput { Test { name: String, #[serde(flatten)] @@ -40,19 +47,33 @@ pub(crate) enum CargoTestMessage { }, } -impl ParseFromLine for CargoTestMessage { - fn from_line(line: &str, _: &mut String) -> Option { +pub(crate) struct CargoTestOutputParser { + pub target: TestTarget, +} + +impl CargoTestOutputParser { + pub(crate) fn new(test_target: &TestTarget) -> Self { + Self { target: test_target.clone() } + } +} + +impl CargoParser for CargoTestOutputParser { + fn from_line(&self, line: &str, _error: &mut String) -> Option { let mut deserializer = serde_json::Deserializer::from_str(line); deserializer.disable_recursion_limit(); - if let Ok(message) = CargoTestMessage::deserialize(&mut deserializer) { - return Some(message); - } - Some(CargoTestMessage::Custom { text: line.to_owned() }) + Some(CargoTestMessage { + target: self.target.clone(), + output: if let Ok(message) = CargoTestOutput::deserialize(&mut deserializer) { + message + } else { + CargoTestOutput::Custom { text: line.to_owned() } + }, + }) } - fn from_eof() -> Option { - Some(CargoTestMessage::Finished) + fn from_eof(&self) -> Option { + Some(CargoTestMessage { target: self.target.clone(), output: CargoTestOutput::Finished }) } } @@ -62,14 +83,14 @@ pub(crate) struct CargoTestHandle { } // Example of a cargo test command: -// cargo test --workspace --no-fail-fast -- -Z unstable-options --format=json -// or -// cargo test --package my-package --no-fail-fast -- module::func -Z unstable-options --format=json +// +// cargo test --package my-package --bin my_bin --no-fail-fast -- module::func -Z unstable-options --format=json -#[derive(Debug)] -pub(crate) enum TestTarget { - Workspace, - Package(String), +#[derive(Debug, Clone)] +pub(crate) struct TestTarget { + pub package: String, + pub target: String, + pub kind: TargetKind, } impl CargoTestHandle { @@ -84,15 +105,18 @@ impl CargoTestHandle { cmd.env("RUSTC_BOOTSTRAP", "1"); cmd.arg("test"); - match &test_target { - TestTarget::Package(package) => { - cmd.arg("--package"); - cmd.arg(package); - } - TestTarget::Workspace => { - cmd.arg("--workspace"); - } - }; + cmd.arg("--package"); + cmd.arg(&test_target.package); + + if let TargetKind::Lib { .. } = test_target.kind { + // no name required with lib because there can only be one lib target per package + cmd.arg("--lib"); + } else if let Some(cargo_target) = test_target.kind.as_cargo_target() { + cmd.arg(format!("--{cargo_target}")); + cmd.arg(&test_target.target); + } else { + tracing::warn!("Running test for unknown cargo target {:?}", test_target.kind); + } // --no-fail-fast is needed to ensure that all requested tests will run cmd.arg("--no-fail-fast"); @@ -110,6 +134,8 @@ impl CargoTestHandle { cmd.arg(extra_arg); } - Ok(Self { _handle: CommandHandle::spawn(cmd, sender)? }) + Ok(Self { + _handle: CommandHandle::spawn(cmd, CargoTestOutputParser::new(&test_target), sender)?, + }) } } From 92fc2bb2b8e2640baa9f8e6ac73d209e506ec99c Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Thu, 27 Feb 2025 14:21:12 +0000 Subject: [PATCH 0063/2248] Emit `collapsible_match` at the right node --- clippy_lints/src/matches/collapsible_match.rs | 4 ++-- tests/ui/collapsible_match.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs index 97e8423695d99..4c46084db875f 100644 --- a/clippy_lints/src/matches/collapsible_match.rs +++ b/clippy_lints/src/matches/collapsible_match.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::higher::IfLetOrMatch; use clippy_utils::msrvs::Msrv; use clippy_utils::source::snippet; @@ -99,7 +99,7 @@ fn check_arm<'tcx>( } else { String::new() }; - span_lint_and_then(cx, COLLAPSIBLE_MATCH, inner_expr.span, msg, |diag| { + span_lint_hir_and_then(cx, COLLAPSIBLE_MATCH, inner_expr.hir_id, inner_expr.span, msg, |diag| { let mut help_span = MultiSpan::from_spans(vec![binding_span, inner_then_pat.span]); help_span.push_span_label(binding_span, "replace this binding"); help_span.push_span_label(inner_then_pat.span, format!("with this pattern{replace_msg}")); diff --git a/tests/ui/collapsible_match.rs b/tests/ui/collapsible_match.rs index 796cabd4b669a..55ef55844957a 100644 --- a/tests/ui/collapsible_match.rs +++ b/tests/ui/collapsible_match.rs @@ -303,6 +303,18 @@ pub fn test_2(x: Issue9647) { } } +// https://github.com/rust-lang/rust-clippy/issues/14281 +fn lint_emitted_at_right_node(opt: Option>) { + let n = match opt { + #[expect(clippy::collapsible_match)] + Some(n) => match n { + Ok(n) => n, + _ => return, + }, + None => return, + }; +} + fn make() -> T { unimplemented!() } From 7721431d57f7c8eea818d39d7a284459bb15f6e3 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 27 Feb 2025 09:09:52 -0800 Subject: [PATCH 0064/2248] Stop using `hash_raw_entry` in `CodegenCx::const_str` That unstable feature completed fcp-close, so the compiler needs to be migrated away to allow its removal. In this case, `cg_llvm` and `cg_gcc` were using raw entries to optimize their `const_str_cache` lookup and insertion. We can change that to separate `get` and (on miss) `insert` calls, so we still have the fast path avoiding string allocation when the cache hits. --- src/common.rs | 13 ++++++------- src/lib.rs | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/common.rs b/src/common.rs index 20a3482aaa27f..ce1a200886478 100644 --- a/src/common.rs +++ b/src/common.rs @@ -146,13 +146,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn const_str(&self, s: &str) -> (RValue<'gcc>, RValue<'gcc>) { - let str_global = *self - .const_str_cache - .borrow_mut() - .raw_entry_mut() - .from_key(s) - .or_insert_with(|| (s.to_owned(), self.global_string(s))) - .1; + let mut const_str_cache = self.const_str_cache.borrow_mut(); + let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| { + let g = self.global_string(s); + const_str_cache.insert(s.to_owned(), g); + g + }); let len = s.len(); let cs = self.const_ptrcast( str_global.get_address(None), diff --git a/src/lib.rs b/src/lib.rs index 6455bcec6851b..7413868767901 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ #![allow(internal_features)] #![doc(rust_logo)] #![feature(rustdoc_internals)] -#![feature(rustc_private, decl_macro, never_type, trusted_len, hash_raw_entry, let_chains)] +#![feature(rustc_private, decl_macro, never_type, trusted_len, let_chains)] #![allow(broken_intra_doc_links)] #![recursion_limit = "256"] #![warn(rust_2018_idioms)] From e1d6f1fc5ca8ec2a69033a7c506a0a7a824fc8e8 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 16 Feb 2025 17:21:08 +0100 Subject: [PATCH 0065/2248] Use a lintcheck specific Clippy configuration file in the CI By default, lintcheck will use the `clippy.toml` file found at the toplevel of the repository (`CARGO_MANIFEST_DIR`). This file is meant for configuration of Clippy applied to Clippy sources. This creates a new `lintcheck/ci-config/clippy.toml` file which is used by the CI when running lintcheck. By default this uses the default Clippy configuration. --- .github/workflows/lintcheck.yml | 4 ++-- lintcheck/ci-config/clippy.toml | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 lintcheck/ci-config/clippy.toml diff --git a/.github/workflows/lintcheck.yml b/.github/workflows/lintcheck.yml index d487c7d949857..70c805903d36e 100644 --- a/.github/workflows/lintcheck.yml +++ b/.github/workflows/lintcheck.yml @@ -66,7 +66,7 @@ jobs: - name: Run lintcheck if: steps.cache-json.outputs.cache-hit != 'true' - run: ./target/debug/lintcheck --format json --all-lints --crates-toml ./lintcheck/ci_crates.toml + run: env CLIPPY_CONF_DIR="$PWD/lintcheck/ci-config" ./target/debug/lintcheck --format json --all-lints --crates-toml ./lintcheck/ci_crates.toml - name: Upload base JSON uses: actions/upload-artifact@v4 @@ -97,7 +97,7 @@ jobs: run: cargo build --manifest-path=lintcheck/Cargo.toml - name: Run lintcheck - run: ./target/debug/lintcheck --format json --all-lints --crates-toml ./lintcheck/ci_crates.toml + run: env CLIPPY_CONF_DIR="$PWD/lintcheck/ci-config" ./target/debug/lintcheck --format json --all-lints --crates-toml ./lintcheck/ci_crates.toml - name: Upload head JSON uses: actions/upload-artifact@v4 diff --git a/lintcheck/ci-config/clippy.toml b/lintcheck/ci-config/clippy.toml new file mode 100644 index 0000000000000..d9eb2ef90dba2 --- /dev/null +++ b/lintcheck/ci-config/clippy.toml @@ -0,0 +1,6 @@ +# Configuration applied when running lintcheck from the CI +# +# The CI will set the `CLIPPY_CONF_DIR` environment variable +# to `$PWD/lintcheck/ci-config`. + +avoid-breaking-exported-api = false From 3caa1f25d883b8c5a5695b0c9a7717c8ff521a56 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 21 Feb 2025 08:29:10 +0100 Subject: [PATCH 0066/2248] Add regression tests for `suspicious_doc_comments` --- tests/ui/suspicious_doc_comments.fixed | 4 ++++ tests/ui/suspicious_doc_comments.rs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/tests/ui/suspicious_doc_comments.fixed b/tests/ui/suspicious_doc_comments.fixed index 3696b0e066d28..3faa4b21ee414 100644 --- a/tests/ui/suspicious_doc_comments.fixed +++ b/tests/ui/suspicious_doc_comments.fixed @@ -87,4 +87,8 @@ pub mod useless_outer_doc { use std::mem; } +// Do not lint, this is not a `///!` +#[doc = "! here's some docs !"] +fn issue14265() {} + fn main() {} diff --git a/tests/ui/suspicious_doc_comments.rs b/tests/ui/suspicious_doc_comments.rs index 4107f5526d132..4af6ed850c2bb 100644 --- a/tests/ui/suspicious_doc_comments.rs +++ b/tests/ui/suspicious_doc_comments.rs @@ -87,4 +87,8 @@ pub mod useless_outer_doc { use std::mem; } +// Do not lint, this is not a `///!` +#[doc = "! here's some docs !"] +fn issue14265() {} + fn main() {} From 975dee20ef70423c00a617867fa78e7ae9f63fce Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Feb 2025 16:29:07 +0100 Subject: [PATCH 0067/2248] =?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/intrinsic/mod.rs | 2 +- src/type_of.rs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index f8672c0729998..f38622074f18b 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -312,7 +312,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let layout = self.layout_of(tp_ty).layout; let _use_integer_compare = match layout.backend_repr() { Scalar(_) | ScalarPair(_, _) => true, - Vector { .. } => false, + SimdVector { .. } => false, Memory { .. } => { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), diff --git a/src/type_of.rs b/src/type_of.rs index bac4fc51300a2..ae98b3d0b56e2 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -63,7 +63,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( ) -> Type<'gcc> { match layout.backend_repr { BackendRepr::Scalar(_) => bug!("handled elsewhere"), - BackendRepr::Vector { ref element, count } => { + BackendRepr::SimdVector { ref element, count } => { let element = layout.scalar_gcc_type_at(cx, element, Size::ZERO); let element = // NOTE: gcc doesn't allow pointer types in vectors. @@ -178,7 +178,7 @@ pub trait LayoutGccExt<'tcx> { impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { fn is_gcc_immediate(&self) -> bool { match self.backend_repr { - BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, + BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => true, BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false, } } @@ -186,9 +186,9 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { fn is_gcc_scalar_pair(&self) -> bool { match self.backend_repr { BackendRepr::ScalarPair(..) => true, - BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => { - false - } + BackendRepr::Scalar(_) + | BackendRepr::SimdVector { .. } + | BackendRepr::Memory { .. } => false, } } From 31236a491571f6fcf3d3be458ada764848f85734 Mon Sep 17 00:00:00 2001 From: Vishruth-Thimmaiah Date: Wed, 29 Jan 2025 15:06:03 +0530 Subject: [PATCH 0068/2248] fix[`missing_asserts_for_indexing`]: ignore asserts after indexing --- .../src/missing_asserts_for_indexing.rs | 19 ++++++++++------- .../missing_asserts_for_indexing_unfixable.rs | 6 ++++++ ...sing_asserts_for_indexing_unfixable.stderr | 21 ++++++++++++++++++- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs index d78299fe08be8..5ce3e73ae16de 100644 --- a/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/clippy_lints/src/missing_asserts_for_indexing.rs @@ -244,14 +244,16 @@ fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Uni assert_span, slice, } => { - *entry = IndexEntry::AssertWithIndex { - highest_index: index, - asserted_len: *asserted_len, - assert_span: *assert_span, - slice, - indexes: vec![expr.span], - comparison: *comparison, - }; + if slice.span.lo() > assert_span.lo() { + *entry = IndexEntry::AssertWithIndex { + highest_index: index, + asserted_len: *asserted_len, + assert_span: *assert_span, + slice, + indexes: vec![expr.span], + comparison: *comparison, + }; + } }, IndexEntry::IndexWithoutAssert { highest_index, indexes, .. @@ -287,6 +289,7 @@ fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Un indexes, slice, } = entry + && expr.span.lo() <= slice.span.lo() { *entry = IndexEntry::AssertWithIndex { highest_index: *highest_index, diff --git a/tests/ui/missing_asserts_for_indexing_unfixable.rs b/tests/ui/missing_asserts_for_indexing_unfixable.rs index a520151a2dd94..2fac9d7a59c2d 100644 --- a/tests/ui/missing_asserts_for_indexing_unfixable.rs +++ b/tests/ui/missing_asserts_for_indexing_unfixable.rs @@ -73,4 +73,10 @@ pub fn issue11856(values: &[i32]) -> usize { ascending.len() } +fn assert_after_indexing(v1: &[u8]) { + let _ = v1[1] + v1[2]; + //~^ ERROR: indexing into a slice multiple times without an `assert` + assert!(v1.len() > 2); +} + fn main() {} diff --git a/tests/ui/missing_asserts_for_indexing_unfixable.stderr b/tests/ui/missing_asserts_for_indexing_unfixable.stderr index 24109b052a8af..1674861c9ed76 100644 --- a/tests/ui/missing_asserts_for_indexing_unfixable.stderr +++ b/tests/ui/missing_asserts_for_indexing_unfixable.stderr @@ -180,5 +180,24 @@ LL | let _ = x[0] + x[1]; | ^^^^ = note: asserting the length before indexing will elide bounds checks -error: aborting due to 8 previous errors +error: indexing into a slice multiple times without an `assert` + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:77:13 + | +LL | let _ = v1[1] + v1[2]; + | ^^^^^^^^^^^^^ + | + = help: consider asserting the length before indexing: `assert!(v1.len() > 2);` +note: slice indexed here + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:77:13 + | +LL | let _ = v1[1] + v1[2]; + | ^^^^^ +note: slice indexed here + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:77:21 + | +LL | let _ = v1[1] + v1[2]; + | ^^^^^ + = note: asserting the length before indexing will elide bounds checks + +error: aborting due to 9 previous errors From 2cd3ea1f9d756f9029e969ed1758492e7620ab99 Mon Sep 17 00:00:00 2001 From: Vishruth-Thimmaiah Date: Wed, 29 Jan 2025 19:27:32 +0530 Subject: [PATCH 0069/2248] fix[`missing_asserts_for_indexing`]: ignore lint if first index is highest --- .../src/missing_asserts_for_indexing.rs | 25 ++++++++++++++++--- tests/ui/missing_asserts_for_indexing.fixed | 10 ++++++++ tests/ui/missing_asserts_for_indexing.rs | 10 ++++++++ 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs index 5ce3e73ae16de..d9acf655b8af9 100644 --- a/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/clippy_lints/src/missing_asserts_for_indexing.rs @@ -168,6 +168,7 @@ enum IndexEntry<'hir> { /// if the `assert!` asserts the right length. AssertWithIndex { highest_index: usize, + is_first_highest: bool, asserted_len: usize, assert_span: Span, slice: &'hir Expr<'hir>, @@ -177,6 +178,7 @@ enum IndexEntry<'hir> { /// Indexing without an `assert!` IndexWithoutAssert { highest_index: usize, + is_first_highest: bool, indexes: Vec, slice: &'hir Expr<'hir>, }, @@ -247,6 +249,7 @@ fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Uni if slice.span.lo() > assert_span.lo() { *entry = IndexEntry::AssertWithIndex { highest_index: index, + is_first_highest: true, asserted_len: *asserted_len, assert_span: *assert_span, slice, @@ -256,18 +259,28 @@ fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Uni } }, IndexEntry::IndexWithoutAssert { - highest_index, indexes, .. + highest_index, + indexes, + is_first_highest, + .. } | IndexEntry::AssertWithIndex { - highest_index, indexes, .. + highest_index, + indexes, + is_first_highest, + .. } => { indexes.push(expr.span); + if *is_first_highest { + (*is_first_highest) = *highest_index >= index; + } *highest_index = (*highest_index).max(index); }, } } else { indexes.push(IndexEntry::IndexWithoutAssert { highest_index: index, + is_first_highest: true, indexes: vec![expr.span], slice, }); @@ -286,6 +299,7 @@ fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Un if let Some(entry) = entry { if let IndexEntry::IndexWithoutAssert { highest_index, + is_first_highest, indexes, slice, } = entry @@ -294,6 +308,7 @@ fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Un *entry = IndexEntry::AssertWithIndex { highest_index: *highest_index, indexes: mem::take(indexes), + is_first_highest: *is_first_highest, slice, assert_span: expr.span, comparison, @@ -328,12 +343,13 @@ fn report_indexes(cx: &LateContext<'_>, map: &UnindexMap match *entry { IndexEntry::AssertWithIndex { highest_index, + is_first_highest, asserted_len, ref indexes, comparison, assert_span, slice, - } if indexes.len() > 1 => { + } if indexes.len() > 1 && !is_first_highest => { // if we have found an `assert!`, let's also check that it's actually right // and if it covers the highest index and if not, suggest the correct length let sugg = match comparison { @@ -381,8 +397,9 @@ fn report_indexes(cx: &LateContext<'_>, map: &UnindexMap IndexEntry::IndexWithoutAssert { ref indexes, highest_index, + is_first_highest, slice, - } if indexes.len() > 1 => { + } if indexes.len() > 1 && !is_first_highest => { // if there was no `assert!` but more than one index, suggest // adding an `assert!` that covers the highest index report_lint( diff --git a/tests/ui/missing_asserts_for_indexing.fixed b/tests/ui/missing_asserts_for_indexing.fixed index 3bbafe0bba3fe..6e803322f65ae 100644 --- a/tests/ui/missing_asserts_for_indexing.fixed +++ b/tests/ui/missing_asserts_for_indexing.fixed @@ -139,4 +139,14 @@ fn issue11835(v1: &[u8], v2: &[u8], v3: &[u8], v4: &[u8]) { let _ = v4[0] + v4[1] + v4[2]; } +// ok +fn same_index_multiple_times(v1: &[u8]) { + let _ = v1[0] + v1[0]; +} + +// ok +fn highest_index_first(v1: &[u8]) { + let _ = v1[2] + v1[1] + v1[0]; +} + fn main() {} diff --git a/tests/ui/missing_asserts_for_indexing.rs b/tests/ui/missing_asserts_for_indexing.rs index f8ea0173c13fc..4614a8ef5d0de 100644 --- a/tests/ui/missing_asserts_for_indexing.rs +++ b/tests/ui/missing_asserts_for_indexing.rs @@ -139,4 +139,14 @@ fn issue11835(v1: &[u8], v2: &[u8], v3: &[u8], v4: &[u8]) { let _ = v4[0] + v4[1] + v4[2]; } +// ok +fn same_index_multiple_times(v1: &[u8]) { + let _ = v1[0] + v1[0]; +} + +// ok +fn highest_index_first(v1: &[u8]) { + let _ = v1[2] + v1[1] + v1[0]; +} + fn main() {} From 80046158ba9a2bd6900529251ac6a87a07f4030c Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 28 Feb 2025 19:55:42 -0800 Subject: [PATCH 0070/2248] Use `BinOp::Cmp` for `iNN::signum` This way it can use the nice new LLVM intrinsic in LLVM20. --- library/core/src/intrinsics/mod.rs | 10 ++++++---- library/core/src/num/int_macros.rs | 5 +---- ..._way_compare_char.LowerIntrinsics.panic-unwind.diff | 2 +- ...ay_compare_signed.LowerIntrinsics.panic-unwind.diff | 2 +- ..._compare_unsigned.LowerIntrinsics.panic-unwind.diff | 2 +- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 38a60338e74ed..81087c5417a02 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2528,13 +2528,15 @@ pub const fn bswap(_x: T) -> T; #[rustc_intrinsic] pub const fn bitreverse(_x: T) -> T; -/// Does a three-way comparison between the two integer arguments. +/// Does a three-way comparison between the two arguments, +/// which must be of character or integer (signed or unsigned) type. /// -/// This is included as an intrinsic as it's useful to let it be one thing -/// in MIR, rather than the multiple checks and switches that make its IR -/// large and difficult to optimize. +/// This was originally added because it greatly simplified the MIR in `cmp` +/// implementations, and then LLVM 20 added a backend intrinsic for it too. /// /// The stabilized version of this intrinsic is [`Ord::cmp`]. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] #[rustc_intrinsic] pub const fn three_way_compare(_lhs: T, _rhss: T) -> crate::cmp::Ordering; diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 7d99aaa173143..273db46e4b453 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -3571,10 +3571,7 @@ macro_rules! int_impl { // so delegate it to `Ord` which is already producing -1/0/+1 // exactly like we need and can be the place to deal with the complexity. - // FIXME(const-hack): replace with cmp - if self < 0 { -1 } - else if self == 0 { 0 } - else { 1 } + crate::intrinsics::three_way_compare(self, 0) as Self } /// Returns `true` if `self` is positive and `false` if the number is zero or diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff index 596ad70b3bfad..f29bc5dfc6e4f 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff @@ -18,7 +18,7 @@ _4 = copy _1; StorageLive(_5); _5 = copy _2; -- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind continue]; +- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff index 987c216669271..654cb2503df58 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff @@ -15,7 +15,7 @@ _4 = copy _1; StorageLive(_5); _5 = copy _2; -- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind continue]; +- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff index d7ec6dcfa2c3c..82c89b7ce549c 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff @@ -18,7 +18,7 @@ _4 = copy _1; StorageLive(_5); _5 = copy _2; -- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind continue]; +- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; } From c25f12a667cd83fb79e6f7098e3191f9b1ab6416 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 2 Mar 2025 18:41:28 +0000 Subject: [PATCH 0071/2248] Revert "Auto merge of #135335 - oli-obk:push-zxwssomxxtnq, r=saethlin" This reverts commit a7a6c64a657f68113301c2ffe0745b49a16442d1, reversing changes made to ebbe63891f1fae21734cb97f2f863b08b1d44bf8. --- src/common.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/common.rs b/src/common.rs index 20a3482aaa27f..2052a6aa21597 100644 --- a/src/common.rs +++ b/src/common.rs @@ -64,11 +64,6 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) } } - fn is_undef(&self, _val: RValue<'gcc>) -> bool { - // FIXME: actually check for undef - false - } - fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> { let local = self.current_func.borrow().expect("func").new_local(None, typ, "undefined"); if typ.is_struct().is_some() { From ae07d7d368f3487999e68c5c2aa00a9ba2539905 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Feb 2025 14:13:16 +1100 Subject: [PATCH 0072/2248] Simplify `implied_target_features`. Currently its argument is an iterator, but in practice it's always a singleton. --- src/gcc_util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 4e8c8aaaf5c8a..6eae0c24f48ad 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -48,7 +48,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Date: Tue, 25 Feb 2025 15:25:54 +1100 Subject: [PATCH 0073/2248] 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 | 68 +++++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f090597f95335..d478b2af46c28 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -259,8 +259,8 @@ impl CodegenBackend for GccCodegenBackend { .join(sess) } - fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec { - target_features_cfg(sess, allow_unstable, &self.target_info) + fn target_features_cfg(&self, sess: &Session) -> (Vec, Vec) { + target_features_cfg(sess, &self.target_info) } } @@ -486,35 +486,41 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { /// Returns the features that should be set in `cfg(target_feature)`. fn target_features_cfg( sess: &Session, - allow_unstable: bool, target_info: &LockedTargetInfo, -) -> Vec { +) -> (Vec, Vec) { // TODO(antoyo): use global_gcc_features. - sess.target - .rust_target_features() - .iter() - .filter_map(|&(feature, gate, _)| { - if allow_unstable - || (gate.in_cfg() && (sess.is_nightly_build() || gate.requires_nightly().is_none())) - { - Some(feature) - } else { - None - } - }) - .filter(|feature| { - // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it. - if *feature == "neon" { - return false; - } - target_info.cpu_supports(feature) - /* - adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma, - avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq, - bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm, - sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves - */ - }) - .map(Symbol::intern) - .collect() + let f = |allow_unstable| { + sess.target + .rust_target_features() + .iter() + .filter_map(|&(feature, gate, _)| { + if allow_unstable + || (gate.in_cfg() + && (sess.is_nightly_build() || gate.requires_nightly().is_none())) + { + Some(feature) + } else { + None + } + }) + .filter(|feature| { + // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it. + if *feature == "neon" { + return false; + } + target_info.cpu_supports(feature) + /* + adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma, + avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq, + bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm, + sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves + */ + }) + .map(Symbol::intern) + .collect() + }; + + let target_features = f(false); + let unstable_target_features = f(true); + (target_features, unstable_target_features) } From 0ec1d460bb898a22de37bcc040f86449371bdbdb Mon Sep 17 00:00:00 2001 From: sayantn Date: Tue, 4 Mar 2025 20:07:25 +0530 Subject: [PATCH 0074/2248] 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 0075/2248] 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 e0409677fd449a3b8024bfa81481116c2fb3c850 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 5 Mar 2025 22:03:54 +0100 Subject: [PATCH 0076/2248] Show when build scripts fail what the errors were --- src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 733a7c359b8e7..273be22d8d328 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -139,9 +139,10 @@ impl GlobalState { "Proc-macros and/or build scripts have changed and need to be rebuilt.\n\n", ); } - if self.fetch_build_data_error().is_err() { - status.health |= lsp_ext::Health::Warning; + if let Err(build_data_err) = self.fetch_build_data_error() { + status.health |= lsp_ext::Health::Error; message.push_str("Failed to run build scripts of some packages.\n\n"); + format_to!(message, "{build_data_err}\n"); } if let Some(err) = &self.config_errors { status.health |= lsp_ext::Health::Warning; From 222adac953d1e745763850f75f4afac69b1d4321 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 5 Mar 2025 01:04:10 +0100 Subject: [PATCH 0077/2248] Allow optimizing out `panic_bounds_check` in Unicode checks. --- library/core/src/unicode/unicode_data.rs | 73 +++++++++---------- .../src/range_search.rs | 25 ++++--- .../unicode-table-generator/src/skiplist.rs | 20 +++-- 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 4655d35e9c437..e103d09d9ed62 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -55,24 +55,31 @@ fn decode_length(short_offset_run_header: u32) -> usize { (short_offset_run_header >> 21) as usize } +/// # Safety +/// +/// The last element of `short_offset_runs` must be greater than `std::char::MAX`. #[inline(always)] -fn skip_search( - needle: u32, +unsafe fn skip_search( + needle: char, short_offset_runs: &[u32; SOR], offsets: &[u8; OFFSETS], ) -> bool { - // Note that this *cannot* be past the end of the array, as the last - // element is greater than std::char::MAX (the largest possible needle). - // - // So, we cannot have found it (i.e. Ok(idx) + 1 != length) and the correct - // location cannot be past it, so Err(idx) != length either. - // - // This means that we can avoid bounds checking for the accesses below, too. + let needle = needle as u32; + let last_idx = match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header << 11) { Ok(idx) => idx + 1, Err(idx) => idx, }; + // SAFETY: `last_idx` *cannot* be past the end of the array, as the last + // element is greater than `std::char::MAX` (the largest possible needle) + // as guaranteed by the caller. + // + // So, we cannot have found it (i.e. `Ok(idx) => idx + 1 != length`) and the + // correct location cannot be past it, so `Err(idx) => idx != length` either. + // + // This means that we can avoid bounds checking for the accesses below, too. + unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; let mut offset_idx = decode_length(short_offset_runs[last_idx]); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { @@ -169,11 +176,9 @@ pub mod alphabetic { 0, 0, 0, 0, 5, 0, 0, ]; pub fn lookup(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -222,11 +227,9 @@ pub mod case_ignorable { 1, 61, 4, 0, 5, 254, 2, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, ]; pub fn lookup(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -252,11 +255,9 @@ pub mod cased { 8, 0, 10, 1, 20, 6, 6, 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0, ]; pub fn lookup(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -269,11 +270,9 @@ pub mod cc { 0, 32, 95, 33, 0, ]; pub fn lookup(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -320,11 +319,9 @@ pub mod grapheme_extend { (c as u32) >= 0x300 && lookup_slow(c) } fn lookup_slow(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -459,11 +456,9 @@ pub mod n { 10, 247, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0, ]; pub fn lookup(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs index 9a51979a2f0d9..7376bbdc9aeeb 100644 --- a/src/tools/unicode-table-generator/src/range_search.rs +++ b/src/tools/unicode-table-generator/src/range_search.rs @@ -53,24 +53,31 @@ fn decode_length(short_offset_run_header: u32) -> usize { (short_offset_run_header >> 21) as usize } +/// # Safety +/// +/// The last element of `short_offset_runs` must be greater than `std::char::MAX`. #[inline(always)] -fn skip_search( - needle: u32, +unsafe fn skip_search( + needle: char, short_offset_runs: &[u32; SOR], offsets: &[u8; OFFSETS], ) -> bool { - // Note that this *cannot* be past the end of the array, as the last - // element is greater than std::char::MAX (the largest possible needle). - // - // So, we cannot have found it (i.e. Ok(idx) + 1 != length) and the correct - // location cannot be past it, so Err(idx) != length either. - // - // This means that we can avoid bounds checking for the accesses below, too. + let needle = needle as u32; + let last_idx = match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header << 11) { Ok(idx) => idx + 1, Err(idx) => idx, }; + // SAFETY: `last_idx` *cannot* be past the end of the array, as the last + // element is greater than `std::char::MAX` (the largest possible needle) + // as guaranteed by the caller. + // + // So, we cannot have found it (i.e. `Ok(idx) => idx + 1 != length`) and the + // correct location cannot be past it, so `Err(idx) => idx != length` either. + // + // This means that we can avoid bounds checking for the accesses below, too. + unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; let mut offset_idx = decode_length(short_offset_runs[last_idx]); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs index 8ca18ddc91a80..8dd3eeb8735dd 100644 --- a/src/tools/unicode-table-generator/src/skiplist.rs +++ b/src/tools/unicode-table-generator/src/skiplist.rs @@ -108,11 +108,21 @@ impl RawEmitter { } else { writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); } - writeln!(&mut self.file, " super::skip_search(",).unwrap(); - writeln!(&mut self.file, " c as u32,").unwrap(); - writeln!(&mut self.file, " &SHORT_OFFSET_RUNS,").unwrap(); - writeln!(&mut self.file, " &OFFSETS,").unwrap(); - writeln!(&mut self.file, " )").unwrap(); + writeln!( + &mut self.file, + " const {{ assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); }}", + ) + .unwrap(); + writeln!( + &mut self.file, + " // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`.", + ) + .unwrap(); + writeln!( + &mut self.file, + " unsafe {{ super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) }}" + ) + .unwrap(); writeln!(&mut self.file, "}}").unwrap(); } } From 3e374043f3ec5d4146fcd350a3e027f359e8ef1c Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 5 Mar 2025 15:47:14 +0100 Subject: [PATCH 0078/2248] Add test for `escape_debug` without bounds check. --- tests/codegen/char-escape-debug-no-bounds-check.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/codegen/char-escape-debug-no-bounds-check.rs diff --git a/tests/codegen/char-escape-debug-no-bounds-check.rs b/tests/codegen/char-escape-debug-no-bounds-check.rs new file mode 100644 index 0000000000000..cfde46045e5a5 --- /dev/null +++ b/tests/codegen/char-escape-debug-no-bounds-check.rs @@ -0,0 +1,14 @@ +//@ compile-flags: -Copt-level=3 +#![crate_type = "lib"] + +use std::char::EscapeDebug; + +// Make sure no bounds checks are emitted when escaping a character. + +// CHECK-LABEL: @char_escape_debug_no_bounds_check +#[no_mangle] +pub fn char_escape_debug_no_bounds_check(c: char) -> EscapeDebug { + // CHECK-NOT: panic + // CHECK-NOT: panic_bounds_check + c.escape_debug() +} From 34ac75be2830892baaebc81d3d4e13504c362d1a Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 5 Mar 2025 22:38:58 +0100 Subject: [PATCH 0079/2248] Add second precondition for `skip_search`. --- library/core/src/unicode/unicode_data.rs | 262 ++++++++++++++---- .../src/range_search.rs | 42 ++- .../unicode-table-generator/src/skiplist.rs | 75 +++-- 3 files changed, 294 insertions(+), 85 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index e103d09d9ed62..56f5b7ed8eb1d 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -47,27 +47,42 @@ const fn bitset_search< (word & (1 << (needle % 64) as u64)) != 0 } -fn decode_prefix_sum(short_offset_run_header: u32) -> u32 { - short_offset_run_header & ((1 << 21) - 1) -} +#[repr(transparent)] +struct ShortOffsetRunHeader(u32); + +impl ShortOffsetRunHeader { + const fn new(start_index: usize, prefix_sum: u32) -> Self { + assert!(start_index < (1 << 11)); + assert!(prefix_sum < (1 << 21)); + + Self((start_index as u32) << 21 | prefix_sum) + } -fn decode_length(short_offset_run_header: u32) -> usize { - (short_offset_run_header >> 21) as usize + #[inline] + const fn start_index(&self) -> usize { + (self.0 >> 21) as usize + } + + #[inline] + const fn prefix_sum(&self) -> u32 { + self.0 & ((1 << 21) - 1) + } } /// # Safety /// -/// The last element of `short_offset_runs` must be greater than `std::char::MAX`. +/// - The last element of `short_offset_runs` must be greater than `std::char::MAX`. +/// - The start indices of all elements in `short_offset_runs` must be less than `OFFSETS`. #[inline(always)] unsafe fn skip_search( needle: char, - short_offset_runs: &[u32; SOR], + short_offset_runs: &[ShortOffsetRunHeader; SOR], offsets: &[u8; OFFSETS], ) -> bool { let needle = needle as u32; let last_idx = - match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header << 11) { + match short_offset_runs.binary_search_by_key(&(needle << 11), |header| (header.0 << 11)) { Ok(idx) => idx + 1, Err(idx) => idx, }; @@ -81,18 +96,23 @@ unsafe fn skip_search( // This means that we can avoid bounds checking for the accesses below, too. unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; - let mut offset_idx = decode_length(short_offset_runs[last_idx]); + let mut offset_idx = short_offset_runs[last_idx].start_index(); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { - decode_length(*next) - offset_idx + (*next).start_index() - offset_idx } else { offsets.len() - offset_idx }; + let prev = - last_idx.checked_sub(1).map(|prev| decode_prefix_sum(short_offset_runs[prev])).unwrap_or(0); + last_idx.checked_sub(1).map(|prev| short_offset_runs[prev].prefix_sum()).unwrap_or(0); let total = needle - prev; let mut prefix_sum = 0; for _ in 0..(length - 1) { + // SAFETY: It is guaranteed that `length <= OFFSETS - offset_idx`, + // so it follows that `length - 1 + offset_idx < OFFSETS`, therefore + // `offset_idx < OFFSETS` is always true in this loop. + unsafe { crate::hint::assert_unchecked(offset_idx < OFFSETS) }; let offset = offsets[offset_idx]; prefix_sum += offset as u32; if prefix_sum > total { @@ -107,15 +127,36 @@ pub const UNICODE_VERSION: (u8, u8, u8) = (16, 0, 0); #[rustfmt::skip] pub mod alphabetic { - static SHORT_OFFSET_RUNS: [u32; 53] = [ - 706, 33559113, 876615277, 956309270, 1166025910, 1314925568, 1319120901, 1398813696, - 1449151936, 1451271309, 1455465997, 1463867300, 1652619520, 1663105646, 1665203518, - 1711342208, 1797326647, 1895898848, 2560697242, 2583768976, 2594255920, 2600551419, - 2608940615, 2613141760, 2615240704, 2619435577, 2621533504, 2652997624, 2688650454, - 2692853744, 2699145507, 2713826044, 2734799872, 2736903168, 2757875366, 2835472128, - 2883707536, 2934039760, 2942429152, 2955013632, 2988568880, 3126984704, 3139610336, - 3141711674, 3145911970, 3154308065, 3158503006, 3162699776, 3164797470, 3166896128, - 3168998219, 3171099568, 3176407984, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 53] = [ + ShortOffsetRunHeader::new(0, 706), ShortOffsetRunHeader::new(16, 4681), + ShortOffsetRunHeader::new(418, 5741), ShortOffsetRunHeader::new(456, 7958), + ShortOffsetRunHeader::new(556, 9398), ShortOffsetRunHeader::new(627, 11264), + ShortOffsetRunHeader::new(629, 12293), ShortOffsetRunHeader::new(667, 13312), + ShortOffsetRunHeader::new(691, 19904), ShortOffsetRunHeader::new(692, 42125), + ShortOffsetRunHeader::new(694, 42509), ShortOffsetRunHeader::new(698, 55204), + ShortOffsetRunHeader::new(788, 63744), ShortOffsetRunHeader::new(793, 64110), + ShortOffsetRunHeader::new(794, 64830), ShortOffsetRunHeader::new(816, 66176), + ShortOffsetRunHeader::new(857, 67383), ShortOffsetRunHeader::new(904, 73440), + ShortOffsetRunHeader::new(1221, 74650), ShortOffsetRunHeader::new(1232, 77712), + ShortOffsetRunHeader::new(1237, 78896), ShortOffsetRunHeader::new(1240, 82939), + ShortOffsetRunHeader::new(1244, 83527), ShortOffsetRunHeader::new(1246, 90368), + ShortOffsetRunHeader::new(1247, 92160), ShortOffsetRunHeader::new(1249, 92729), + ShortOffsetRunHeader::new(1250, 93504), ShortOffsetRunHeader::new(1265, 100344), + ShortOffsetRunHeader::new(1282, 101590), ShortOffsetRunHeader::new(1284, 110576), + ShortOffsetRunHeader::new(1287, 110883), ShortOffsetRunHeader::new(1294, 111356), + ShortOffsetRunHeader::new(1304, 113664), ShortOffsetRunHeader::new(1305, 119808), + ShortOffsetRunHeader::new(1315, 120486), ShortOffsetRunHeader::new(1352, 122624), + ShortOffsetRunHeader::new(1375, 123536), ShortOffsetRunHeader::new(1399, 124112), + ShortOffsetRunHeader::new(1403, 124896), ShortOffsetRunHeader::new(1409, 126464), + ShortOffsetRunHeader::new(1425, 127280), ShortOffsetRunHeader::new(1491, 131072), + ShortOffsetRunHeader::new(1497, 173792), ShortOffsetRunHeader::new(1498, 177978), + ShortOffsetRunHeader::new(1500, 183970), ShortOffsetRunHeader::new(1504, 191457), + ShortOffsetRunHeader::new(1506, 192094), ShortOffsetRunHeader::new(1508, 194560), + ShortOffsetRunHeader::new(1509, 195102), ShortOffsetRunHeader::new(1510, 196608), + ShortOffsetRunHeader::new(1511, 201547), ShortOffsetRunHeader::new(1512, 205744), + ShortOffsetRunHeader::new(1514, 1319856), ]; static OFFSETS: [u8; 1515] = [ 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 29, @@ -176,20 +217,44 @@ pub mod alphabetic { 0, 0, 0, 0, 5, 0, 0, ]; pub fn lookup(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } #[rustfmt::skip] pub mod case_ignorable { - static SHORT_OFFSET_RUNS: [u32; 37] = [ - 688, 44045149, 572528402, 576724925, 807414908, 878718981, 903913493, 929080568, 933275148, - 937491230, 1138818560, 1147208189, 1210124160, 1222707713, 1235291428, 1260457643, - 1277237295, 1537284411, 1545673776, 1604394739, 1667314736, 1692492062, 1700883184, - 1709272384, 1721855823, 1730260976, 1747041437, 1759629056, 1768018279, 1776409088, - 1797382144, 1822548654, 1856103659, 1864493264, 1872884731, 1882062849, 1887371760, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 37] = [ + ShortOffsetRunHeader::new(0, 688), ShortOffsetRunHeader::new(21, 4957), + ShortOffsetRunHeader::new(273, 5906), ShortOffsetRunHeader::new(275, 8125), + ShortOffsetRunHeader::new(385, 11388), ShortOffsetRunHeader::new(419, 12293), + ShortOffsetRunHeader::new(431, 40981), ShortOffsetRunHeader::new(443, 42232), + ShortOffsetRunHeader::new(445, 42508), ShortOffsetRunHeader::new(447, 64286), + ShortOffsetRunHeader::new(543, 65024), ShortOffsetRunHeader::new(547, 66045), + ShortOffsetRunHeader::new(577, 67456), ShortOffsetRunHeader::new(583, 68097), + ShortOffsetRunHeader::new(589, 68900), ShortOffsetRunHeader::new(601, 69291), + ShortOffsetRunHeader::new(609, 71727), ShortOffsetRunHeader::new(733, 71995), + ShortOffsetRunHeader::new(737, 72752), ShortOffsetRunHeader::new(765, 73459), + ShortOffsetRunHeader::new(795, 78896), ShortOffsetRunHeader::new(807, 90398), + ShortOffsetRunHeader::new(811, 92912), ShortOffsetRunHeader::new(815, 93504), + ShortOffsetRunHeader::new(821, 94031), ShortOffsetRunHeader::new(825, 110576), + ShortOffsetRunHeader::new(833, 113821), ShortOffsetRunHeader::new(839, 118528), + ShortOffsetRunHeader::new(843, 119143), ShortOffsetRunHeader::new(847, 121344), + ShortOffsetRunHeader::new(857, 122880), ShortOffsetRunHeader::new(869, 123566), + ShortOffsetRunHeader::new(885, 124139), ShortOffsetRunHeader::new(889, 125136), + ShortOffsetRunHeader::new(893, 127995), ShortOffsetRunHeader::new(897, 917505), + ShortOffsetRunHeader::new(899, 2032112), ]; static OFFSETS: [u8; 905] = [ 39, 1, 6, 1, 11, 1, 35, 1, 1, 1, 71, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2, @@ -227,18 +292,36 @@ pub mod case_ignorable { 1, 61, 4, 0, 5, 254, 2, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, ]; pub fn lookup(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } #[rustfmt::skip] pub mod cased { - static SHORT_OFFSET_RUNS: [u32; 22] = [ - 4256, 115348384, 136322176, 144711446, 163587254, 320875520, 325101120, 350268208, - 392231680, 404815649, 413205504, 421595008, 467733632, 484513952, 501313088, 505533440, - 509728422, 587325184, 635559984, 648145152, 652341552, 657650058, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 22] = [ + ShortOffsetRunHeader::new(0, 4256), ShortOffsetRunHeader::new(55, 5024), + ShortOffsetRunHeader::new(65, 7296), ShortOffsetRunHeader::new(69, 7958), + ShortOffsetRunHeader::new(78, 9398), ShortOffsetRunHeader::new(153, 11264), + ShortOffsetRunHeader::new(155, 42560), ShortOffsetRunHeader::new(167, 43824), + ShortOffsetRunHeader::new(187, 64256), ShortOffsetRunHeader::new(193, 65313), + ShortOffsetRunHeader::new(197, 66560), ShortOffsetRunHeader::new(201, 67456), + ShortOffsetRunHeader::new(223, 68736), ShortOffsetRunHeader::new(231, 71840), + ShortOffsetRunHeader::new(239, 93760), ShortOffsetRunHeader::new(241, 119808), + ShortOffsetRunHeader::new(243, 120486), ShortOffsetRunHeader::new(280, 122624), + ShortOffsetRunHeader::new(303, 122928), ShortOffsetRunHeader::new(309, 125184), + ShortOffsetRunHeader::new(311, 127280), ShortOffsetRunHeader::new(313, 1241482), ]; static OFFSETS: [u8; 319] = [ 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5, @@ -255,35 +338,67 @@ pub mod cased { 8, 0, 10, 1, 20, 6, 6, 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0, ]; pub fn lookup(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } #[rustfmt::skip] pub mod cc { - static SHORT_OFFSET_RUNS: [u32; 1] = [ - 1114272, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 1] = [ + ShortOffsetRunHeader::new(0, 1114272), ]; static OFFSETS: [u8; 5] = [ 0, 32, 95, 33, 0, ]; pub fn lookup(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } #[rustfmt::skip] pub mod grapheme_extend { - static SHORT_OFFSET_RUNS: [u32; 34] = [ - 768, 2098307, 6292881, 10490717, 522196754, 526393356, 723528943, 731918378, 744531567, - 752920578, 769719070, 908131840, 912326558, 920715773, 924912129, 937495844, 962662059, - 971053103, 1256266800, 1323376371, 1386296384, 1407279390, 1415670512, 1424060239, - 1432468637, 1449250560, 1453445477, 1461836288, 1487003648, 1512170158, 1541530860, - 1549920464, 1559101472, 1568604656, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 34] = [ + ShortOffsetRunHeader::new(0, 768), ShortOffsetRunHeader::new(1, 1155), + ShortOffsetRunHeader::new(3, 1425), ShortOffsetRunHeader::new(5, 4957), + ShortOffsetRunHeader::new(249, 5906), ShortOffsetRunHeader::new(251, 8204), + ShortOffsetRunHeader::new(345, 11503), ShortOffsetRunHeader::new(349, 12330), + ShortOffsetRunHeader::new(355, 42607), ShortOffsetRunHeader::new(359, 43010), + ShortOffsetRunHeader::new(367, 64286), ShortOffsetRunHeader::new(433, 65024), + ShortOffsetRunHeader::new(435, 65438), ShortOffsetRunHeader::new(439, 66045), + ShortOffsetRunHeader::new(441, 68097), ShortOffsetRunHeader::new(447, 68900), + ShortOffsetRunHeader::new(459, 69291), ShortOffsetRunHeader::new(463, 71727), + ShortOffsetRunHeader::new(599, 72752), ShortOffsetRunHeader::new(631, 73459), + ShortOffsetRunHeader::new(661, 78912), ShortOffsetRunHeader::new(671, 90398), + ShortOffsetRunHeader::new(675, 92912), ShortOffsetRunHeader::new(679, 94031), + ShortOffsetRunHeader::new(683, 113821), ShortOffsetRunHeader::new(691, 118528), + ShortOffsetRunHeader::new(693, 119141), ShortOffsetRunHeader::new(697, 121344), + ShortOffsetRunHeader::new(709, 122880), ShortOffsetRunHeader::new(721, 123566), + ShortOffsetRunHeader::new(735, 124140), ShortOffsetRunHeader::new(739, 125136), + ShortOffsetRunHeader::new(743, 917536), ShortOffsetRunHeader::new(747, 2032112), ]; static OFFSETS: [u8; 751] = [ 0, 112, 0, 7, 0, 45, 1, 1, 1, 2, 1, 2, 1, 1, 72, 11, 48, 21, 16, 1, 101, 7, 2, 6, 2, 2, 1, @@ -319,8 +434,16 @@ pub mod grapheme_extend { (c as u32) >= 0x300 && lookup_slow(c) } fn lookup_slow(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -433,13 +556,30 @@ pub mod lowercase { #[rustfmt::skip] pub mod n { - static SHORT_OFFSET_RUNS: [u32; 42] = [ - 1632, 18876774, 31461440, 102765417, 111154926, 115349830, 132128880, 165684320, 186656630, - 195046653, 199241735, 203436434, 216049184, 241215536, 249605104, 274792208, 278987015, - 283181793, 295766104, 320933114, 383848032, 396432464, 438376016, 446765280, 463543280, - 471932752, 488711168, 497115440, 501312096, 505507184, 522284672, 526503152, 530698944, - 534894542, 547479872, 551674608, 555869424, 560064711, 568454257, 576844032, 597818352, - 603126778, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 42] = [ + ShortOffsetRunHeader::new(0, 1632), ShortOffsetRunHeader::new(9, 2406), + ShortOffsetRunHeader::new(15, 4160), ShortOffsetRunHeader::new(49, 4969), + ShortOffsetRunHeader::new(53, 5870), ShortOffsetRunHeader::new(55, 6470), + ShortOffsetRunHeader::new(63, 8304), ShortOffsetRunHeader::new(79, 9312), + ShortOffsetRunHeader::new(89, 10102), ShortOffsetRunHeader::new(93, 11517), + ShortOffsetRunHeader::new(95, 12295), ShortOffsetRunHeader::new(97, 12690), + ShortOffsetRunHeader::new(103, 42528), ShortOffsetRunHeader::new(115, 43056), + ShortOffsetRunHeader::new(119, 44016), ShortOffsetRunHeader::new(131, 65296), + ShortOffsetRunHeader::new(133, 65799), ShortOffsetRunHeader::new(135, 66273), + ShortOffsetRunHeader::new(141, 67672), ShortOffsetRunHeader::new(153, 68858), + ShortOffsetRunHeader::new(183, 69216), ShortOffsetRunHeader::new(189, 70736), + ShortOffsetRunHeader::new(209, 71248), ShortOffsetRunHeader::new(213, 71904), + ShortOffsetRunHeader::new(221, 72688), ShortOffsetRunHeader::new(225, 73552), + ShortOffsetRunHeader::new(233, 74752), ShortOffsetRunHeader::new(237, 90416), + ShortOffsetRunHeader::new(239, 92768), ShortOffsetRunHeader::new(241, 93552), + ShortOffsetRunHeader::new(249, 93824), ShortOffsetRunHeader::new(251, 118000), + ShortOffsetRunHeader::new(253, 119488), ShortOffsetRunHeader::new(255, 120782), + ShortOffsetRunHeader::new(261, 123200), ShortOffsetRunHeader::new(263, 123632), + ShortOffsetRunHeader::new(265, 124144), ShortOffsetRunHeader::new(267, 125127), + ShortOffsetRunHeader::new(271, 126065), ShortOffsetRunHeader::new(275, 127232), + ShortOffsetRunHeader::new(285, 130032), ShortOffsetRunHeader::new(287, 1244154), ]; static OFFSETS: [u8; 289] = [ 48, 10, 120, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118, @@ -456,8 +596,16 @@ pub mod n { 10, 247, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0, ]; pub fn lookup(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs index 7376bbdc9aeeb..09bfe9a86a486 100644 --- a/src/tools/unicode-table-generator/src/range_search.rs +++ b/src/tools/unicode-table-generator/src/range_search.rs @@ -45,27 +45,42 @@ const fn bitset_search< (word & (1 << (needle % 64) as u64)) != 0 } -fn decode_prefix_sum(short_offset_run_header: u32) -> u32 { - short_offset_run_header & ((1 << 21) - 1) -} +#[repr(transparent)] +struct ShortOffsetRunHeader(u32); + +impl ShortOffsetRunHeader { + const fn new(start_index: usize, prefix_sum: u32) -> Self { + assert!(start_index < (1 << 11)); + assert!(prefix_sum < (1 << 21)); + + Self((start_index as u32) << 21 | prefix_sum) + } -fn decode_length(short_offset_run_header: u32) -> usize { - (short_offset_run_header >> 21) as usize + #[inline] + const fn start_index(&self) -> usize { + (self.0 >> 21) as usize + } + + #[inline] + const fn prefix_sum(&self) -> u32 { + self.0 & ((1 << 21) - 1) + } } /// # Safety /// -/// The last element of `short_offset_runs` must be greater than `std::char::MAX`. +/// - The last element of `short_offset_runs` must be greater than `std::char::MAX`. +/// - The start indices of all elements in `short_offset_runs` must be less than `OFFSETS`. #[inline(always)] unsafe fn skip_search( needle: char, - short_offset_runs: &[u32; SOR], + short_offset_runs: &[ShortOffsetRunHeader; SOR], offsets: &[u8; OFFSETS], ) -> bool { let needle = needle as u32; let last_idx = - match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header << 11) { + match short_offset_runs.binary_search_by_key(&(needle << 11), |header| (header.0 << 11)) { Ok(idx) => idx + 1, Err(idx) => idx, }; @@ -79,18 +94,23 @@ unsafe fn skip_search( // This means that we can avoid bounds checking for the accesses below, too. unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; - let mut offset_idx = decode_length(short_offset_runs[last_idx]); + let mut offset_idx = short_offset_runs[last_idx].start_index(); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { - decode_length(*next) - offset_idx + (*next).start_index() - offset_idx } else { offsets.len() - offset_idx }; + let prev = - last_idx.checked_sub(1).map(|prev| decode_prefix_sum(short_offset_runs[prev])).unwrap_or(0); + last_idx.checked_sub(1).map(|prev| short_offset_runs[prev].prefix_sum()).unwrap_or(0); let total = needle - prev; let mut prefix_sum = 0; for _ in 0..(length - 1) { + // SAFETY: It is guaranteed that `length <= OFFSETS - offset_idx`, + // so it follows that `length - 1 + offset_idx < OFFSETS`, therefore + // `offset_idx < OFFSETS` is always true in this loop. + unsafe { crate::hint::assert_unchecked(offset_idx < OFFSETS) }; let offset = offsets[offset_idx]; prefix_sum += offset as u32; if prefix_sum > total { diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs index 8dd3eeb8735dd..c2e44aec89031 100644 --- a/src/tools/unicode-table-generator/src/skiplist.rs +++ b/src/tools/unicode-table-generator/src/skiplist.rs @@ -1,26 +1,23 @@ -use std::fmt::Write as _; +use std::fmt::{self, Write as _}; use std::ops::Range; use crate::fmt_list; use crate::raw_emitter::RawEmitter; /// This will get packed into a single u32 before inserting into the data set. -#[derive(Debug, PartialEq)] +#[derive(PartialEq)] struct ShortOffsetRunHeader { - /// Note, we only allow for 21 bits here. - prefix_sum: u32, - /// Note, we actually only allow for 11 bits here. This should be enough -- /// our largest sets are around ~1400 offsets long. - start_idx: u16, -} + start_index: u16, -impl ShortOffsetRunHeader { - fn pack(&self) -> u32 { - assert!(self.start_idx < (1 << 11)); - assert!(self.prefix_sum < (1 << 21)); + /// Note, we only allow for 21 bits here. + prefix_sum: u32, +} - (self.start_idx as u32) << 21 | self.prefix_sum +impl fmt::Debug for ShortOffsetRunHeader { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ShortOffsetRunHeader::new({}, {})", self.start_index, self.prefix_sum) } } @@ -53,7 +50,7 @@ impl RawEmitter { coded_offsets.push(offset); } else { short_offset_runs.push(ShortOffsetRunHeader { - start_idx: start.try_into().unwrap(), + start_index: start.try_into().unwrap(), prefix_sum, }); // This is just needed to maintain indices even/odd @@ -73,9 +70,13 @@ impl RawEmitter { writeln!( &mut self.file, - "static SHORT_OFFSET_RUNS: [u32; {}] = [{}];", + "use super::ShortOffsetRunHeader;\n" + ).unwrap(); + writeln!( + &mut self.file, + "static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; {}] = [{}];", short_offset_runs.len(), - fmt_list(short_offset_runs.iter().map(|v| v.pack())) + fmt_list(short_offset_runs.iter()) ) .unwrap(); self.bytes_used += 4 * short_offset_runs.len(); @@ -110,12 +111,52 @@ impl RawEmitter { } writeln!( &mut self.file, - " const {{ assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); }}", + " const {{", + ) + .unwrap(); + writeln!( + &mut self.file, + " assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32));", + ) + .unwrap(); + writeln!( + &mut self.file, + " let mut i = 0;", + ) + .unwrap(); + writeln!( + &mut self.file, + " while i < SHORT_OFFSET_RUNS.len() {{", + ) + .unwrap(); + writeln!( + &mut self.file, + " assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len());", + ) + .unwrap(); + writeln!( + &mut self.file, + " i += 1;", + ) + .unwrap(); + writeln!( + &mut self.file, + " }}", + ) + .unwrap(); + writeln!( + &mut self.file, + " }}", + ) + .unwrap(); + writeln!( + &mut self.file, + " // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`", ) .unwrap(); writeln!( &mut self.file, - " // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`.", + " // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`.", ) .unwrap(); writeln!( From 429c09ead27f1715f07808f4b98eabfd40830520 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 6 Mar 2025 22:31:03 +0100 Subject: [PATCH 0080/2248] Do not suggest replacing an expression by an ambiguous type name An expression such as `<_>::default()` should not be replaced by an ambiguous type name such as `_` even if the inferred type in the original expression is a singleton. --- clippy_lints/src/default_constructed_unit_structs.rs | 2 ++ tests/ui/default_constructed_unit_structs.fixed | 9 +++++++++ tests/ui/default_constructed_unit_structs.rs | 9 +++++++++ 3 files changed, 20 insertions(+) diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs index bbd5dc15542d1..85a6305917112 100644 --- a/clippy_lints/src/default_constructed_unit_structs.rs +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -70,6 +70,8 @@ impl LateLintPass<'_> for DefaultConstructedUnitStructs { && let var @ ty::VariantDef { ctor: Some((hir::def::CtorKind::Const, _)), .. } = def.non_enum_variant() && !var.is_field_list_non_exhaustive() && !expr.span.from_expansion() && !qpath.span().from_expansion() + // do not suggest replacing an expression by a type name with placeholders + && !base.is_suggestable_infer_ty() { span_lint_and_sugg( cx, diff --git a/tests/ui/default_constructed_unit_structs.fixed b/tests/ui/default_constructed_unit_structs.fixed index fa4d55177823e..91a6161f98af9 100644 --- a/tests/ui/default_constructed_unit_structs.fixed +++ b/tests/ui/default_constructed_unit_structs.fixed @@ -161,3 +161,12 @@ fn main() { let _ = ::default(); } + +fn issue12654() { + #[derive(Default)] + struct G; + + fn f(_g: G) {} + + f(<_>::default()); +} diff --git a/tests/ui/default_constructed_unit_structs.rs b/tests/ui/default_constructed_unit_structs.rs index 291cd89da0b79..571f7cde26ad8 100644 --- a/tests/ui/default_constructed_unit_structs.rs +++ b/tests/ui/default_constructed_unit_structs.rs @@ -161,3 +161,12 @@ fn main() { let _ = ::default(); } + +fn issue12654() { + #[derive(Default)] + struct G; + + fn f(_g: G) {} + + f(<_>::default()); +} From 253ecb9d7dfbfe3110c7e58e5017b31058f96d80 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 6 Mar 2025 22:42:54 +0100 Subject: [PATCH 0081/2248] Signal the problem on the whole expression span This is more consistent with what other lints are doing: the use of `default` to create a unit struct is the whole expression. --- .../src/default_constructed_unit_structs.rs | 18 ++++++--- .../ui/default_constructed_unit_structs.fixed | 3 +- .../default_constructed_unit_structs.stderr | 38 ++++++++++++------- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs index 85a6305917112..7410e0a67050a 100644 --- a/clippy_lints/src/default_constructed_unit_structs.rs +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -1,5 +1,6 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_ty_alias; +use clippy_utils::sugg::DiagExt as _; use hir::ExprKind; use hir::def::Res; use rustc_errors::Applicability; @@ -73,14 +74,19 @@ impl LateLintPass<'_> for DefaultConstructedUnitStructs { // do not suggest replacing an expression by a type name with placeholders && !base.is_suggestable_infer_ty() { - span_lint_and_sugg( + span_lint_and_then( cx, DEFAULT_CONSTRUCTED_UNIT_STRUCTS, - expr.span.with_lo(qpath.qself_span().hi()), + expr.span, "use of `default` to create a unit struct", - "remove this call to `default`", - String::new(), - Applicability::MachineApplicable, + |diag| { + diag.suggest_remove_item( + cx, + expr.span.with_lo(qpath.qself_span().hi()), + "remove this call to `default`", + Applicability::MachineApplicable, + ); + }, ); } } diff --git a/tests/ui/default_constructed_unit_structs.fixed b/tests/ui/default_constructed_unit_structs.fixed index 91a6161f98af9..3beddca6fb1ec 100644 --- a/tests/ui/default_constructed_unit_structs.fixed +++ b/tests/ui/default_constructed_unit_structs.fixed @@ -8,8 +8,7 @@ struct UnitStruct; impl UnitStruct { fn new() -> Self { //should lint - Self - //~^ default_constructed_unit_structs + Self//~^ default_constructed_unit_structs } } diff --git a/tests/ui/default_constructed_unit_structs.stderr b/tests/ui/default_constructed_unit_structs.stderr index 6d4e1bdc2cc81..7c0f4c0d4aca0 100644 --- a/tests/ui/default_constructed_unit_structs.stderr +++ b/tests/ui/default_constructed_unit_structs.stderr @@ -1,41 +1,53 @@ error: use of `default` to create a unit struct - --> tests/ui/default_constructed_unit_structs.rs:11:13 + --> tests/ui/default_constructed_unit_structs.rs:11:9 | -LL | Self::default() - | ^^^^^^^^^^^ help: remove this call to `default` +LL | Self::default() + | _________^^^^-^^^^^^^^^^ +LL | | + | |________- help: remove this call to `default` | = note: `-D clippy::default-constructed-unit-structs` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::default_constructed_unit_structs)]` error: use of `default` to create a unit struct - --> tests/ui/default_constructed_unit_structs.rs:54:31 + --> tests/ui/default_constructed_unit_structs.rs:54:20 | LL | inner: PhantomData::default(), - | ^^^^^^^^^^^ help: remove this call to `default` + | ^^^^^^^^^^^----------- + | | + | help: remove this call to `default` error: use of `default` to create a unit struct - --> tests/ui/default_constructed_unit_structs.rs:128:33 + --> tests/ui/default_constructed_unit_structs.rs:128:13 | LL | let _ = PhantomData::::default(); - | ^^^^^^^^^^^ help: remove this call to `default` + | ^^^^^^^^^^^^^^^^^^^^----------- + | | + | help: remove this call to `default` error: use of `default` to create a unit struct - --> tests/ui/default_constructed_unit_structs.rs:130:42 + --> tests/ui/default_constructed_unit_structs.rs:130:31 | LL | let _: PhantomData = PhantomData::default(); - | ^^^^^^^^^^^ help: remove this call to `default` + | ^^^^^^^^^^^----------- + | | + | help: remove this call to `default` error: use of `default` to create a unit struct - --> tests/ui/default_constructed_unit_structs.rs:132:55 + --> tests/ui/default_constructed_unit_structs.rs:132:31 | LL | let _: PhantomData = std::marker::PhantomData::default(); - | ^^^^^^^^^^^ help: remove this call to `default` + | ^^^^^^^^^^^^^^^^^^^^^^^^----------- + | | + | help: remove this call to `default` error: use of `default` to create a unit struct - --> tests/ui/default_constructed_unit_structs.rs:134:23 + --> tests/ui/default_constructed_unit_structs.rs:134:13 | LL | let _ = UnitStruct::default(); - | ^^^^^^^^^^^ help: remove this call to `default` + | ^^^^^^^^^^----------- + | | + | help: remove this call to `default` error: aborting due to 6 previous errors From 10cf3cb945b413c0fb81cf13c4bf4db762ba5377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Mon, 3 Mar 2025 12:54:26 +0100 Subject: [PATCH 0082/2248] Add helper methods checking for "#[non_exhaustive] that's active" A check for `#[non_exhaustive]` is often done in combination with checking whether the type is local to the crate, in a variety of ways. Create a helper method and standardize on it as the way to check for this. --- clippy_lints/src/default.rs | 2 +- clippy_lints/src/needless_update.rs | 5 +++-- clippy_lints/src/unneeded_struct_pattern.rs | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/default.rs b/clippy_lints/src/default.rs index ffdd946aadb8b..886c325b355fe 100644 --- a/clippy_lints/src/default.rs +++ b/clippy_lints/src/default.rs @@ -134,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { && let ty::Adt(adt, args) = *binding_type.kind() && adt.is_struct() && let variant = adt.non_enum_variant() - && (adt.did().is_local() || !variant.is_field_list_non_exhaustive()) + && !variant.field_list_has_applicable_non_exhaustive() && let module_did = cx.tcx.parent_module(stmt.hir_id) && variant .fields diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 0cba72bd2c6a9..cce0617ba3925 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -54,8 +54,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessUpdate { if let ExprKind::Struct(_, fields, StructTailExpr::Base(base)) = expr.kind { let ty = cx.typeck_results().expr_ty(expr); if let ty::Adt(def, _) = ty.kind() { - if fields.len() == def.non_enum_variant().fields.len() - && !def.variant(0_usize.into()).is_field_list_non_exhaustive() + let variant = def.non_enum_variant(); + if fields.len() == variant.fields.len() + && !variant.is_field_list_non_exhaustive() { span_lint( cx, diff --git a/clippy_lints/src/unneeded_struct_pattern.rs b/clippy_lints/src/unneeded_struct_pattern.rs index a74eab8b6ae50..3326dea8c5dfa 100644 --- a/clippy_lints/src/unneeded_struct_pattern.rs +++ b/clippy_lints/src/unneeded_struct_pattern.rs @@ -51,7 +51,7 @@ impl LateLintPass<'_> for UnneededStructPattern { let variant = cx.tcx.adt_def(enum_did).variant_with_id(did); let has_only_fields_brackets = variant.ctor.is_some() && variant.fields.is_empty(); - let non_exhaustive_activated = !variant.def_id.is_local() && variant.is_field_list_non_exhaustive(); + let non_exhaustive_activated = variant.field_list_has_applicable_non_exhaustive(); if !has_only_fields_brackets || non_exhaustive_activated { return; } From a11fbeec1fc0ad1b8c8814dd2fa4704c4d5e8e0e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 7 Mar 2025 17:09:12 +0100 Subject: [PATCH 0083/2248] Small code improvement in rustdoc hidden stripper --- src/librustdoc/passes/strip_hidden.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index bcdca862862d4..692ce21d6cfbc 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -91,19 +91,21 @@ impl DocFolder for Stripper<'_, '_> { if let clean::ImportItem(clean::Import { source, .. }) = &i.kind && let Some(source_did) = source.did - && let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local()) { - let reexports = reexport_chain(self.tcx, import_def_id, source_did); + if self.tcx.is_doc_hidden(source_did) { + return None; + } else if let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local()) { + let reexports = reexport_chain(self.tcx, import_def_id, source_did); - // Check if any reexport in the chain has a hidden source - let has_hidden_source = reexports - .iter() - .filter_map(|reexport| reexport.id()) - .any(|reexport_did| self.tcx.is_doc_hidden(reexport_did)) - || self.tcx.is_doc_hidden(source_did); + // Check if any reexport in the chain has a hidden source + let has_hidden_source = reexports + .iter() + .filter_map(|reexport| reexport.id()) + .any(|reexport_did| self.tcx.is_doc_hidden(reexport_did)); - if has_hidden_source { - return None; + if has_hidden_source { + return None; + } } } From 00fb741ac188f292842fa6762d8bf487d6110952 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Fri, 7 Mar 2025 18:27:29 +0100 Subject: [PATCH 0084/2248] Remove explicit error message when build.rs fails --- src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 273be22d8d328..3aec2582d1523 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -139,10 +139,10 @@ impl GlobalState { "Proc-macros and/or build scripts have changed and need to be rebuilt.\n\n", ); } - if let Err(build_data_err) = self.fetch_build_data_error() { - status.health |= lsp_ext::Health::Error; + if self.fetch_build_data_error().is_err() { + status.health |= lsp_ext::Health::Warning; message.push_str("Failed to run build scripts of some packages.\n\n"); - format_to!(message, "{build_data_err}\n"); + message.push_str("Please refer to the logs for more details on the errors."); } if let Some(err) = &self.config_errors { status.health |= lsp_ext::Health::Warning; From 22725588d3156f472b66a19b9ec97fdcc5d0a663 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 7 Mar 2025 20:16:39 +0100 Subject: [PATCH 0085/2248] Never inline `lookup_slow`. --- library/core/src/unicode/unicode_data.rs | 2 ++ src/tools/unicode-table-generator/src/skiplist.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 56f5b7ed8eb1d..f25f443567a83 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -433,6 +433,8 @@ pub mod grapheme_extend { pub fn lookup(c: char) -> bool { (c as u32) >= 0x300 && lookup_slow(c) } + + #[inline(never)] fn lookup_slow(c: char) -> bool { const { assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs index c2e44aec89031..e4c3d96546f1e 100644 --- a/src/tools/unicode-table-generator/src/skiplist.rs +++ b/src/tools/unicode-table-generator/src/skiplist.rs @@ -105,6 +105,8 @@ impl RawEmitter { writeln!(&mut self.file, " (c as u32) >= {first_code_point:#04x} && lookup_slow(c)") .unwrap(); writeln!(&mut self.file, "}}").unwrap(); + writeln!(&mut self.file).unwrap(); + writeln!(&mut self.file, "#[inline(never)]").unwrap(); writeln!(&mut self.file, "fn lookup_slow(c: char) -> bool {{").unwrap(); } else { writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); From 90ebc246075f9b56cd0a2dee2496698a94c9c033 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 7 Mar 2025 20:19:12 +0100 Subject: [PATCH 0086/2248] Use `intrinsics::assume` instead of `hint::assert_unchecked`. --- library/core/src/unicode/unicode_data.rs | 10 ++++++++-- src/tools/unicode-table-generator/src/range_search.rs | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index f25f443567a83..63d1581145868 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -94,7 +94,10 @@ unsafe fn skip_search( // correct location cannot be past it, so `Err(idx) => idx != length` either. // // This means that we can avoid bounds checking for the accesses below, too. - unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; + // + // We need to use `intrinsics::assume` since the `panic_nounwind` contained + // in `hint::assert_unchecked` may not be optimized out. + unsafe { crate::intrinsics::assume(last_idx < SOR) }; let mut offset_idx = short_offset_runs[last_idx].start_index(); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { @@ -112,7 +115,10 @@ unsafe fn skip_search( // SAFETY: It is guaranteed that `length <= OFFSETS - offset_idx`, // so it follows that `length - 1 + offset_idx < OFFSETS`, therefore // `offset_idx < OFFSETS` is always true in this loop. - unsafe { crate::hint::assert_unchecked(offset_idx < OFFSETS) }; + // + // We need to use `intrinsics::assume` since the `panic_nounwind` contained + // in `hint::assert_unchecked` may not be optimized out. + unsafe { crate::intrinsics::assume(offset_idx < OFFSETS) }; let offset = offsets[offset_idx]; prefix_sum += offset as u32; if prefix_sum > total { diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs index 09bfe9a86a486..02f9cf16d4d37 100644 --- a/src/tools/unicode-table-generator/src/range_search.rs +++ b/src/tools/unicode-table-generator/src/range_search.rs @@ -92,7 +92,10 @@ unsafe fn skip_search( // correct location cannot be past it, so `Err(idx) => idx != length` either. // // This means that we can avoid bounds checking for the accesses below, too. - unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; + // + // We need to use `intrinsics::assume` since the `panic_nounwind` contained + // in `hint::assert_unchecked` may not be optimized out. + unsafe { crate::intrinsics::assume(last_idx < SOR) }; let mut offset_idx = short_offset_runs[last_idx].start_index(); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { @@ -110,7 +113,10 @@ unsafe fn skip_search( // SAFETY: It is guaranteed that `length <= OFFSETS - offset_idx`, // so it follows that `length - 1 + offset_idx < OFFSETS`, therefore // `offset_idx < OFFSETS` is always true in this loop. - unsafe { crate::hint::assert_unchecked(offset_idx < OFFSETS) }; + // + // We need to use `intrinsics::assume` since the `panic_nounwind` contained + // in `hint::assert_unchecked` may not be optimized out. + unsafe { crate::intrinsics::assume(offset_idx < OFFSETS) }; let offset = offsets[offset_idx]; prefix_sum += offset as u32; if prefix_sum > total { From 70b588882781ff091a0bff927f8ff74c0d234798 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Tue, 4 Mar 2025 20:28:38 -0800 Subject: [PATCH 0087/2248] compiler: Use size_of from the prelude instead of imported Use `std::mem::{size_of, size_of_val, align_of, align_of_val}` from the prelude instead of importing or qualifying them. These functions were added to all preludes in Rust 1.80. --- src/builder.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index c8b7616e64509..6573b5b165e61 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -2439,9 +2439,5 @@ fn get_maybe_pointer_size(value: RValue<'_>) -> u32 { #[cfg(not(feature = "master"))] fn get_maybe_pointer_size(value: RValue<'_>) -> u32 { let type_ = value.get_type(); - if type_.get_pointee().is_some() { - std::mem::size_of::<*const ()>() as _ - } else { - type_.get_size() - } + if type_.get_pointee().is_some() { size_of::<*const ()>() as _ } else { type_.get_size() } } From 572da5cd261381451669d7d35c199e2227f9e6db Mon Sep 17 00:00:00 2001 From: Madhav Madhusoodanan Date: Sat, 8 Mar 2025 16:47:58 +0530 Subject: [PATCH 0088/2248] cleaned up tests by bringing objects under `mini_core` into scope --- example/mini_core.rs | 109 +++++++++--------- tests/run/abort1.rs | 41 +------ tests/run/abort2.rs | 41 +------ tests/run/array.rs | 10 +- tests/run/assign.rs | 127 +-------------------- tests/run/closure.rs | 39 ++----- tests/run/condition.rs | 26 ++--- tests/run/empty_main.rs | 30 +---- tests/run/exit.rs | 37 +------ tests/run/exit_code.rs | 30 +---- tests/run/float.rs | 4 - tests/run/fun_ptr.rs | 9 +- tests/run/int.rs | 4 - tests/run/mut_ref.rs | 131 +--------------------- tests/run/operations.rs | 225 +------------------------------------- tests/run/ptr_cast.rs | 9 +- tests/run/return-tuple.rs | 47 +------- tests/run/slice.rs | 13 +-- tests/run/static.rs | 78 +------------ tests/run/structs.rs | 45 +------- tests/run/tuple.rs | 37 +------ 21 files changed, 124 insertions(+), 968 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index bd7a4612a92cc..8d749c7a8f17d 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -51,6 +51,10 @@ impl LegacyReceiver for &T {} impl LegacyReceiver for &mut T {} impl LegacyReceiver for Box {} +#[lang = "receiver"] +trait Receiver { +} + #[lang = "copy"] pub trait Copy {} @@ -139,6 +143,14 @@ impl Mul for usize { } } +impl Mul for isize { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + self * rhs + } +} + #[lang = "add"] pub trait Add { type Output; @@ -162,6 +174,14 @@ impl Add for i8 { } } +impl Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + impl Add for usize { type Output = Self; @@ -193,6 +213,14 @@ impl Sub for usize { } } +impl Sub for isize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + impl Sub for u8 { type Output = Self; @@ -588,70 +616,43 @@ 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 { @@ -664,6 +665,10 @@ pub mod libc { pub fn memcpy(dst: *mut u8, src: *const u8, size: usize); pub fn memmove(dst: *mut u8, src: *const u8, size: usize); pub fn strncpy(dst: *mut u8, src: *const u8, size: usize); + pub fn fflush(stream: *mut i32) -> i32; + pub fn exit(status: i32); + + pub static stdout: *mut i32; } } diff --git a/tests/run/abort1.rs b/tests/run/abort1.rs index 696197d73772f..6561aaf25f6ed 100644 --- a/tests/run/abort1.rs +++ b/tests/run/abort1.rs @@ -3,47 +3,12 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -mod intrinsics { - use super::Sized; - - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; fn test_fail() -> ! { unsafe { intrinsics::abort() }; diff --git a/tests/run/abort2.rs b/tests/run/abort2.rs index 714cd6c0f3817..a9f176577fc79 100644 --- a/tests/run/abort2.rs +++ b/tests/run/abort2.rs @@ -3,47 +3,12 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -mod intrinsics { - use super::Sized; - - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; fn fail() -> i32 { unsafe { intrinsics::abort() }; diff --git a/tests/run/array.rs b/tests/run/array.rs index c3c08c29c6dba..b405102baff68 100644 --- a/tests/run/array.rs +++ b/tests/run/array.rs @@ -8,19 +8,11 @@ // 10 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - pub fn puts(s: *const u8) -> i32; - } -} +use mini_core::*; static mut ONE: usize = 1; diff --git a/tests/run/assign.rs b/tests/run/assign.rs index 2a47f0c2966e5..99a61337ada44 100644 --- a/tests/run/assign.rs +++ b/tests/run/assign.rs @@ -5,132 +5,12 @@ // 7 8 // 10 -#![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for *mut i32 {} -impl Copy for usize {} -impl Copy for u8 {} -impl Copy for i8 {} -impl Copy for i32 {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn puts(s: *const u8) -> i32; - pub fn fflush(stream: *mut i32) -> i32; - pub fn printf(format: *const i8, ...) -> i32; - - pub static stdout: *mut i32; - } -} - -mod intrinsics { - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -#[lang = "panic"] -#[track_caller] -#[no_mangle] -pub fn panic(_msg: &'static str) -> ! { - unsafe { - libc::puts("Panicking\0" as *const str as *const u8); - libc::fflush(libc::stdout); - intrinsics::abort(); - } -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} - -impl Add for u8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i32 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for usize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for isize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -#[track_caller] -#[lang = "panic_const_add_overflow"] -pub fn panic_const_add_overflow() -> ! { - panic("attempt to add with overflow"); -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; fn inc_ref(num: &mut isize) -> isize { *num = *num + 5; @@ -141,7 +21,6 @@ fn inc(num: isize) -> isize { num + 1 } - #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { argc = inc(argc); diff --git a/tests/run/closure.rs b/tests/run/closure.rs index 46c47bc54ed01..c8f06265c6b9a 100644 --- a/tests/run/closure.rs +++ b/tests/run/closure.rs @@ -9,54 +9,37 @@ // Both args: 11 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} +use mini_core::*; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { let string = "Arg: %d\n\0"; - let mut closure = || { - unsafe { - libc::printf(string as *const str as *const i8, argc); - } + let mut closure = || unsafe { + libc::printf(string as *const str as *const i8, argc); }; closure(); - let mut closure = || { - unsafe { - libc::printf("Argument: %d\n\0" as *const str as *const i8, argc); - } + let mut closure = || unsafe { + libc::printf("Argument: %d\n\0" as *const str as *const i8, argc); }; closure(); - let mut closure = |string| { - unsafe { - libc::printf(string as *const str as *const i8, argc); - } + let mut closure = |string| unsafe { + libc::printf(string as *const str as *const i8, argc); }; closure("String arg: %d\n\0"); - let mut closure = |arg: isize| { - unsafe { - libc::printf("Int argument: %d\n\0" as *const str as *const i8, arg); - } + let mut closure = |arg: isize| unsafe { + libc::printf("Int argument: %d\n\0" as *const str as *const i8, arg); }; closure(argc + 1); - let mut closure = |string, arg: isize| { - unsafe { - libc::printf(string as *const str as *const i8, arg); - } + let mut closure = |string, arg: isize| unsafe { + libc::printf(string as *const str as *const i8, arg); }; closure("Both args: %d\n\0", argc + 10); diff --git a/tests/run/condition.rs b/tests/run/condition.rs index 039ef94eaa717..d3714587401a8 100644 --- a/tests/run/condition.rs +++ b/tests/run/condition.rs @@ -6,18 +6,11 @@ // 1 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} +use mini_core::*; #[start] fn main(argc: isize, _argv: *const *const u8) -> isize { @@ -26,15 +19,14 @@ fn main(argc: isize, _argv: *const *const u8) -> isize { libc::printf(b"true\n\0" as *const u8 as *const i8); } - let string = - match argc { - 1 => b"1\n\0", - 2 => b"2\n\0", - 3 => b"3\n\0", - 4 => b"4\n\0", - 5 => b"5\n\0", - _ => b"_\n\0", - }; + let string = match argc { + 1 => b"1\n\0", + 2 => b"2\n\0", + 3 => b"3\n\0", + 4 => b"4\n\0", + 5 => b"5\n\0", + _ => b"_\n\0", + }; libc::printf(string as *const u8 as *const i8); } 0 diff --git a/tests/run/empty_main.rs b/tests/run/empty_main.rs index e66a859ad698e..c4a24e9b18546 100644 --- a/tests/run/empty_main.rs +++ b/tests/run/empty_main.rs @@ -3,36 +3,12 @@ // Run-time: // status: 0 -#![feature(auto_traits, lang_items, no_core, start)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { diff --git a/tests/run/exit.rs b/tests/run/exit.rs index bf1cbeef30205..3d66d8fbdb21a 100644 --- a/tests/run/exit.rs +++ b/tests/run/exit.rs @@ -3,43 +3,12 @@ // Run-time: // status: 2 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -mod libc { - #[link(name = "c")] - extern "C" { - pub fn exit(status: i32); - } -} - -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { diff --git a/tests/run/exit_code.rs b/tests/run/exit_code.rs index be7a233efdaaf..b18d08879f0dd 100644 --- a/tests/run/exit_code.rs +++ b/tests/run/exit_code.rs @@ -3,36 +3,12 @@ // Run-time: // status: 1 -#![feature(auto_traits, lang_items, no_core, start)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { diff --git a/tests/run/float.rs b/tests/run/float.rs index e0a57e6fed1a8..424fa1cf4ad53 100644 --- a/tests/run/float.rs +++ b/tests/run/float.rs @@ -5,10 +5,6 @@ #![feature(const_black_box)] -/* - * Code - */ - fn main() { use std::hint::black_box; diff --git a/tests/run/fun_ptr.rs b/tests/run/fun_ptr.rs index ed1bf72bb2754..45b4ebcd9f05e 100644 --- a/tests/run/fun_ptr.rs +++ b/tests/run/fun_ptr.rs @@ -5,18 +5,11 @@ // stdout: 1 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} +use mini_core::*; fn i16_as_i8(a: i16) -> i8 { a as i8 diff --git a/tests/run/int.rs b/tests/run/int.rs index bfe73c38435a3..47b5dea46f8de 100644 --- a/tests/run/int.rs +++ b/tests/run/int.rs @@ -5,10 +5,6 @@ #![feature(const_black_box)] -/* - * Code - */ - fn main() { use std::hint::black_box; diff --git a/tests/run/mut_ref.rs b/tests/run/mut_ref.rs index 3ae793382164b..5c91bc96ca000 100644 --- a/tests/run/mut_ref.rs +++ b/tests/run/mut_ref.rs @@ -1,4 +1,3 @@ - // Compiler: // // Run-time: @@ -7,141 +6,19 @@ // 6 // 11 -#![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for *mut i32 {} -impl Copy for usize {} -impl Copy for u8 {} -impl Copy for i8 {} -impl Copy for i32 {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn puts(s: *const u8) -> i32; - pub fn fflush(stream: *mut i32) -> i32; - pub fn printf(format: *const i8, ...) -> i32; - - pub static stdout: *mut i32; - } -} - -mod intrinsics { - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -#[lang = "panic"] -#[track_caller] -#[no_mangle] -pub fn panic(_msg: &'static str) -> ! { - unsafe { - libc::puts("Panicking\0" as *const str as *const u8); - libc::fflush(libc::stdout); - intrinsics::abort(); - } -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} - -impl Add for u8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i32 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for usize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for isize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -#[track_caller] -#[lang = "panic_const_add_overflow"] -pub fn panic_const_add_overflow() -> ! { - panic("attempt to add with overflow"); -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; struct Test { field: isize, } fn test(num: isize) -> Test { - Test { - field: num + 1, - } + Test { field: num + 1 } } fn update_num(num: &mut isize) { diff --git a/tests/run/operations.rs b/tests/run/operations.rs index 0e44fc580b8c4..a298cf2a68d5c 100644 --- a/tests/run/operations.rs +++ b/tests/run/operations.rs @@ -5,231 +5,12 @@ // 39 // 10 -#![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types, rustc_attrs)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for *mut i32 {} -impl Copy for usize {} -impl Copy for u8 {} -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} - -#[lang = "deref"] -pub trait Deref { - type Target: ?Sized; - - fn deref(&self) -> &Self::Target; -} - -#[lang = "legacy_receiver"] -trait LegacyReceiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - pub fn puts(s: *const u8) -> i32; - pub fn fflush(stream: *mut i32) -> i32; - - pub static stdout: *mut i32; - } -} - -mod intrinsics { - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -#[lang = "panic"] -#[track_caller] -#[no_mangle] -pub fn panic(_msg: &'static str) -> ! { - unsafe { - libc::puts("Panicking\0" as *const str as *const u8); - libc::fflush(libc::stdout); - intrinsics::abort(); - } -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} - -impl Add for u8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i32 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for usize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for isize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -#[lang = "sub"] -pub trait Sub { - type Output; - - fn sub(self, rhs: RHS) -> Self::Output; -} - -impl Sub for usize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for isize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for u8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for i8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for i16 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -#[lang = "mul"] -pub trait Mul { - type Output; - - #[must_use] - fn mul(self, rhs: RHS) -> Self::Output; -} - -impl Mul for u8 { - type Output = Self; - - fn mul(self, rhs: Self) -> Self::Output { - self * rhs - } -} - -impl Mul for usize { - type Output = Self; - - fn mul(self, rhs: Self) -> Self::Output { - self * rhs - } -} - -impl Mul for isize { - type Output = Self; - - fn mul(self, rhs: Self) -> Self::Output { - self * rhs - } -} - -#[track_caller] -#[lang = "panic_const_add_overflow"] -pub fn panic_const_add_overflow() -> ! { - panic("attempt to add with overflow"); -} - -#[track_caller] -#[lang = "panic_const_sub_overflow"] -pub fn panic_const_sub_overflow() -> ! { - panic("attempt to subtract with overflow"); -} - -#[track_caller] -#[lang = "panic_const_mul_overflow"] -pub fn panic_const_mul_overflow() -> ! { - panic("attempt to multiply with overflow"); -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { diff --git a/tests/run/ptr_cast.rs b/tests/run/ptr_cast.rs index 2b8812ad51c5e..eb4cf3eafd0ee 100644 --- a/tests/run/ptr_cast.rs +++ b/tests/run/ptr_cast.rs @@ -5,18 +5,11 @@ // stdout: 1 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} +use mini_core::*; static mut ONE: usize = 1; diff --git a/tests/run/return-tuple.rs b/tests/run/return-tuple.rs index f2a5a2e4384df..c3069933e0854 100644 --- a/tests/run/return-tuple.rs +++ b/tests/run/return-tuple.rs @@ -6,53 +6,12 @@ // 10 // 42 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -#[lang = "copy"] -pub unsafe trait Copy {} - -impl Copy for bool {} -impl Copy for u8 {} -impl Copy for u16 {} -impl Copy for u32 {} -impl Copy for u64 {} -impl Copy for usize {} -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for isize {} -impl Copy for f32 {} -impl Copy for char {} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} - -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "legacy_receiver"] -trait LegacyReceiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u32) { ( diff --git a/tests/run/slice.rs b/tests/run/slice.rs index fba93fc155495..6f2f8b9a9cec6 100644 --- a/tests/run/slice.rs +++ b/tests/run/slice.rs @@ -5,25 +5,16 @@ // stdout: 5 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} +use mini_core::*; static mut TWO: usize = 2; fn index_slice(s: &[u32]) -> u32 { - unsafe { - s[TWO] - } + unsafe { s[TWO] } } #[start] diff --git a/tests/run/static.rs b/tests/run/static.rs index a17ea2a48936d..5fc167ce4e479 100644 --- a/tests/run/static.rs +++ b/tests/run/static.rs @@ -9,72 +9,12 @@ // 12 // 1 -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "destruct"] -pub trait Destruct {} - -#[lang = "drop"] -pub trait Drop {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for *mut T {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -mod intrinsics { - use super::Sized; - - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} - -#[lang = "structural_peq"] -pub trait StructuralPartialEq {} - -#[lang = "drop_in_place"] -#[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { - // Code here does not matter - this is replaced by the - // real drop glue by the compiler. - drop_in_place(to_drop); -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; struct Test { field: isize, @@ -86,17 +26,11 @@ struct WithRef { static mut CONSTANT: isize = 10; -static mut TEST: Test = Test { - field: 12, -}; +static mut TEST: Test = Test { field: 12 }; -static mut TEST2: Test = Test { - field: 14, -}; +static mut TEST2: Test = Test { field: 14 }; -static mut WITH_REF: WithRef = WithRef { - refe: unsafe { &TEST }, -}; +static mut WITH_REF: WithRef = WithRef { refe: unsafe { &TEST } }; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { diff --git a/tests/run/structs.rs b/tests/run/structs.rs index d6455667400c9..641c6c71d1e02 100644 --- a/tests/run/structs.rs +++ b/tests/run/structs.rs @@ -5,43 +5,12 @@ // stdout: 1 // 2 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; struct Test { field: isize, @@ -57,12 +26,8 @@ fn one() -> isize { #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { - let test = Test { - field: one(), - }; - let two = Two { - two: 2, - }; + let test = Test { field: one() }; + let two = Two { two: 2 }; unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field); libc::printf(b"%ld\n\0" as *const u8 as *const i8, two.two); diff --git a/tests/run/tuple.rs b/tests/run/tuple.rs index 8a7d85ae867e8..1f2d24eeacc51 100644 --- a/tests/run/tuple.rs +++ b/tests/run/tuple.rs @@ -4,43 +4,12 @@ // status: 0 // stdout: 3 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { From 224dad154bd055bf3fb792ae51f9c6d91a927f9b Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 8 Mar 2025 12:47:40 +0100 Subject: [PATCH 0089/2248] Fix formatting. --- .../unicode-table-generator/src/skiplist.rs | 41 ++++--------------- 1 file changed, 7 insertions(+), 34 deletions(-) diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs index e4c3d96546f1e..d3e5c9eded243 100644 --- a/src/tools/unicode-table-generator/src/skiplist.rs +++ b/src/tools/unicode-table-generator/src/skiplist.rs @@ -68,10 +68,7 @@ impl RawEmitter { assert!(inserted); } - writeln!( - &mut self.file, - "use super::ShortOffsetRunHeader;\n" - ).unwrap(); + writeln!(&mut self.file, "use super::ShortOffsetRunHeader;\n").unwrap(); writeln!( &mut self.file, "static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; {}] = [{}];", @@ -111,46 +108,22 @@ impl RawEmitter { } else { writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); } - writeln!( - &mut self.file, - " const {{", - ) - .unwrap(); + writeln!(&mut self.file, " const {{").unwrap(); writeln!( &mut self.file, " assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32));", ) .unwrap(); - writeln!( - &mut self.file, - " let mut i = 0;", - ) - .unwrap(); - writeln!( - &mut self.file, - " while i < SHORT_OFFSET_RUNS.len() {{", - ) - .unwrap(); + writeln!(&mut self.file, " let mut i = 0;").unwrap(); + writeln!(&mut self.file, " while i < SHORT_OFFSET_RUNS.len() {{").unwrap(); writeln!( &mut self.file, " assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len());", ) .unwrap(); - writeln!( - &mut self.file, - " i += 1;", - ) - .unwrap(); - writeln!( - &mut self.file, - " }}", - ) - .unwrap(); - writeln!( - &mut self.file, - " }}", - ) - .unwrap(); + writeln!(&mut self.file, " i += 1;").unwrap(); + writeln!(&mut self.file, " }}").unwrap(); + writeln!(&mut self.file, " }}").unwrap(); writeln!( &mut self.file, " // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`", From 3628a8f326d1f323832aeae742ab3bbd025e4166 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 8 Mar 2025 12:56:00 +0100 Subject: [PATCH 0090/2248] Remove unneeded parentheses. --- library/core/src/unicode/unicode_data.rs | 12 ++++++------ src/tools/unicode-table-generator/src/skiplist.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 63d1581145868..25b9c6e0e0e94 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -224,7 +224,7 @@ pub mod alphabetic { ]; pub fn lookup(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); @@ -299,7 +299,7 @@ pub mod case_ignorable { ]; pub fn lookup(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); @@ -345,7 +345,7 @@ pub mod cased { ]; pub fn lookup(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); @@ -370,7 +370,7 @@ pub mod cc { ]; pub fn lookup(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); @@ -443,7 +443,7 @@ pub mod grapheme_extend { #[inline(never)] fn lookup_slow(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); @@ -605,7 +605,7 @@ pub mod n { ]; pub fn lookup(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs index d3e5c9eded243..34c9802e122f6 100644 --- a/src/tools/unicode-table-generator/src/skiplist.rs +++ b/src/tools/unicode-table-generator/src/skiplist.rs @@ -111,7 +111,7 @@ impl RawEmitter { writeln!(&mut self.file, " const {{").unwrap(); writeln!( &mut self.file, - " assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32));", + " assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32);", ) .unwrap(); writeln!(&mut self.file, " let mut i = 0;").unwrap(); From 0af04455f1aec53fcd37f67c45d362df76364947 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Sat, 8 Mar 2025 10:54:45 -0500 Subject: [PATCH 0091/2248] Make `visit_map` happy path more evident --- clippy_config/src/conf.rs | 55 +++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 75f68d0dc5f9d..7d94525e6d25a 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -218,42 +218,53 @@ macro_rules! define_Conf { let mut value_spans = HashMap::new(); let mut errors = Vec::new(); let mut warnings = Vec::new(); + + // Declare a local variable for each field field available to a configuration file. $(let mut $name = None;)* + // could get `Field` here directly, but get `String` first for diagnostics while let Some(name) = map.next_key::>()? { - match Field::deserialize(name.get_ref().as_str().into_deserializer()) { + let field = match Field::deserialize(name.get_ref().as_str().into_deserializer()) { Err(e) => { let e: FieldError = e; errors.push(ConfError::spanned(self.0, e.error, e.suggestion, name.span())); + continue; } - $(Ok(Field::$name) => { + Ok(field) => field + }; + + match field { + $(Field::$name => { + // Is this a deprecated field, i.e., is `$dep` set? If so, push a warning. $(warnings.push(ConfError::spanned(self.0, format!("deprecated field `{}`. {}", name.get_ref(), $dep), None, name.span()));)? let raw_value = map.next_value::>()?; let value_span = raw_value.span(); - match <$ty>::deserialize(raw_value.into_inner()) { - Err(e) => errors.push(ConfError::spanned(self.0, e.to_string().replace('\n', " ").trim(), None, value_span)), - Ok(value) => match $name { - Some(_) => { - errors.push(ConfError::spanned(self.0, format!("duplicate field `{}`", name.get_ref()), None, name.span())); - } - None => { - $name = Some(value); - value_spans.insert(name.get_ref().as_str().to_string(), value_span); - // $new_conf is the same as one of the defined `$name`s, so - // this variable is defined in line 2 of this function. - $(match $new_conf { - Some(_) => errors.push(ConfError::spanned(self.0, concat!( - "duplicate field `", stringify!($new_conf), - "` (provided as `", stringify!($name), "`)" - ), None, name.span())), - None => $new_conf = $name.clone(), - })? - }, + let value = match <$ty>::deserialize(raw_value.into_inner()) { + Err(e) => { + errors.push(ConfError::spanned(self.0, e.to_string().replace('\n', " ").trim(), None, value_span)); + continue; } + Ok(value) => value + }; + // Was this field set previously? + if $name.is_some() { + errors.push(ConfError::spanned(self.0, format!("duplicate field `{}`", name.get_ref()), None, name.span())); + continue; } + $name = Some(value); + value_spans.insert(name.get_ref().as_str().to_string(), value_span); + // If this is a deprecated field, was the new field (`$new_conf`) set previously? + // Note that `$new_conf` is one of the defined `$name`s. + $(match $new_conf { + Some(_) => errors.push(ConfError::spanned(self.0, concat!( + "duplicate field `", stringify!($new_conf), + "` (provided as `", stringify!($name), "`)" + ), None, name.span())), + None => $new_conf = $name.clone(), + })? })* // ignore contents of the third_party key - Ok(Field::third_party) => drop(map.next_value::()) + Field::third_party => drop(map.next_value::()) } } let conf = Conf { $($name: $name.unwrap_or_else(defaults::$name),)* }; From 680e6f35bcd3f23b9f98e05a3c193405bb69c510 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Mon, 10 Mar 2025 10:43:28 +0100 Subject: [PATCH 0092/2248] Fix diagnostics being cleared right after being received --- src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs index 7529e7c188f8a..dd5103258069e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs @@ -401,7 +401,9 @@ impl FlycheckActor { package_id = package_id.as_ref().map(|it| &it.repr), "diagnostic received" ); - self.diagnostics_received = DiagnosticsReceived::Yes; + if self.diagnostics_received == DiagnosticsReceived::No { + self.diagnostics_received = DiagnosticsReceived::Yes; + } if let Some(package_id) = &package_id { if self.diagnostics_cleared_for.insert(package_id.clone()) { tracing::trace!( From 1ba439124dd8e695c1eeb4b689bb322a4ce5a473 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 10 Mar 2025 10:39:04 +0100 Subject: [PATCH 0093/2248] Make change annotations per text-edit --- .../crates/ide-assists/src/tests.rs | 25 +++-------- .../crates/ide-completion/src/render.rs | 3 +- .../rust-analyzer/crates/ide-db/src/rename.rs | 8 +--- .../crates/ide-db/src/text_edit.rs | 21 ++++----- .../rust-analyzer/crates/ide/src/rename.rs | 29 +----------- src/tools/rust-analyzer/crates/ide/src/ssr.rs | 6 +-- .../crates/rust-analyzer/src/lsp/to_proto.rs | 45 ++++++++++++------- 7 files changed, 53 insertions(+), 84 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs index 7d7012c462222..b4042abf5d649 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -710,24 +710,21 @@ pub fn test_some_range(a: int) -> bool { Indel { insert: "let", delete: 45..47, - annotation: None, }, Indel { insert: "var_name", delete: 48..60, - annotation: None, }, Indel { insert: "=", delete: 61..81, - annotation: None, }, Indel { insert: "5;\n if let 2..6 = var_name {\n true\n } else {\n false\n }", delete: 82..108, - annotation: None, }, ], + annotation: None, }, Some( SnippetEdit( @@ -845,24 +842,21 @@ pub fn test_some_range(a: int) -> bool { Indel { insert: "let", delete: 45..47, - annotation: None, }, Indel { insert: "var_name", delete: 48..60, - annotation: None, }, Indel { insert: "=", delete: 61..81, - annotation: None, }, Indel { insert: "5;\n if let 2..6 = var_name {\n true\n } else {\n false\n }", delete: 82..108, - annotation: None, }, ], + annotation: None, }, Some( SnippetEdit( @@ -914,29 +908,25 @@ pub fn test_some_range(a: int) -> bool { Indel { insert: "const", delete: 45..47, - annotation: None, }, Indel { insert: "VAR_NAME:", delete: 48..60, - annotation: None, }, Indel { insert: "i32", delete: 61..81, - annotation: None, }, Indel { insert: "=", delete: 82..86, - annotation: None, }, Indel { insert: "5;\n if let 2..6 = VAR_NAME {\n true\n } else {\n false\n }", delete: 87..108, - annotation: None, }, ], + annotation: None, }, Some( SnippetEdit( @@ -988,29 +978,25 @@ pub fn test_some_range(a: int) -> bool { Indel { insert: "static", delete: 45..47, - annotation: None, }, Indel { insert: "VAR_NAME:", delete: 48..60, - annotation: None, }, Indel { insert: "i32", delete: 61..81, - annotation: None, }, Indel { insert: "=", delete: 82..86, - annotation: None, }, Indel { insert: "5;\n if let 2..6 = VAR_NAME {\n true\n } else {\n false\n }", delete: 87..108, - annotation: None, }, ], + annotation: None, }, Some( SnippetEdit( @@ -1062,14 +1048,13 @@ pub fn test_some_range(a: int) -> bool { Indel { insert: "fun_name()", delete: 59..60, - annotation: None, }, Indel { insert: "\n\nfn fun_name() -> i32 {\n 5\n}", delete: 110..110, - annotation: None, }, ], + annotation: None, }, Some( SnippetEdit( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 4d0a4a4782247..90abd4337f4ae 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -2770,14 +2770,13 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } Indel { insert: "(", delete: 107..107, - annotation: None, }, Indel { insert: "qux)()", delete: 109..110, - annotation: None, }, ], + annotation: None, }, kind: SymbolKind( Field, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs index 1633065f65217..a7584f67f118c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs @@ -367,14 +367,10 @@ fn rename_reference( ) })); - let mut insert_def_edit = |def| { - let (file_id, edit) = source_edit_from_def(sema, def, new_name, &mut source_change)?; - source_change.insert_source_edit(file_id, edit); - Ok(()) - }; // This needs to come after the references edits, because we change the annotation of existing edits // if a conflict is detected. - insert_def_edit(def)?; + let (file_id, edit) = source_edit_from_def(sema, def, new_name, &mut source_change)?; + source_change.insert_source_edit(file_id, edit); Ok(source_change) } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/text_edit.rs b/src/tools/rust-analyzer/crates/ide-db/src/text_edit.rs index b59010f2f8c83..6e9bd7bdcc21a 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/text_edit.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/text_edit.rs @@ -18,18 +18,19 @@ pub struct Indel { pub insert: String, /// Refers to offsets in the original text pub delete: TextRange, - pub annotation: Option, } #[derive(Default, Debug, Clone)] pub struct TextEdit { /// Invariant: disjoint and sorted by `delete`. indels: Vec, + annotation: Option, } #[derive(Debug, Default, Clone)] pub struct TextEditBuilder { indels: Vec, + annotation: Option, } impl Indel { @@ -40,7 +41,7 @@ impl Indel { Indel::replace(range, String::new()) } pub fn replace(range: TextRange, replace_with: String) -> Indel { - Indel { delete: range, insert: replace_with, annotation: None } + Indel { delete: range, insert: replace_with } } pub fn apply(&self, text: &mut String) { @@ -142,12 +143,12 @@ impl TextEdit { Some(res) } - pub fn set_annotation(&mut self, annotation: Option) { - if annotation.is_some() { - for indel in &mut self.indels { - indel.annotation = annotation; - } - } + pub(crate) fn set_annotation(&mut self, conflict_annotation: Option) { + self.annotation = conflict_annotation; + } + + pub fn change_annotation(&self) -> Option { + self.annotation } } @@ -183,10 +184,10 @@ impl TextEditBuilder { self.indel(Indel::insert(offset, text)); } pub fn finish(self) -> TextEdit { - let mut indels = self.indels; + let TextEditBuilder { mut indels, annotation } = self; assert_disjoint_or_equal(&mut indels); indels = coalesce_indels(indels); - TextEdit { indels } + TextEdit { indels, annotation } } pub fn invalidates_offset(&self, offset: TextSize) -> bool { self.indels.iter().any(|indel| indel.delete.contains_inclusive(offset)) diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs index d0e1c2097a7a9..08e25dde60631 100644 --- a/src/tools/rust-analyzer/crates/ide/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs @@ -509,10 +509,9 @@ mod tests { let found_conflicts = source_change .source_file_edits .iter() + .filter(|(_, (edit, _))| edit.change_annotation().is_some()) .flat_map(|(file_id, (edit, _))| { - edit.into_iter() - .filter(|edit| edit.annotation.is_some()) - .map(move |edit| (*file_id, edit.delete)) + edit.into_iter().map(move |edit| (*file_id, edit.delete)) }) .sorted_unstable_by_key(|(file_id, range)| (*file_id, range.start())) .collect_vec(); @@ -1081,7 +1080,6 @@ mod foo$0; Indel { insert: "foo2", delete: 4..7, - annotation: None, }, ], ), @@ -1129,7 +1127,6 @@ use crate::foo$0::FooContent; Indel { insert: "quux", delete: 8..11, - annotation: None, }, ], ), @@ -1141,7 +1138,6 @@ use crate::foo$0::FooContent; Indel { insert: "quux", delete: 11..14, - annotation: None, }, ], ), @@ -1183,7 +1179,6 @@ mod fo$0o; Indel { insert: "foo2", delete: 4..7, - annotation: None, }, ], ), @@ -1232,7 +1227,6 @@ mod outer { mod fo$0o; } Indel { insert: "bar", delete: 16..19, - annotation: None, }, ], ), @@ -1304,7 +1298,6 @@ pub mod foo$0; Indel { insert: "foo2", delete: 27..30, - annotation: None, }, ], ), @@ -1316,7 +1309,6 @@ pub mod foo$0; Indel { insert: "foo2", delete: 8..11, - annotation: None, }, ], ), @@ -1372,7 +1364,6 @@ mod quux; Indel { insert: "foo2", delete: 4..7, - annotation: None, }, ], ), @@ -1506,12 +1497,10 @@ pub fn baz() {} Indel { insert: "r#fn", delete: 4..7, - annotation: None, }, Indel { insert: "r#fn", delete: 22..25, - annotation: None, }, ], ), @@ -1576,12 +1565,10 @@ pub fn baz() {} Indel { insert: "foo", delete: 4..8, - annotation: None, }, Indel { insert: "foo", delete: 23..27, - annotation: None, }, ], ), @@ -1643,7 +1630,6 @@ fn bar() { Indel { insert: "dyn", delete: 7..10, - annotation: None, }, ], ), @@ -1655,7 +1641,6 @@ fn bar() { Indel { insert: "r#dyn", delete: 18..21, - annotation: None, }, ], ), @@ -1685,7 +1670,6 @@ fn bar() { Indel { insert: "r#dyn", delete: 7..10, - annotation: None, }, ], ), @@ -1697,7 +1681,6 @@ fn bar() { Indel { insert: "dyn", delete: 18..21, - annotation: None, }, ], ), @@ -1727,7 +1710,6 @@ fn bar() { Indel { insert: "r#dyn", delete: 7..10, - annotation: None, }, ], ), @@ -1739,7 +1721,6 @@ fn bar() { Indel { insert: "dyn", delete: 18..21, - annotation: None, }, ], ), @@ -1776,12 +1757,10 @@ fn bar() { Indel { insert: "abc", delete: 7..10, - annotation: None, }, Indel { insert: "abc", delete: 32..35, - annotation: None, }, ], ), @@ -1793,7 +1772,6 @@ fn bar() { Indel { insert: "abc", delete: 18..23, - annotation: None, }, ], ), @@ -1827,12 +1805,10 @@ fn bar() { Indel { insert: "abc", delete: 7..12, - annotation: None, }, Indel { insert: "abc", delete: 34..39, - annotation: None, }, ], ), @@ -1844,7 +1820,6 @@ fn bar() { Indel { insert: "abc", delete: 18..21, - annotation: None, }, ], ), diff --git a/src/tools/rust-analyzer/crates/ide/src/ssr.rs b/src/tools/rust-analyzer/crates/ide/src/ssr.rs index 90e350949b81f..5812a92b3893f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/ssr.rs +++ b/src/tools/rust-analyzer/crates/ide/src/ssr.rs @@ -139,9 +139,9 @@ mod tests { Indel { insert: "3", delete: 33..34, - annotation: None, }, ], + annotation: None, }, None, ), @@ -182,9 +182,9 @@ mod tests { Indel { insert: "3", delete: 33..34, - annotation: None, }, ], + annotation: None, }, None, ), @@ -196,9 +196,9 @@ mod tests { Indel { insert: "3", delete: 11..12, - annotation: None, }, ], + annotation: None, }, None, ), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index 6db7bcb11102c..70e567ec76920 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -16,7 +16,7 @@ use ide::{ SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize, UpdateTest, }; -use ide_db::{assists, rust_doc::format_docs, FxHasher}; +use ide_db::{assists, rust_doc::format_docs, source_change::ChangeAnnotationId, FxHasher}; use itertools::Itertools; use paths::{Utf8Component, Utf8Prefix}; use semver::VersionReq; @@ -200,10 +200,10 @@ pub(crate) fn snippet_text_edit( line_index: &LineIndex, is_snippet: bool, indel: Indel, + annotation: Option, client_supports_annotations: bool, ) -> lsp_ext::SnippetTextEdit { - let annotation_id = - indel.annotation.filter(|_| client_supports_annotations).map(|it| it.to_string()); + let annotation_id = annotation.filter(|_| client_supports_annotations).map(|it| it.to_string()); let text_edit = text_edit(line_index, indel); let insert_text_format = if is_snippet { Some(lsp_types::InsertTextFormat::SNIPPET) } else { None }; @@ -228,10 +228,17 @@ pub(crate) fn snippet_text_edit_vec( text_edit: TextEdit, clients_support_annotations: bool, ) -> Vec { + let annotation = text_edit.change_annotation(); text_edit .into_iter() .map(|indel| { - self::snippet_text_edit(line_index, is_snippet, indel, clients_support_annotations) + self::snippet_text_edit( + line_index, + is_snippet, + indel, + annotation, + clients_support_annotations, + ) }) .collect() } @@ -1082,6 +1089,7 @@ fn merge_text_and_snippet_edits( ) -> Vec { let mut edits: Vec = vec![]; let mut snippets = snippet_edit.into_edit_ranges().into_iter().peekable(); + let annotation = edit.change_annotation(); let text_edits = edit.into_iter(); // offset to go from the final source location to the original source location let mut source_text_offset = 0i32; @@ -1127,11 +1135,8 @@ fn merge_text_and_snippet_edits( edits.push(snippet_text_edit( line_index, true, - Indel { - insert: format!("${snippet_index}"), - delete: snippet_range, - annotation: None, - }, + Indel { insert: format!("${snippet_index}"), delete: snippet_range }, + annotation, client_supports_annotations, )) } @@ -1190,11 +1195,8 @@ fn merge_text_and_snippet_edits( edits.push(snippet_text_edit( line_index, true, - Indel { - insert: new_text, - delete: current_indel.delete, - annotation: current_indel.annotation, - }, + Indel { insert: new_text, delete: current_indel.delete }, + annotation, client_supports_annotations, )) } else { @@ -1204,6 +1206,7 @@ fn merge_text_and_snippet_edits( line_index, false, current_indel, + annotation, client_supports_annotations, )); } @@ -1230,7 +1233,8 @@ fn merge_text_and_snippet_edits( snippet_text_edit( line_index, true, - Indel { insert: format!("${snippet_index}"), delete: snippet_range, annotation: None }, + Indel { insert: format!("${snippet_index}"), delete: snippet_range }, + annotation, client_supports_annotations, ) })); @@ -1251,8 +1255,17 @@ pub(crate) fn snippet_text_document_edit( let mut edits = if let Some(snippet_edit) = snippet_edit { merge_text_and_snippet_edits(&line_index, edit, snippet_edit, client_supports_annotations) } else { + let annotation = edit.change_annotation(); edit.into_iter() - .map(|it| snippet_text_edit(&line_index, is_snippet, it, client_supports_annotations)) + .map(|it| { + snippet_text_edit( + &line_index, + is_snippet, + it, + annotation, + client_supports_annotations, + ) + }) .collect() }; From 1dd859f65865415a84837e487f54a1a69eb05b12 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 10 Mar 2025 06:47:02 +0100 Subject: [PATCH 0094/2248] Add missing name-ref parents to syntactic highlighting --- .../crates/ide/src/syntax_highlighting/highlight.rs | 3 +++ .../syntax_highlighting/test_data/highlight_doctest.html | 9 ++++----- .../crates/ide/src/syntax_highlighting/tests.rs | 9 ++++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index 282fbb4433b22..2b7c871a386d2 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -824,6 +824,7 @@ fn highlight_name_ref_by_syntax( h.into() } } + RECORD_EXPR_FIELD | RECORD_PAT_FIELD => HlTag::Symbol(SymbolKind::Field).into(), PATH_SEGMENT => { let name_based_fallback = || { if name.text().chars().next().unwrap_or_default().is_uppercase() { @@ -862,6 +863,8 @@ fn highlight_name_ref_by_syntax( .into(), } } + ASSOC_TYPE_ARG => SymbolKind::TypeAlias.into(), + USE_BOUND_GENERIC_ARG => SymbolKind::TypeParam.into(), _ => default.into(), } } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index c8c8c5dba4c40..d00f279c82995 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -45,14 +45,13 @@ //! fn test() {} //! ``` +//! Syntactic name ref highlighting testing //! ```rust //! extern crate self; -//! extern crate std; +//! extern crate other as otter; //! extern crate core; -//! extern crate alloc; -//! extern crate proc_macro; -//! extern crate test; -//! extern crate Krate; +//! trait T { type Assoc; } +//! fn f<Arg>() -> use<Arg> where (): T<Assoc = ()> {} //! ``` mod outline_module; diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index 8f69bb8230000..9e8af4bac2277 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -739,14 +739,13 @@ fn test_highlight_doc_comment() { //! fn test() {} //! ``` +//! Syntactic name ref highlighting testing //! ```rust //! extern crate self; -//! extern crate std; +//! extern crate other as otter; //! extern crate core; -//! extern crate alloc; -//! extern crate proc_macro; -//! extern crate test; -//! extern crate Krate; +//! trait T { type Assoc; } +//! fn f() -> use where (): T {} //! ``` mod outline_module; From 99fe5167e55644b542d38150b9fd1c370ed2fe09 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 10 Mar 2025 13:57:26 +0100 Subject: [PATCH 0095/2248] Remove generated md book files --- src/tools/rust-analyzer/docs/book/README.md | 1 + .../docs/book/src/assists_generated.md | 3890 ----------------- .../docs/book/src/diagnostics_generated.md | 516 --- .../docs/book/src/features_generated.md | 940 ---- 4 files changed, 1 insertion(+), 5346 deletions(-) delete mode 100644 src/tools/rust-analyzer/docs/book/src/assists_generated.md delete mode 100644 src/tools/rust-analyzer/docs/book/src/diagnostics_generated.md delete mode 100644 src/tools/rust-analyzer/docs/book/src/features_generated.md diff --git a/src/tools/rust-analyzer/docs/book/README.md b/src/tools/rust-analyzer/docs/book/README.md index 043524b2341b7..464ea02512f74 100644 --- a/src/tools/rust-analyzer/docs/book/README.md +++ b/src/tools/rust-analyzer/docs/book/README.md @@ -8,6 +8,7 @@ To run the documentation site locally: ```shell cargo install mdbook +cargo xtask codegen cd docs/book mdbook serve # make changes to documentation files in doc/book/src diff --git a/src/tools/rust-analyzer/docs/book/src/assists_generated.md b/src/tools/rust-analyzer/docs/book/src/assists_generated.md deleted file mode 100644 index 9a80185179279..0000000000000 --- a/src/tools/rust-analyzer/docs/book/src/assists_generated.md +++ /dev/null @@ -1,3890 +0,0 @@ -//! Generated by `cargo xtask codegen assists-doc-tests`, do not edit by hand. - -### `add_braces` -**Source:** [add_braces.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_braces.rs#L8) - -Adds braces to lambda and match arm expressions. - -#### Before -```rust -fn foo(n: i32) -> i32 { - match n { - 1 =>┃ n + 1, - _ => 0 - } -} -``` - -#### After -```rust -fn foo(n: i32) -> i32 { - match n { - 1 => { - n + 1 - }, - _ => 0 - } -} -``` - - -### `add_explicit_enum_discriminant` -**Source:** [add_explicit_enum_discriminant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs#L11) - -Adds explicit discriminant to all enum variants. - -#### Before -```rust -enum TheEnum┃ { - Foo, - Bar, - Baz = 42, - Quux, -} -``` - -#### After -```rust -enum TheEnum { - Foo = 0, - Bar = 1, - Baz = 42, - Quux = 43, -} -``` - - -### `add_explicit_type` -**Source:** [add_explicit_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_explicit_type.rs#L7) - -Specify type for a let binding. - -#### Before -```rust -fn main() { - let x┃ = 92; -} -``` - -#### After -```rust -fn main() { - let x: i32 = 92; -} -``` - - -### `add_hash` -**Source:** [raw_string.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/raw_string.rs#L89) - -Adds a hash to a raw string literal. - -#### Before -```rust -fn main() { - r#"Hello,┃ World!"#; -} -``` - -#### After -```rust -fn main() { - r##"Hello, World!"##; -} -``` - - -### `add_impl_default_members` -**Source:** [add_missing_impl_members.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_missing_impl_members.rs#L58) - -Adds scaffold for overriding default impl members. - -#### Before -```rust -trait Trait { - type X; - fn foo(&self); - fn bar(&self) {} -} - -impl Trait for () { - type X = (); - fn foo(&self) {}┃ -} -``` - -#### After -```rust -trait Trait { - type X; - fn foo(&self); - fn bar(&self) {} -} - -impl Trait for () { - type X = (); - fn foo(&self) {} - - ┃fn bar(&self) {} -} -``` - - -### `add_impl_missing_members` -**Source:** [add_missing_impl_members.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_missing_impl_members.rs#L16) - -Adds scaffold for required impl members. - -#### Before -```rust -trait Trait { - type X; - fn foo(&self) -> T; - fn bar(&self) {} -} - -impl Trait for () {┃ - -} -``` - -#### After -```rust -trait Trait { - type X; - fn foo(&self) -> T; - fn bar(&self) {} -} - -impl Trait for () { - ┃type X; - - fn foo(&self) -> u32 { - todo!() - } -} -``` - - -### `add_label_to_loop` -**Source:** [add_label_to_loop.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_label_to_loop.rs#L9) - -Adds a label to a loop. - -#### Before -```rust -fn main() { - loop┃ { - break; - continue; - } -} -``` - -#### After -```rust -fn main() { - 'l: loop { - break 'l; - continue 'l; - } -} -``` - - -### `add_lifetime_to_type` -**Source:** [add_lifetime_to_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_lifetime_to_type.rs#L5) - -Adds a new lifetime to a struct, enum or union. - -#### Before -```rust -struct Point { - x: &┃u32, - y: u32, -} -``` - -#### After -```rust -struct Point<'a> { - x: &'a u32, - y: u32, -} -``` - - -### `add_missing_match_arms` -**Source:** [add_missing_match_arms.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_missing_match_arms.rs#L16) - -Adds missing clauses to a `match` expression. - -#### Before -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - match action { - ┃ - } -} -``` - -#### After -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - match action { - Action::Move { distance } => ${1:todo!()}, - Action::Stop => ${2:todo!()},┃ - } -} -``` - - -### `add_return_type` -**Source:** [add_return_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_return_type.rs#L6) - -Adds the return type to a function or closure inferred from its tail expression if it doesn't have a return -type specified. This assists is useable in a functions or closures tail expression or return type position. - -#### Before -```rust -fn foo() { 4┃2i32 } -``` - -#### After -```rust -fn foo() -> i32 { 42i32 } -``` - - -### `add_turbo_fish` -**Source:** [add_turbo_fish.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_turbo_fish.rs#L14) - -Adds `::<_>` to a call of a generic method or function. - -#### Before -```rust -fn make() -> T { todo!() } -fn main() { - let x = make┃(); -} -``` - -#### After -```rust -fn make() -> T { todo!() } -fn main() { - let x = make::<${0:_}>(); -} -``` - - -### `apply_demorgan` -**Source:** [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L23) - -Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). -This transforms expressions of the form `!l || !r` into `!(l && r)`. -This also works with `&&`. This assist can only be applied with the cursor -on either `||` or `&&`. - -#### Before -```rust -fn main() { - if x != 4 ||┃ y < 3.14 {} -} -``` - -#### After -```rust -fn main() { - if !(x == 4 && y >= 3.14) {} -} -``` - - -### `apply_demorgan_iterator` -**Source:** [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L156) - -Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) to -`Iterator::all` and `Iterator::any`. - -This transforms expressions of the form `!iter.any(|x| predicate(x))` into -`iter.all(|x| !predicate(x))` and vice versa. This also works the other way for -`Iterator::all` into `Iterator::any`. - -#### Before -```rust -fn main() { - let arr = [1, 2, 3]; - if !arr.into_iter().┃any(|num| num == 4) { - println!("foo"); - } -} -``` - -#### After -```rust -fn main() { - let arr = [1, 2, 3]; - if arr.into_iter().all(|num| num != 4) { - println!("foo"); - } -} -``` - - -### `auto_import` -**Source:** [auto_import.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/auto_import.rs#L73) - -If the name is unresolved, provides all possible imports for it. - -#### Before -```rust -fn main() { - let map = HashMap┃::new(); -} -``` - -#### After -```rust -use std::collections::HashMap; - -fn main() { - let map = HashMap::new(); -} -``` - - -### `bind_unused_param` -**Source:** [bind_unused_param.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/bind_unused_param.rs#L12) - -Binds unused function parameter to an underscore. - -#### Before -```rust -fn some_function(x: i32┃) {} -``` - -#### After -```rust -fn some_function(x: i32) { - let _ = x; -} -``` - - -### `change_visibility` -**Source:** [change_visibility.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/change_visibility.rs#L13) - -Adds or changes existing visibility specifier. - -#### Before -```rust -┃fn frobnicate() {} -``` - -#### After -```rust -pub(crate) fn frobnicate() {} -``` - - -### `comment_to_doc` -**Source:** [convert_comment_from_or_to_doc.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs#L9) - -Converts comments to documentation. - -#### Before -```rust -// Wow what ┃a nice module -// I sure hope this shows up when I hover over it -``` - -#### After -```rust -//! Wow what a nice module -//! I sure hope this shows up when I hover over it -``` - - -### `convert_bool_then_to_if` -**Source:** [convert_bool_then.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_bool_then.rs#L143) - -Converts a `bool::then` method call to an equivalent if expression. - -#### Before -```rust -fn main() { - (0 == 0).then┃(|| val) -} -``` - -#### After -```rust -fn main() { - if 0 == 0 { - Some(val) - } else { - None - } -} -``` - - -### `convert_bool_to_enum` -**Source:** [convert_bool_to_enum.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_bool_to_enum.rs#L29) - -This converts boolean local variables, fields, constants, and statics into a new -enum with two variants `Bool::True` and `Bool::False`, as well as replacing -all assignments with the variants and replacing all usages with `== Bool::True` or -`== Bool::False`. - -#### Before -```rust -fn main() { - let ┃bool = true; - - if bool { - println!("foo"); - } -} -``` - -#### After -```rust -#[derive(PartialEq, Eq)] -enum Bool { True, False } - -fn main() { - let bool = Bool::True; - - if bool == Bool::True { - println!("foo"); - } -} -``` - - -### `convert_closure_to_fn` -**Source:** [convert_closure_to_fn.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_closure_to_fn.rs#L25) - -This converts a closure to a freestanding function, changing all captures to parameters. - -#### Before -```rust -fn main() { - let mut s = String::new(); - let closure = |┃a| s.push_str(a); - closure("abc"); -} -``` - -#### After -```rust -fn main() { - let mut s = String::new(); - fn closure(a: &str, s: &mut String) { - s.push_str(a) - } - closure("abc", &mut s); -} -``` - - -### `convert_for_loop_with_for_each` -**Source:** [convert_iter_for_each_to_for.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs#L76) - -Converts a for loop into a for_each loop on the Iterator. - -#### Before -```rust -fn main() { - let x = vec![1, 2, 3]; - for┃ v in x { - let y = v * 2; - } -} -``` - -#### After -```rust -fn main() { - let x = vec![1, 2, 3]; - x.into_iter().for_each(|v| { - let y = v * 2; - }); -} -``` - - -### `convert_from_to_tryfrom` -**Source:** [convert_from_to_tryfrom.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs#L10) - -Converts a From impl to a TryFrom impl, wrapping returns in `Ok`. - -#### Before -```rust -impl ┃From for Thing { - fn from(val: usize) -> Self { - Thing { - b: val.to_string(), - a: val - } - } -} -``` - -#### After -```rust -impl TryFrom for Thing { - type Error = ${0:()}; - - fn try_from(val: usize) -> Result { - Ok(Thing { - b: val.to_string(), - a: val - }) - } -} -``` - - -### `convert_if_to_bool_then` -**Source:** [convert_bool_then.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_bool_then.rs#L21) - -Converts an if expression into a corresponding `bool::then` call. - -#### Before -```rust -fn main() { - if┃ cond { - Some(val) - } else { - None - } -} -``` - -#### After -```rust -fn main() { - cond.then(|| val) -} -``` - - -### `convert_integer_literal` -**Source:** [convert_integer_literal.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_integer_literal.rs#L5) - -Converts the base of integer literals to other bases. - -#### Before -```rust -const _: i32 = 10┃; -``` - -#### After -```rust -const _: i32 = 0b1010; -``` - - -### `convert_into_to_from` -**Source:** [convert_into_to_from.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_into_to_from.rs#L8) - -Converts an Into impl to an equivalent From impl. - -#### Before -```rust -impl ┃Into for usize { - fn into(self) -> Thing { - Thing { - b: self.to_string(), - a: self - } - } -} -``` - -#### After -```rust -impl From for Thing { - fn from(val: usize) -> Self { - Thing { - b: val.to_string(), - a: val - } - } -} -``` - - -### `convert_iter_for_each_to_for` -**Source:** [convert_iter_for_each_to_for.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs#L11) - -Converts an Iterator::for_each function into a for loop. - -#### Before -```rust -fn main() { - let iter = iter::repeat((9, 2)); - iter.for_each┃(|(x, y)| { - println!("x: {}, y: {}", x, y); - }); -} -``` - -#### After -```rust -fn main() { - let iter = iter::repeat((9, 2)); - for (x, y) in iter { - println!("x: {}, y: {}", x, y); - } -} -``` - - -### `convert_let_else_to_match` -**Source:** [convert_let_else_to_match.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_let_else_to_match.rs#L9) - -Converts let-else statement to let statement and match expression. - -#### Before -```rust -fn main() { - let Ok(mut x) = f() else┃ { return }; -} -``` - -#### After -```rust -fn main() { - let mut x = match f() { - Ok(x) => x, - _ => return, - }; -} -``` - - -### `convert_match_to_let_else` -**Source:** [convert_match_to_let_else.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_match_to_let_else.rs#L12) - -Converts let statement with match initializer to let-else statement. - -#### Before -```rust -fn foo(opt: Option<()>) { - let val┃ = match opt { - Some(it) => it, - None => return, - }; -} -``` - -#### After -```rust -fn foo(opt: Option<()>) { - let Some(val) = opt else { return }; -} -``` - - -### `convert_named_struct_to_tuple_struct` -**Source:** [convert_named_struct_to_tuple_struct.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs#L11) - -Converts struct with named fields to tuple struct, and analogously for enum variants with named -fields. - -#### Before -```rust -struct Point┃ { x: f32, y: f32 } - -impl Point { - pub fn new(x: f32, y: f32) -> Self { - Point { x, y } - } - - pub fn x(&self) -> f32 { - self.x - } - - pub fn y(&self) -> f32 { - self.y - } -} -``` - -#### After -```rust -struct Point(f32, f32); - -impl Point { - pub fn new(x: f32, y: f32) -> Self { - Point(x, y) - } - - pub fn x(&self) -> f32 { - self.0 - } - - pub fn y(&self) -> f32 { - self.1 - } -} -``` - - -### `convert_nested_function_to_closure` -**Source:** [convert_nested_function_to_closure.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs#L7) - -Converts a function that is defined within the body of another function into a closure. - -#### Before -```rust -fn main() { - fn fo┃o(label: &str, number: u64) { - println!("{}: {}", label, number); - } - - foo("Bar", 100); -} -``` - -#### After -```rust -fn main() { - let foo = |label: &str, number: u64| { - println!("{}: {}", label, number); - }; - - foo("Bar", 100); -} -``` - - -### `convert_to_guarded_return` -**Source:** [convert_to_guarded_return.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_to_guarded_return.rs#L24) - -Replace a large conditional with a guarded return. - -#### Before -```rust -fn main() { - ┃if cond { - foo(); - bar(); - } -} -``` - -#### After -```rust -fn main() { - if !cond { - return; - } - foo(); - bar(); -} -``` - - -### `convert_tuple_return_type_to_struct` -**Source:** [convert_tuple_return_type_to_struct.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs#L20) - -This converts the return type of a function from a tuple type -into a tuple struct and updates the body accordingly. - -#### Before -```rust -fn bar() { - let (a, b, c) = foo(); -} - -fn foo() -> (┃u32, u32, u32) { - (1, 2, 3) -} -``` - -#### After -```rust -fn bar() { - let FooResult(a, b, c) = foo(); -} - -struct FooResult(u32, u32, u32); - -fn foo() -> FooResult { - FooResult(1, 2, 3) -} -``` - - -### `convert_tuple_struct_to_named_struct` -**Source:** [convert_tuple_struct_to_named_struct.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs#L10) - -Converts tuple struct to struct with named fields, and analogously for tuple enum variants. - -#### Before -```rust -struct Point┃(f32, f32); - -impl Point { - pub fn new(x: f32, y: f32) -> Self { - Point(x, y) - } - - pub fn x(&self) -> f32 { - self.0 - } - - pub fn y(&self) -> f32 { - self.1 - } -} -``` - -#### After -```rust -struct Point { field1: f32, field2: f32 } - -impl Point { - pub fn new(x: f32, y: f32) -> Self { - Point { field1: x, field2: y } - } - - pub fn x(&self) -> f32 { - self.field1 - } - - pub fn y(&self) -> f32 { - self.field2 - } -} -``` - - -### `convert_two_arm_bool_match_to_matches_macro` -**Source:** [convert_two_arm_bool_match_to_matches_macro.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs#L8) - -Convert 2-arm match that evaluates to a boolean into the equivalent matches! invocation. - -#### Before -```rust -fn main() { - match scrutinee┃ { - Some(val) if val.cond() => true, - _ => false, - } -} -``` - -#### After -```rust -fn main() { - matches!(scrutinee, Some(val) if val.cond()) -} -``` - - -### `convert_while_to_loop` -**Source:** [convert_while_to_loop.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_while_to_loop.rs#L20) - -Replace a while with a loop. - -#### Before -```rust -fn main() { - ┃while cond { - foo(); - } -} -``` - -#### After -```rust -fn main() { - loop { - if !cond { - break; - } - foo(); - } -} -``` - - -### `destructure_struct_binding` -**Source:** [destructure_struct_binding.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/destructure_struct_binding.rs#L18) - -Destructures a struct binding in place. - -#### Before -```rust -struct Foo { - bar: i32, - baz: i32, -} -fn main() { - let ┃foo = Foo { bar: 1, baz: 2 }; - let bar2 = foo.bar; - let baz2 = &foo.baz; -} -``` - -#### After -```rust -struct Foo { - bar: i32, - baz: i32, -} -fn main() { - let Foo { bar, baz } = Foo { bar: 1, baz: 2 }; - let bar2 = bar; - let baz2 = &baz; -} -``` - - -### `destructure_tuple_binding` -**Source:** [destructure_tuple_binding.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/destructure_tuple_binding.rs#L19) - -Destructures a tuple binding in place. - -#### Before -```rust -fn main() { - let ┃t = (1,2); - let v = t.0; -} -``` - -#### After -```rust -fn main() { - let (┃_0, _1) = (1,2); - let v = _0; -} -``` - - -### `desugar_async_into_impl_future` -**Source:** [toggle_async_sugar.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/toggle_async_sugar.rs#L103) - -Rewrites asynchronous function from `async fn` into `-> impl Future`. -This action does not touch the function body and therefore `0` -block does not transform to `async { 0 }`. - -#### Before -```rust -pub as┃ync fn foo() -> usize { - 0 -} -``` - -#### After -```rust -pub fn foo() -> impl core::future::Future { - 0 -} -``` - - -### `desugar_doc_comment` -**Source:** [desugar_doc_comment.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/desugar_doc_comment.rs#L14) - -Desugars doc-comments to the attribute form. - -#### Before -```rust -/// Multi-line┃ -/// comment -``` - -#### After -```rust -#[doc = r"Multi-line -comment"] -``` - - -### `expand_glob_import` -**Source:** [expand_glob_import.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_glob_import.rs#L19) - -Expands glob imports. - -#### Before -```rust -mod foo { - pub struct Bar; - pub struct Baz; -} - -use foo::*┃; - -fn qux(bar: Bar, baz: Baz) {} -``` - -#### After -```rust -mod foo { - pub struct Bar; - pub struct Baz; -} - -use foo::{Bar, Baz}; - -fn qux(bar: Bar, baz: Baz) {} -``` - - -### `expand_glob_reexport` -**Source:** [expand_glob_import.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_glob_import.rs#L81) - -Expands non-private glob imports. - -#### Before -```rust -mod foo { - pub struct Bar; - pub struct Baz; -} - -pub use foo::*┃; -``` - -#### After -```rust -mod foo { - pub struct Bar; - pub struct Baz; -} - -pub use foo::{Bar, Baz}; -``` - - -### `expand_record_rest_pattern` -**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L26) - -Fills fields by replacing rest pattern in record patterns. - -#### Before -```rust -struct Bar { y: Y, z: Z } - -fn foo(bar: Bar) { - let Bar { ..┃ } = bar; -} -``` - -#### After -```rust -struct Bar { y: Y, z: Z } - -fn foo(bar: Bar) { - let Bar { y, z } = bar; -} -``` - - -### `expand_tuple_struct_rest_pattern` -**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L82) - -Fills fields by replacing rest pattern in tuple struct patterns. - -#### Before -```rust -struct Bar(Y, Z); - -fn foo(bar: Bar) { - let Bar(..┃) = bar; -} -``` - -#### After -```rust -struct Bar(Y, Z); - -fn foo(bar: Bar) { - let Bar(_0, _1) = bar; -} -``` - - -### `extract_constant` -**Source:** [extract_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_variable.rs#L35) - -Extracts subexpression into a constant. - -#### Before -```rust -fn main() { - ┃(1 + 2)┃ * 4; -} -``` - -#### After -```rust -fn main() { - const ┃VAR_NAME: i32 = 1 + 2; - VAR_NAME * 4; -} -``` - - -### `extract_expressions_from_format_string` -**Source:** [extract_expressions_from_format_string.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs#L14) - -Move an expression out of a format string. - -#### Before -```rust -fn main() { - print!("{var} {x + 1}┃"); -} -``` - -#### After -```rust -fn main() { - print!("{var} {}"┃, x + 1); -} -``` - - -### `extract_function` -**Source:** [extract_function.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_function.rs#L39) - -Extracts selected statements and comments into new function. - -#### Before -```rust -fn main() { - let n = 1; - ┃let m = n + 2; - // calculate - let k = m + n;┃ - let g = 3; -} -``` - -#### After -```rust -fn main() { - let n = 1; - fun_name(n); - let g = 3; -} - -fn ┃fun_name(n: i32) { - let m = n + 2; - // calculate - let k = m + n; -} -``` - - -### `extract_module` -**Source:** [extract_module.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_module.rs#L29) - -Extracts a selected region as separate module. All the references, visibility and imports are -resolved. - -#### Before -```rust -┃fn foo(name: i32) -> i32 { - name + 1 -}┃ - -fn bar(name: i32) -> i32 { - name + 2 -} -``` - -#### After -```rust -mod modname { - pub(crate) fn foo(name: i32) -> i32 { - name + 1 - } -} - -fn bar(name: i32) -> i32 { - name + 2 -} -``` - - -### `extract_static` -**Source:** [extract_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_variable.rs#L52) - -Extracts subexpression into a static. - -#### Before -```rust -fn main() { - ┃(1 + 2)┃ * 4; -} -``` - -#### After -```rust -fn main() { - static ┃VAR_NAME: i32 = 1 + 2; - VAR_NAME * 4; -} -``` - - -### `extract_struct_from_enum_variant` -**Source:** [extract_struct_from_enum_variant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs#L26) - -Extracts a struct from enum variant. - -#### Before -```rust -enum A { ┃One(u32, u32) } -``` - -#### After -```rust -struct One(u32, u32); - -enum A { One(One) } -``` - - -### `extract_type_alias` -**Source:** [extract_type_alias.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_type_alias.rs#L10) - -Extracts the selected type as a type alias. - -#### Before -```rust -struct S { - field: ┃(u8, u8, u8)┃, -} -``` - -#### After -```rust -type ┃Type = (u8, u8, u8); - -struct S { - field: Type, -} -``` - - -### `extract_variable` -**Source:** [extract_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_variable.rs#L18) - -Extracts subexpression into a variable. - -#### Before -```rust -fn main() { - ┃(1 + 2)┃ * 4; -} -``` - -#### After -```rust -fn main() { - let ┃var_name = 1 + 2; - var_name * 4; -} -``` - - -### `fix_visibility` -**Source:** [fix_visibility.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/fix_visibility.rs#L14) - -Makes inaccessible item public. - -#### Before -```rust -mod m { - fn frobnicate() {} -} -fn main() { - m::frobnicate┃(); -} -``` - -#### After -```rust -mod m { - ┃pub(crate) fn frobnicate() {} -} -fn main() { - m::frobnicate(); -} -``` - - -### `flip_binexpr` -**Source:** [flip_binexpr.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/flip_binexpr.rs#L8) - -Flips operands of a binary expression. - -#### Before -```rust -fn main() { - let _ = 90 +┃ 2; -} -``` - -#### After -```rust -fn main() { - let _ = 2 + 90; -} -``` - - -### `flip_comma` -**Source:** [flip_comma.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/flip_comma.rs#L10) - -Flips two comma-separated items. - -#### Before -```rust -fn main() { - ((1, 2),┃ (3, 4)); -} -``` - -#### After -```rust -fn main() { - ((3, 4), (1, 2)); -} -``` - - -### `flip_or_pattern` -**Source:** [flip_or_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/flip_or_pattern.rs#L9) - -Flips two patterns in an or-pattern. - -#### Before -```rust -fn foo() { - let (a |┃ b) = 1; -} -``` - -#### After -```rust -fn foo() { - let (b | a) = 1; -} -``` - - -### `flip_trait_bound` -**Source:** [flip_trait_bound.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/flip_trait_bound.rs#L9) - -Flips two trait bounds. - -#### Before -```rust -fn foo() { } -``` - -#### After -```rust -fn foo() { } -``` - - -### `generate_constant` -**Source:** [generate_constant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_constant.rs#L14) - -Generate a named constant. - -#### Before -```rust -struct S { i: usize } -impl S { pub fn new(n: usize) {} } -fn main() { - let v = S::new(CAPA┃CITY); -} -``` - -#### After -```rust -struct S { i: usize } -impl S { pub fn new(n: usize) {} } -fn main() { - const CAPACITY: usize = ┃; - let v = S::new(CAPACITY); -} -``` - - -### `generate_default_from_enum_variant` -**Source:** [generate_default_from_enum_variant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs#L6) - -Adds a Default impl for an enum using a variant. - -#### Before -```rust -enum Version { - Undefined, - Minor┃, - Major, -} -``` - -#### After -```rust -enum Version { - Undefined, - Minor, - Major, -} - -impl Default for Version { - fn default() -> Self { - Self::Minor - } -} -``` - - -### `generate_default_from_new` -**Source:** [generate_default_from_new.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_default_from_new.rs#L13) - -Generates default implementation from new method. - -#### Before -```rust -struct Example { _inner: () } - -impl Example { - pub fn n┃ew() -> Self { - Self { _inner: () } - } -} -``` - -#### After -```rust -struct Example { _inner: () } - -impl Example { - pub fn new() -> Self { - Self { _inner: () } - } -} - -impl Default for Example { - fn default() -> Self { - Self::new() - } -} -``` - - -### `generate_delegate_methods` -**Source:** [generate_delegate_methods.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_delegate_methods.rs#L15) - -Generate delegate methods. - -#### Before -```rust -struct Age(u8); -impl Age { - fn age(&self) -> u8 { - self.0 - } -} - -struct Person { - ag┃e: Age, -} -``` - -#### After -```rust -struct Age(u8); -impl Age { - fn age(&self) -> u8 { - self.0 - } -} - -struct Person { - age: Age, -} - -impl Person { - ┃fn age(&self) -> u8 { - self.age.age() - } -} -``` - - -### `generate_delegate_trait` -**Source:** [generate_delegate_trait.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_delegate_trait.rs#L29) - -Generate delegate trait implementation for `StructField`s. - -#### Before -```rust -trait SomeTrait { - type T; - fn fn_(arg: u32) -> u32; - fn method_(&mut self) -> bool; -} -struct A; -impl SomeTrait for A { - type T = u32; - - fn fn_(arg: u32) -> u32 { - 42 - } - - fn method_(&mut self) -> bool { - false - } -} -struct B { - a┃: A, -} -``` - -#### After -```rust -trait SomeTrait { - type T; - fn fn_(arg: u32) -> u32; - fn method_(&mut self) -> bool; -} -struct A; -impl SomeTrait for A { - type T = u32; - - fn fn_(arg: u32) -> u32 { - 42 - } - - fn method_(&mut self) -> bool { - false - } -} -struct B { - a: A, -} - -impl SomeTrait for B { - type T = ::T; - - fn fn_(arg: u32) -> u32 { - ::fn_(arg) - } - - fn method_(&mut self) -> bool { - ::method_(&mut self.a) - } -} -``` - - -### `generate_deref` -**Source:** [generate_deref.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_deref.rs#L16) - -Generate `Deref` impl using the given struct field. - -#### Before -```rust -struct A; -struct B { - ┃a: A -} -``` - -#### After -```rust -struct A; -struct B { - a: A -} - -impl core::ops::Deref for B { - type Target = A; - - fn deref(&self) -> &Self::Target { - &self.a - } -} -``` - - -### `generate_derive` -**Source:** [generate_derive.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_derive.rs#L8) - -Adds a new `#[derive()]` clause to a struct or enum. - -#### Before -```rust -struct Point { - x: u32, - y: u32,┃ -} -``` - -#### After -```rust -#[derive(┃)] -struct Point { - x: u32, - y: u32, -} -``` - - -### `generate_doc_example` -**Source:** [generate_documentation_template.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_documentation_template.rs#L76) - -Generates a rustdoc example when editing an item's documentation. - -#### Before -```rust -/// Adds two numbers.┃ -pub fn add(a: i32, b: i32) -> i32 { a + b } -``` - -#### After -```rust -/// Adds two numbers. -/// -/// # Examples -/// -/// ``` -/// use ra_test_fixture::add; -/// -/// assert_eq!(add(a, b), ); -/// ``` -pub fn add(a: i32, b: i32) -> i32 { a + b } -``` - - -### `generate_documentation_template` -**Source:** [generate_documentation_template.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_documentation_template.rs#L13) - -Adds a documentation template above a function definition / declaration. - -#### Before -```rust -pub struct S; -impl S { - pub unsafe fn set_len┃(&mut self, len: usize) -> Result<(), std::io::Error> { - /* ... */ - } -} -``` - -#### After -```rust -pub struct S; -impl S { - /// Sets the length of this [`S`]. - /// - /// # Errors - /// - /// This function will return an error if . - /// - /// # Safety - /// - /// . - pub unsafe fn set_len(&mut self, len: usize) -> Result<(), std::io::Error> { - /* ... */ - } -} -``` - - -### `generate_enum_as_method` -**Source:** [generate_enum_projection_method.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_enum_projection_method.rs#L59) - -Generate an `as_` method for this enum variant. - -#### Before -```rust -enum Value { - Number(i32), - Text(String)┃, -} -``` - -#### After -```rust -enum Value { - Number(i32), - Text(String), -} - -impl Value { - fn as_text(&self) -> Option<&String> { - if let Self::Text(v) = self { - Some(v) - } else { - None - } - } -} -``` - - -### `generate_enum_is_method` -**Source:** [generate_enum_is_method.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_enum_is_method.rs#L11) - -Generate an `is_` method for this enum variant. - -#### Before -```rust -enum Version { - Undefined, - Minor┃, - Major, -} -``` - -#### After -```rust -enum Version { - Undefined, - Minor, - Major, -} - -impl Version { - /// Returns `true` if the version is [`Minor`]. - /// - /// [`Minor`]: Version::Minor - #[must_use] - fn is_minor(&self) -> bool { - matches!(self, Self::Minor) - } -} -``` - - -### `generate_enum_try_into_method` -**Source:** [generate_enum_projection_method.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_enum_projection_method.rs#L12) - -Generate a `try_into_` method for this enum variant. - -#### Before -```rust -enum Value { - Number(i32), - Text(String)┃, -} -``` - -#### After -```rust -enum Value { - Number(i32), - Text(String), -} - -impl Value { - fn try_into_text(self) -> Result { - if let Self::Text(v) = self { - Ok(v) - } else { - Err(self) - } - } -} -``` - - -### `generate_enum_variant` -**Source:** [generate_enum_variant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_enum_variant.rs#L10) - -Adds a variant to an enum. - -#### Before -```rust -enum Countries { - Ghana, -} - -fn main() { - let country = Countries::Lesotho┃; -} -``` - -#### After -```rust -enum Countries { - Ghana, - Lesotho, -} - -fn main() { - let country = Countries::Lesotho; -} -``` - - -### `generate_fn_type_alias_named` -**Source:** [generate_fn_type_alias.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_fn_type_alias.rs#L10) - -Generate a type alias for the function with named parameters. - -#### Before -```rust -unsafe fn fo┃o(n: i32) -> i32 { 42i32 } -``` - -#### After -```rust -type ${0:FooFn} = unsafe fn(n: i32) -> i32; - -unsafe fn foo(n: i32) -> i32 { 42i32 } -``` - - -### `generate_fn_type_alias_unnamed` -**Source:** [generate_fn_type_alias.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_fn_type_alias.rs#L24) - -Generate a type alias for the function with unnamed parameters. - -#### Before -```rust -unsafe fn fo┃o(n: i32) -> i32 { 42i32 } -``` - -#### After -```rust -type ${0:FooFn} = unsafe fn(i32) -> i32; - -unsafe fn foo(n: i32) -> i32 { 42i32 } -``` - - -### `generate_from_impl_for_enum` -**Source:** [generate_from_impl_for_enum.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs#L8) - -Adds a From impl for this enum variant with one tuple field. - -#### Before -```rust -enum A { ┃One(u32) } -``` - -#### After -```rust -enum A { One(u32) } - -impl From for A { - fn from(v: u32) -> Self { - Self::One(v) - } -} -``` - - -### `generate_function` -**Source:** [generate_function.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_function.rs#L28) - -Adds a stub function with a signature matching the function under the cursor. - -#### Before -```rust -struct Baz; -fn baz() -> Baz { Baz } -fn foo() { - bar┃("", baz()); -} - -``` - -#### After -```rust -struct Baz; -fn baz() -> Baz { Baz } -fn foo() { - bar("", baz()); -} - -fn bar(arg: &str, baz: Baz) ${0:-> _} { - todo!() -} - -``` - - -### `generate_getter` -**Source:** [generate_getter_or_setter.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_getter_or_setter.rs#L73) - -Generate a getter method. - -#### Before -```rust -struct Person { - nam┃e: String, -} -``` - -#### After -```rust -struct Person { - name: String, -} - -impl Person { - fn ┃name(&self) -> &str { - &self.name - } -} -``` - - -### `generate_getter_mut` -**Source:** [generate_getter_or_setter.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_getter_or_setter.rs#L127) - -Generate a mut getter method. - -#### Before -```rust -struct Person { - nam┃e: String, -} -``` - -#### After -```rust -struct Person { - name: String, -} - -impl Person { - fn ┃name_mut(&mut self) -> &mut String { - &mut self.name - } -} -``` - - -### `generate_impl` -**Source:** [generate_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_impl.rs#L20) - -Adds a new inherent impl for a type. - -#### Before -```rust -struct Ctx┃ { - data: T, -} -``` - -#### After -```rust -struct Ctx { - data: T, -} - -impl Ctx {┃} -``` - - -### `generate_is_empty_from_len` -**Source:** [generate_is_empty_from_len.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs#L12) - -Generates is_empty implementation from the len method. - -#### Before -```rust -struct MyStruct { data: Vec } - -impl MyStruct { - #[must_use] - p┃ub fn len(&self) -> usize { - self.data.len() - } -} -``` - -#### After -```rust -struct MyStruct { data: Vec } - -impl MyStruct { - #[must_use] - pub fn len(&self) -> usize { - self.data.len() - } - - #[must_use] - pub fn is_empty(&self) -> bool { - self.len() == 0 - } -} -``` - - -### `generate_mut_trait_impl` -**Source:** [generate_mut_trait_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs#L12) - -Adds a IndexMut impl from the `Index` trait. - -#### Before -```rust -pub enum Axis { X = 0, Y = 1, Z = 2 } - -impl core::ops::Index┃ for [T; 3] { - type Output = T; - - fn index(&self, index: Axis) -> &Self::Output { - &self[index as usize] - } -} -``` - -#### After -```rust -pub enum Axis { X = 0, Y = 1, Z = 2 } - -┃impl core::ops::IndexMut for [T; 3] { - fn index_mut(&mut self, index: Axis) -> &mut Self::Output { - &self[index as usize] - } -} - -impl core::ops::Index for [T; 3] { - type Output = T; - - fn index(&self, index: Axis) -> &Self::Output { - &self[index as usize] - } -} -``` - - -### `generate_new` -**Source:** [generate_new.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_new.rs#L14) - -Adds a `fn new` for a type. - -#### Before -```rust -struct Ctx { - data: T,┃ -} -``` - -#### After -```rust -struct Ctx { - data: T, -} - -impl Ctx { - fn ┃new(data: T) -> Self { - Self { data } - } -} -``` - - -### `generate_setter` -**Source:** [generate_getter_or_setter.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_getter_or_setter.rs#L13) - -Generate a setter method. - -#### Before -```rust -struct Person { - nam┃e: String, -} -``` - -#### After -```rust -struct Person { - name: String, -} - -impl Person { - fn ┃set_name(&mut self, name: String) { - self.name = name; - } -} -``` - - -### `generate_trait_from_impl` -**Source:** [generate_trait_from_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_trait_from_impl.rs#L18) - -Generate trait for an already defined inherent impl and convert impl to a trait impl. - -#### Before -```rust -struct Foo([i32; N]); - -macro_rules! const_maker { - ($t:ty, $v:tt) => { - const CONST: $t = $v; - }; -} - -impl Fo┃o { - // Used as an associated constant. - const CONST_ASSOC: usize = N * 4; - - fn create() -> Option<()> { - Some(()) - } - - const_maker! {i32, 7} -} -``` - -#### After -```rust -struct Foo([i32; N]); - -macro_rules! const_maker { - ($t:ty, $v:tt) => { - const CONST: $t = $v; - }; -} - -trait ${0:NewTrait} { - // Used as an associated constant. - const CONST_ASSOC: usize = N * 4; - - fn create() -> Option<()>; - - const_maker! {i32, 7} -} - -impl ${0:NewTrait} for Foo { - // Used as an associated constant. - const CONST_ASSOC: usize = N * 4; - - fn create() -> Option<()> { - Some(()) - } - - const_maker! {i32, 7} -} -``` - - -### `generate_trait_impl` -**Source:** [generate_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_impl.rs#L66) - -Adds a new trait impl for a type. - -#### Before -```rust -struct ┃Ctx { - data: T, -} -``` - -#### After -```rust -struct Ctx { - data: T, -} - -impl ${1:_} for Ctx {┃} -``` - - -### `inline_call` -**Source:** [inline_call.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_call.rs#L170) - -Inlines a function or method body creating a `let` statement per parameter unless the parameter -can be inlined. The parameter will be inlined either if it the supplied argument is a simple local -or if the parameter is only accessed inside the function body once. - -#### Before -```rust -fn foo(name: Option<&str>) { - let name = name.unwrap┃(); -} -``` - -#### After -```rust -fn foo(name: Option<&str>) { - let name = match name { - Some(val) => val, - None => panic!("called `Option::unwrap()` on a `None` value"), - }; -} -``` - - -### `inline_const_as_literal` -**Source:** [inline_const_as_literal.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_const_as_literal.rs#L6) - -Evaluate and inline const variable as literal. - -#### Before -```rust -const STRING: &str = "Hello, World!"; - -fn something() -> &'static str { - STRING┃ -} -``` - -#### After -```rust -const STRING: &str = "Hello, World!"; - -fn something() -> &'static str { - "Hello, World!" -} -``` - - -### `inline_into_callers` -**Source:** [inline_call.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_call.rs#L32) - -Inline a function or method body into all of its callers where possible, creating a `let` statement per parameter -unless the parameter can be inlined. The parameter will be inlined either if it the supplied argument is a simple local -or if the parameter is only accessed inside the function body once. -If all calls can be inlined the function will be removed. - -#### Before -```rust -fn print(_: &str) {} -fn foo┃(word: &str) { - if !word.is_empty() { - print(word); - } -} -fn bar() { - foo("안녕하세요"); - foo("여러분"); -} -``` - -#### After -```rust -fn print(_: &str) {} - -fn bar() { - { - let word: &str = "안녕하세요"; - if !word.is_empty() { - print(word); - } - }; - { - let word: &str = "여러분"; - if !word.is_empty() { - print(word); - } - }; -} -``` - - -### `inline_local_variable` -**Source:** [inline_local_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_local_variable.rs#L17) - -Inlines a local variable. - -#### Before -```rust -fn main() { - let x┃ = 1 + 2; - x * 4; -} -``` - -#### After -```rust -fn main() { - (1 + 2) * 4; -} -``` - - -### `inline_macro` -**Source:** [inline_macro.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_macro.rs#L7) - -Takes a macro and inlines it one step. - -#### Before -```rust -macro_rules! num { - (+$($t:tt)+) => (1 + num!($($t )+)); - (-$($t:tt)+) => (-1 + num!($($t )+)); - (+) => (1); - (-) => (-1); -} - -fn main() { - let number = num┃!(+ + + - + +); - println!("{number}"); -} -``` - -#### After -```rust -macro_rules! num { - (+$($t:tt)+) => (1 + num!($($t )+)); - (-$($t:tt)+) => (-1 + num!($($t )+)); - (+) => (1); - (-) => (-1); -} - -fn main() { - let number = 1+num!(+ + - + +); - println!("{number}"); -} -``` - - -### `inline_type_alias` -**Source:** [inline_type_alias.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_type_alias.rs#L106) - -Replace a type alias with its concrete type. - -#### Before -```rust -type A = Vec; - -fn main() { - let a: ┃A; -} -``` - -#### After -```rust -type A = Vec; - -fn main() { - let a: Vec; -} -``` - - -### `inline_type_alias_uses` -**Source:** [inline_type_alias.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_type_alias.rs#L24) - -Inline a type alias into all of its uses where possible. - -#### Before -```rust -type ┃A = i32; -fn id(x: A) -> A { - x -}; -fn foo() { - let _: A = 3; -} -``` - -#### After -```rust - -fn id(x: i32) -> i32 { - x -}; -fn foo() { - let _: i32 = 3; -} -``` - - -### `into_to_qualified_from` -**Source:** [into_to_qualified_from.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/into_to_qualified_from.rs#L10) - -Convert an `into` method call to a fully qualified `from` call. - -#### Before -```rust -//- minicore: from -struct B; -impl From for B { - fn from(a: i32) -> Self { - B - } -} - -fn main() -> () { - let a = 3; - let b: B = a.in┃to(); -} -``` - -#### After -```rust -struct B; -impl From for B { - fn from(a: i32) -> Self { - B - } -} - -fn main() -> () { - let a = 3; - let b: B = B::from(a); -} -``` - - -### `introduce_named_lifetime` -**Source:** [introduce_named_lifetime.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/introduce_named_lifetime.rs#L13) - -Change an anonymous lifetime to a named lifetime. - -#### Before -```rust -impl Cursor<'_┃> { - fn node(self) -> &SyntaxNode { - match self { - Cursor::Replace(node) | Cursor::Before(node) => node, - } - } -} -``` - -#### After -```rust -impl<'a> Cursor<'a> { - fn node(self) -> &SyntaxNode { - match self { - Cursor::Replace(node) | Cursor::Before(node) => node, - } - } -} -``` - - -### `introduce_named_type_parameter` -**Source:** [introduce_named_type_parameter.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs#L7) - -Replaces `impl Trait` function argument with the named generic. - -#### Before -```rust -fn foo(bar: ┃impl Bar) {} -``` - -#### After -```rust -fn foo<┃B: Bar>(bar: B) {} -``` - - -### `invert_if` -**Source:** [invert_if.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/invert_if.rs#L13) - -This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}` -This also works with `!=`. This assist can only be applied with the cursor on `if`. - -#### Before -```rust -fn main() { - if┃ !y { A } else { B } -} -``` - -#### After -```rust -fn main() { - if y { B } else { A } -} -``` - - -### `line_to_block` -**Source:** [convert_comment_block.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_comment_block.rs#L9) - -Converts comments between block and single-line form. - -#### Before -```rust - // Multi-line┃ - // comment -``` - -#### After -```rust - /* - Multi-line - comment - */ -``` - - -### `make_raw_string` -**Source:** [raw_string.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/raw_string.rs#L7) - -Adds `r#` to a plain string literal. - -#### Before -```rust -fn main() { - "Hello,┃ World!"; -} -``` - -#### After -```rust -fn main() { - r#"Hello, World!"#; -} -``` - - -### `make_usual_string` -**Source:** [raw_string.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/raw_string.rs#L47) - -Turns a raw string into a plain string. - -#### Before -```rust -fn main() { - r#"Hello,┃ "World!""#; -} -``` - -#### After -```rust -fn main() { - "Hello, \"World!\""; -} -``` - - -### `merge_imports` -**Source:** [merge_imports.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/merge_imports.rs#L21) - -Merges neighbor imports with a common prefix. - -#### Before -```rust -use std::┃fmt::Formatter; -use std::io; -``` - -#### After -```rust -use std::{fmt::Formatter, io}; -``` - - -### `merge_match_arms` -**Source:** [merge_match_arms.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/merge_match_arms.rs#L12) - -Merges the current match arm with the following if their bodies are identical. - -#### Before -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - match action { - ┃Action::Move(..) => foo(), - Action::Stop => foo(), - } -} -``` - -#### After -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - match action { - Action::Move(..) | Action::Stop => foo(), - } -} -``` - - -### `merge_nested_if` -**Source:** [merge_nested_if.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/merge_nested_if.rs#L11) - -This transforms if expressions of the form `if x { if y {A} }` into `if x && y {A}` -This assist can only be applied with the cursor on `if`. - -#### Before -```rust -fn main() { - i┃f x == 3 { if y == 4 { 1 } } -} -``` - -#### After -```rust -fn main() { - if x == 3 && y == 4 { 1 } -} -``` - - -### `move_arm_cond_to_match_guard` -**Source:** [move_guard.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_guard.rs#L69) - -Moves if expression from match arm body into a guard. - -#### Before -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - match action { - Action::Move { distance } => ┃if distance > 10 { foo() }, - _ => (), - } -} -``` - -#### After -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - match action { - Action::Move { distance } if distance > 10 => foo(), - _ => (), - } -} -``` - - -### `move_bounds_to_where_clause` -**Source:** [move_bounds.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_bounds.rs#L12) - -Moves inline type bounds to a where clause. - -#### Before -```rust -fn apply U>(f: F, x: T) -> U { - f(x) -} -``` - -#### After -```rust -fn apply(f: F, x: T) -> U where F: FnOnce(T) -> U { - f(x) -} -``` - - -### `move_const_to_impl` -**Source:** [move_const_to_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_const_to_impl.rs#L14) - -Move a local constant item in a method to impl's associated constant. All the references will be -qualified with `Self::`. - -#### Before -```rust -struct S; -impl S { - fn foo() -> usize { - /// The answer. - const C┃: usize = 42; - - C * C - } -} -``` - -#### After -```rust -struct S; -impl S { - /// The answer. - const C: usize = 42; - - fn foo() -> usize { - Self::C * Self::C - } -} -``` - - -### `move_from_mod_rs` -**Source:** [move_from_mod_rs.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_from_mod_rs.rs#L12) - -Moves xxx/mod.rs to xxx.rs. - -#### Before -```rust -//- /main.rs -mod a; -//- /a/mod.rs -┃fn t() {}┃ -``` - -#### After -```rust -fn t() {} -``` - - -### `move_guard_to_arm_body` -**Source:** [move_guard.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_guard.rs#L8) - -Moves match guard into match arm body. - -#### Before -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - match action { - Action::Move { distance } ┃if distance > 10 => foo(), - _ => (), - } -} -``` - -#### After -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - match action { - Action::Move { distance } => if distance > 10 { - foo() - }, - _ => (), - } -} -``` - - -### `move_module_to_file` -**Source:** [move_module_to_file.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_module_to_file.rs#L15) - -Moves inline module's contents to a separate file. - -#### Before -```rust -mod ┃foo { - fn t() {} -} -``` - -#### After -```rust -mod foo; -``` - - -### `move_to_mod_rs` -**Source:** [move_to_mod_rs.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_to_mod_rs.rs#L12) - -Moves xxx.rs to xxx/mod.rs. - -#### Before -```rust -//- /main.rs -mod a; -//- /a.rs -┃fn t() {}┃ -``` - -#### After -```rust -fn t() {} -``` - - -### `normalize_import` -**Source:** [normalize_import.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/normalize_import.rs#L9) - -Normalizes an import. - -#### Before -```rust -use┃ std::{io, {fmt::Formatter}}; -``` - -#### After -```rust -use std::{fmt::Formatter, io}; -``` - - -### `promote_local_to_const` -**Source:** [promote_local_to_const.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/promote_local_to_const.rs#L17) - -Promotes a local variable to a const item changing its name to a `SCREAMING_SNAKE_CASE` variant -if the local uses no non-const expressions. - -#### Before -```rust -fn main() { - let foo┃ = true; - - if foo { - println!("It's true"); - } else { - println!("It's false"); - } -} -``` - -#### After -```rust -fn main() { - const ┃FOO: bool = true; - - if FOO { - println!("It's true"); - } else { - println!("It's false"); - } -} -``` - - -### `pull_assignment_up` -**Source:** [pull_assignment_up.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/pull_assignment_up.rs#L11) - -Extracts variable assignment to outside an if or match statement. - -#### Before -```rust -fn main() { - let mut foo = 6; - - if true { - ┃foo = 5; - } else { - foo = 4; - } -} -``` - -#### After -```rust -fn main() { - let mut foo = 6; - - foo = if true { - 5 - } else { - 4 - }; -} -``` - - -### `qualify_method_call` -**Source:** [qualify_method_call.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/qualify_method_call.rs#L10) - -Replaces the method call with a qualified function call. - -#### Before -```rust -struct Foo; -impl Foo { - fn foo(&self) {} -} -fn main() { - let foo = Foo; - foo.fo┃o(); -} -``` - -#### After -```rust -struct Foo; -impl Foo { - fn foo(&self) {} -} -fn main() { - let foo = Foo; - Foo::foo(&foo); -} -``` - - -### `qualify_path` -**Source:** [qualify_path.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/qualify_path.rs#L24) - -If the name is unresolved, provides all possible qualified paths for it. - -#### Before -```rust -fn main() { - let map = HashMap┃::new(); -} -``` - -#### After -```rust -fn main() { - let map = std::collections::HashMap::new(); -} -``` - - -### `reformat_number_literal` -**Source:** [number_representation.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/number_representation.rs#L7) - -Adds or removes separators from integer literal. - -#### Before -```rust -const _: i32 = 1012345┃; -``` - -#### After -```rust -const _: i32 = 1_012_345; -``` - - -### `remove_dbg` -**Source:** [remove_dbg.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_dbg.rs#L9) - -Removes `dbg!()` macro call. - -#### Before -```rust -fn main() { - let x = ┃dbg!(42 * dbg!(4 + 2));┃ -} -``` - -#### After -```rust -fn main() { - let x = 42 * (4 + 2); -} -``` - - -### `remove_hash` -**Source:** [raw_string.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/raw_string.rs#L117) - -Removes a hash from a raw string literal. - -#### Before -```rust -fn main() { - r#"Hello,┃ World!"#; -} -``` - -#### After -```rust -fn main() { - r"Hello, World!"; -} -``` - - -### `remove_mut` -**Source:** [remove_mut.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_mut.rs#L5) - -Removes the `mut` keyword. - -#### Before -```rust -impl Walrus { - fn feed(&mut┃ self, amount: u32) {} -} -``` - -#### After -```rust -impl Walrus { - fn feed(&self, amount: u32) {} -} -``` - - -### `remove_parentheses` -**Source:** [remove_parentheses.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_parentheses.rs#L9) - -Removes redundant parentheses. - -#### Before -```rust -fn main() { - _ = ┃(2) + 2; -} -``` - -#### After -```rust -fn main() { - _ = 2 + 2; -} -``` - - -### `remove_unused_imports` -**Source:** [remove_unused_imports.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_unused_imports.rs#L17) - -Removes any use statements in the current selection that are unused. - -#### Before -```rust -struct X(); -mod foo { - use super::X┃; -} -``` - -#### After -```rust -struct X(); -mod foo { -} -``` - - -### `remove_unused_param` -**Source:** [remove_unused_param.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_unused_param.rs#L16) - -Removes unused function parameter. - -#### Before -```rust -fn frobnicate(x: i32┃) {} - -fn main() { - frobnicate(92); -} -``` - -#### After -```rust -fn frobnicate() {} - -fn main() { - frobnicate(); -} -``` - - -### `reorder_fields` -**Source:** [reorder_fields.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/reorder_fields.rs#L8) - -Reorder the fields of record literals and record patterns in the same order as in -the definition. - -#### Before -```rust -struct Foo {foo: i32, bar: i32}; -const test: Foo = ┃Foo {bar: 0, foo: 1} -``` - -#### After -```rust -struct Foo {foo: i32, bar: i32}; -const test: Foo = Foo {foo: 1, bar: 0} -``` - - -### `reorder_impl_items` -**Source:** [reorder_impl_items.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/reorder_impl_items.rs#L11) - -Reorder the items of an `impl Trait`. The items will be ordered -in the same order as in the trait definition. - -#### Before -```rust -trait Foo { - type A; - const B: u8; - fn c(); -} - -struct Bar; -┃impl Foo for Bar┃ { - const B: u8 = 17; - fn c() {} - type A = String; -} -``` - -#### After -```rust -trait Foo { - type A; - const B: u8; - fn c(); -} - -struct Bar; -impl Foo for Bar { - type A = String; - const B: u8 = 17; - fn c() {} -} -``` - - -### `replace_arith_with_checked` -**Source:** [replace_arith_op.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_arith_op.rs#L9) - -Replaces arithmetic on integers with the `checked_*` equivalent. - -#### Before -```rust -fn main() { - let x = 1 ┃+ 2; -} -``` - -#### After -```rust -fn main() { - let x = 1.checked_add(2); -} -``` - - -### `replace_arith_with_saturating` -**Source:** [replace_arith_op.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_arith_op.rs#L28) - -Replaces arithmetic on integers with the `saturating_*` equivalent. - -#### Before -```rust -fn main() { - let x = 1 ┃+ 2; -} -``` - -#### After -```rust -fn main() { - let x = 1.saturating_add(2); -} -``` - - -### `replace_arith_with_wrapping` -**Source:** [replace_arith_op.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_arith_op.rs#L50) - -Replaces arithmetic on integers with the `wrapping_*` equivalent. - -#### Before -```rust -fn main() { - let x = 1 ┃+ 2; -} -``` - -#### After -```rust -fn main() { - let x = 1.wrapping_add(2); -} -``` - - -### `replace_char_with_string` -**Source:** [replace_string_with_char.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_string_with_char.rs#L51) - -Replace a char literal with a string literal. - -#### Before -```rust -fn main() { - find('{┃'); -} -``` - -#### After -```rust -fn main() { - find("{"); -} -``` - - -### `replace_derive_with_manual_impl` -**Source:** [replace_derive_with_manual_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs#L20) - -Converts a `derive` impl into a manual one. - -#### Before -```rust -#[derive(Deb┃ug, Display)] -struct S; -``` - -#### After -```rust -#[derive(Display)] -struct S; - -impl Debug for S { - ┃fn fmt(&self, f: &mut Formatter) -> Result<()> { - f.debug_struct("S").finish() - } -} -``` - - -### `replace_if_let_with_match` -**Source:** [replace_if_let_with_match.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_if_let_with_match.rs#L20) - -Replaces a `if let` expression with a `match` expression. - -#### Before -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - ┃if let Action::Move { distance } = action { - foo(distance) - } else { - bar() - } -} -``` - -#### After -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - match action { - Action::Move { distance } => foo(distance), - _ => bar(), - } -} -``` - - -### `replace_is_some_with_if_let_some` -**Source:** [replace_is_method_with_if_let_method.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs#L9) - -Replace `if x.is_some()` with `if let Some(_tmp) = x` or `if x.is_ok()` with `if let Ok(_tmp) = x`. - -#### Before -```rust -fn main() { - let x = Some(1); - if x.is_som┃e() {} -} -``` - -#### After -```rust -fn main() { - let x = Some(1); - if let Some(${0:x1}) = x {} -} -``` - - -### `replace_let_with_if_let` -**Source:** [replace_let_with_if_let.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_let_with_if_let.rs#L9) - -Replaces `let` with an `if let`. - -#### Before -```rust - -fn main(action: Action) { - ┃let x = compute(); -} - -fn compute() -> Option { None } -``` - -#### After -```rust - -fn main(action: Action) { - if let Some(x) = compute() { - } -} - -fn compute() -> Option { None } -``` - - -### `replace_match_with_if_let` -**Source:** [replace_if_let_with_match.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_if_let_with_match.rs#L188) - -Replaces a binary `match` with a wildcard pattern and no guards with an `if let` expression. - -#### Before -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - ┃match action { - Action::Move { distance } => foo(distance), - _ => bar(), - } -} -``` - -#### After -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - if let Action::Move { distance } = action { - foo(distance) - } else { - bar() - } -} -``` - - -### `replace_named_generic_with_impl` -**Source:** [replace_named_generic_with_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs#L18) - -Replaces named generic with an `impl Trait` in function argument. - -#### Before -```rust -fn new>(location: P) -> Self {} -``` - -#### After -```rust -fn new(location: impl AsRef) -> Self {} -``` - - -### `replace_qualified_name_with_use` -**Source:** [replace_qualified_name_with_use.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs#L13) - -Adds a use statement for a given fully-qualified name. - -#### Before -```rust -fn process(map: std::collections::┃HashMap) {} -``` - -#### After -```rust -use std::collections::HashMap; - -fn process(map: HashMap) {} -``` - - -### `replace_string_with_char` -**Source:** [replace_string_with_char.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_string_with_char.rs#L11) - -Replace string literal with char literal. - -#### Before -```rust -fn main() { - find("{┃"); -} -``` - -#### After -```rust -fn main() { - find('{'); -} -``` - - -### `replace_try_expr_with_match` -**Source:** [replace_try_expr_with_match.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs#L18) - -Replaces a `try` expression with a `match` expression. - -#### Before -```rust -fn handle() { - let pat = Some(true)┃?; -} -``` - -#### After -```rust -fn handle() { - let pat = match Some(true) { - Some(it) => it, - None => return None, - }; -} -``` - - -### `replace_turbofish_with_explicit_type` -**Source:** [replace_turbofish_with_explicit_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs#L12) - -Converts `::<_>` to an explicit type assignment. - -#### Before -```rust -fn make() -> T { ) } -fn main() { - let a = make┃::(); -} -``` - -#### After -```rust -fn make() -> T { ) } -fn main() { - let a: i32 = make(); -} -``` - - -### `replace_with_eager_method` -**Source:** [replace_method_eager_lazy.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs#L89) - -Replace `unwrap_or_else` with `unwrap_or` and `ok_or_else` with `ok_or`. - -#### Before -```rust -fn foo() { - let a = Some(1); - a.unwra┃p_or_else(|| 2); -} -``` - -#### After -```rust -fn foo() { - let a = Some(1); - a.unwrap_or(2); -} -``` - - -### `replace_with_lazy_method` -**Source:** [replace_method_eager_lazy.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs#L9) - -Replace `unwrap_or` with `unwrap_or_else` and `ok_or` with `ok_or_else`. - -#### Before -```rust -fn foo() { - let a = Some(1); - a.unwra┃p_or(2); -} -``` - -#### After -```rust -fn foo() { - let a = Some(1); - a.unwrap_or_else(|| 2); -} -``` - - -### `sort_items` -**Source:** [sort_items.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/sort_items.rs#L12) - -Sorts item members alphabetically: fields, enum variants and methods. - -#### Before -```rust -struct ┃Foo┃ { second: u32, first: String } -``` - -#### After -```rust -struct Foo { first: String, second: u32 } -``` - ---- - -#### Before -```rust -trait ┃Bar┃ { - fn second(&self) -> u32; - fn first(&self) -> String; -} -``` - -#### After -```rust -trait Bar { - fn first(&self) -> String; - fn second(&self) -> u32; -} -``` - ---- - -#### Before -```rust -struct Baz; -impl ┃Baz┃ { - fn second(&self) -> u32; - fn first(&self) -> String; -} -``` - -#### After -```rust -struct Baz; -impl Baz { - fn first(&self) -> String; - fn second(&self) -> u32; -} -``` - ---- -There is a difference between sorting enum variants: - -#### Before -```rust -enum ┃Animal┃ { - Dog(String, f64), - Cat { weight: f64, name: String }, -} -``` - -#### After -```rust -enum Animal { - Cat { weight: f64, name: String }, - Dog(String, f64), -} -``` - -and sorting a single enum struct variant: - -#### Before -```rust -enum Animal { - Dog(String, f64), - Cat ┃{ weight: f64, name: String }┃, -} -``` - -#### After -```rust -enum Animal { - Dog(String, f64), - Cat { name: String, weight: f64 }, -} -``` - - -### `split_import` -**Source:** [split_import.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/split_import.rs#L5) - -Wraps the tail of import into braces. - -#### Before -```rust -use std::┃collections::HashMap; -``` - -#### After -```rust -use std::{collections::HashMap}; -``` - - -### `sugar_impl_future_into_async` -**Source:** [toggle_async_sugar.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/toggle_async_sugar.rs#L13) - -Rewrites asynchronous function from `-> impl Future` into `async fn`. -This action does not touch the function body and therefore `async { 0 }` -block does not transform to just `0`. - -#### Before -```rust -pub fn foo() -> impl core::future::F┃uture { - async { 0 } -} -``` - -#### After -```rust -pub async fn foo() -> usize { - async { 0 } -} -``` - - -### `toggle_ignore` -**Source:** [toggle_ignore.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/toggle_ignore.rs#L8) - -Adds `#[ignore]` attribute to the test. - -#### Before -```rust -┃#[test] -fn arithmetics { - assert_eq!(2 + 2, 5); -} -``` - -#### After -```rust -#[test] -#[ignore] -fn arithmetics { - assert_eq!(2 + 2, 5); -} -``` - - -### `toggle_macro_delimiter` -**Source:** [toggle_macro_delimiter.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs#L9) - -Change macro delimiters in the order of `( -> { -> [ -> (`. - -#### Before -```rust -macro_rules! sth { - () => {}; -} - -sth!┃( ); -``` - -#### After -```rust -macro_rules! sth { - () => {}; -} - -sth!{ } -``` - - -### `unmerge_match_arm` -**Source:** [unmerge_match_arm.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unmerge_match_arm.rs#L10) - -Splits the current match with a `|` pattern into two arms with identical bodies. - -#### Before -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - match action { - Action::Move(..) ┃| Action::Stop => foo(), - } -} -``` - -#### After -```rust -enum Action { Move { distance: u32 }, Stop } - -fn handle(action: Action) { - match action { - Action::Move(..) => foo(), - Action::Stop => foo(), - } -} -``` - - -### `unmerge_use` -**Source:** [unmerge_use.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unmerge_use.rs#L12) - -Extracts single use item from use list. - -#### Before -```rust -use std::fmt::{Debug, Display┃}; -``` - -#### After -```rust -use std::fmt::{Debug}; -use std::fmt::Display; -``` - - -### `unnecessary_async` -**Source:** [unnecessary_async.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unnecessary_async.rs#L17) - -Removes the `async` mark from functions which have no `.await` in their body. -Looks for calls to the functions and removes the `.await` on the call site. - -#### Before -```rust -pub asy┃nc fn foo() {} -pub async fn bar() { foo().await } -``` - -#### After -```rust -pub fn foo() {} -pub async fn bar() { foo() } -``` - - -### `unqualify_method_call` -**Source:** [unqualify_method_call.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unqualify_method_call.rs#L9) - -Transforms universal function call syntax into a method call. - -#### Before -```rust -fn main() { - std::ops::Add::add┃(1, 2); -} -``` - -#### After -```rust -use std::ops::Add; - -fn main() { - 1.add(2); -} -``` - - -### `unwrap_block` -**Source:** [unwrap_block.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unwrap_block.rs#L12) - -This assist removes if...else, for, while and loop control statements to just keep the body. - -#### Before -```rust -fn foo() { - if true {┃ - println!("foo"); - } -} -``` - -#### After -```rust -fn foo() { - println!("foo"); -} -``` - - -### `unwrap_option_return_type` -**Source:** [unwrap_return_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unwrap_return_type.rs#L13) - -Unwrap the function's return type. - -#### Before -```rust -fn foo() -> Option┃ { Some(42i32) } -``` - -#### After -```rust -fn foo() -> i32 { 42i32 } -``` - - -### `unwrap_result_return_type` -**Source:** [unwrap_return_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unwrap_return_type.rs#L26) - -Unwrap the function's return type. - -#### Before -```rust -fn foo() -> Result┃ { Ok(42i32) } -``` - -#### After -```rust -fn foo() -> i32 { 42i32 } -``` - - -### `unwrap_tuple` -**Source:** [unwrap_tuple.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unwrap_tuple.rs#L8) - -Unwrap the tuple to different variables. - -#### Before -```rust -fn main() { - ┃let (foo, bar) = ("Foo", "Bar"); -} -``` - -#### After -```rust -fn main() { - let foo = "Foo"; - let bar = "Bar"; -} -``` - - -### `wrap_return_type_in_option` -**Source:** [wrap_return_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/wrap_return_type.rs#L16) - -Wrap the function's return type into Option. - -#### Before -```rust -fn foo() -> i32┃ { 42i32 } -``` - -#### After -```rust -fn foo() -> Option { Some(42i32) } -``` - - -### `wrap_return_type_in_result` -**Source:** [wrap_return_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/wrap_return_type.rs#L29) - -Wrap the function's return type into Result. - -#### Before -```rust -fn foo() -> i32┃ { 42i32 } -``` - -#### After -```rust -fn foo() -> Result { Ok(42i32) } -``` - - -### `wrap_unwrap_cfg_attr` -**Source:** [wrap_unwrap_cfg_attr.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs#L12) - -Wraps an attribute to a cfg_attr attribute or unwraps a cfg_attr attribute to the inner attributes. - -#### Before -```rust -#[derive┃(Debug)] -struct S { - field: i32 -} -``` - -#### After -```rust -#[cfg_attr(┃, derive(Debug))] -struct S { - field: i32 -} -``` diff --git a/src/tools/rust-analyzer/docs/book/src/diagnostics_generated.md b/src/tools/rust-analyzer/docs/book/src/diagnostics_generated.md deleted file mode 100644 index d34c459ad0258..0000000000000 --- a/src/tools/rust-analyzer/docs/book/src/diagnostics_generated.md +++ /dev/null @@ -1,516 +0,0 @@ -//! Generated by `cargo xtask codegen diagnostics-docs`, do not edit by hand. - -#### attribute-expansion-disabled - -Source: [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#7) - - -This diagnostic is shown for attribute proc macros when attribute expansions have been disabled. - - - - -#### await-outside-of-async - -Source: [await_outside_of_async.rs](crates/ide-diagnostics/src/handlers/await_outside_of_async.rs#3) - - -This diagnostic is triggered if the `await` keyword is used outside of an async function or block - - - - -#### break-outside-of-loop - -Source: [break_outside_of_loop.rs](crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs#3) - - -This diagnostic is triggered if the `break` keyword is used outside of a loop. - - - - -#### cast-to-unsized - -Source: [invalid_cast.rs](crates/ide-diagnostics/src/handlers/invalid_cast.rs#106) - - -This diagnostic is triggered when casting to an unsized type - - - - -#### expected-function - -Source: [expected_function.rs](crates/ide-diagnostics/src/handlers/expected_function.rs#5) - - -This diagnostic is triggered if a call is made on something that is not callable. - - - - -#### generic-args-prohibited - -Source: [generic_args_prohibited.rs](crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs#10) - - -This diagnostic is shown when generic arguments are provided for a type that does not accept -generic arguments. - - - - -#### inactive-code - -Source: [inactive_code.rs](crates/ide-diagnostics/src/handlers/inactive_code.rs#6) - - -This diagnostic is shown for code with inactive `#[cfg]` attributes. - - - - -#### incoherent-impl - -Source: [incoherent_impl.rs](crates/ide-diagnostics/src/handlers/incoherent_impl.rs#6) - - -This diagnostic is triggered if the targe type of an impl is from a foreign crate. - - - - -#### incorrect-ident-case - -Source: [incorrect_case.rs](crates/ide-diagnostics/src/handlers/incorrect_case.rs#13) - - -This diagnostic is triggered if an item name doesn't follow [Rust naming convention](https://doc.rust-lang.org/1.0.0/style/style/naming/README.html). - - - - -#### invalid-cast - -Source: [invalid_cast.rs](crates/ide-diagnostics/src/handlers/invalid_cast.rs#18) - - -This diagnostic is triggered if the code contains an illegal cast - - - - -#### invalid-derive-target - -Source: [invalid_derive_target.rs](crates/ide-diagnostics/src/handlers/invalid_derive_target.rs#3) - - -This diagnostic is shown when the derive attribute is used on an item other than a `struct`, -`enum` or `union`. - - - - -#### macro-def-error - -Source: [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#24) - - -This diagnostic is shown for macro expansion errors. - - - - -#### macro-error - -Source: [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#3) - - -This diagnostic is shown for macro expansion errors. - - - - -#### malformed-derive - -Source: [malformed_derive.rs](crates/ide-diagnostics/src/handlers/malformed_derive.rs#3) - - -This diagnostic is shown when the derive attribute has invalid input. - - - - -#### mismatched-arg-count - -Source: [mismatched_arg_count.rs](crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs#31) - - -This diagnostic is triggered if a function is invoked with an incorrect amount of arguments. - - - - -#### mismatched-tuple-struct-pat-arg-count - -Source: [mismatched_arg_count.rs](crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs#11) - - -This diagnostic is triggered if a function is invoked with an incorrect amount of arguments. - - - - -#### missing-fields - -Source: [missing_fields.rs](crates/ide-diagnostics/src/handlers/missing_fields.rs#19) - - -This diagnostic is triggered if record lacks some fields that exist in the corresponding structure. - -Example: - -```rust -struct A { a: u8, b: u8 } - -let a = A { a: 10 }; -``` - - - - -#### missing-match-arm - -Source: [missing_match_arms.rs](crates/ide-diagnostics/src/handlers/missing_match_arms.rs#3) - - -This diagnostic is triggered if `match` block is missing one or more match arms. - - - - -#### missing-unsafe - -Source: [missing_unsafe.rs](crates/ide-diagnostics/src/handlers/missing_unsafe.rs#10) - - -This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block. - - - - -#### moved-out-of-ref - -Source: [moved_out_of_ref.rs](crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs#4) - - -This diagnostic is triggered on moving non copy things out of references. - - - - -#### need-mut - -Source: [mutability_errors.rs](crates/ide-diagnostics/src/handlers/mutability_errors.rs#8) - - -This diagnostic is triggered on mutating an immutable variable. - - - - -#### no-such-field - -Source: [no_such_field.rs](crates/ide-diagnostics/src/handlers/no_such_field.rs#12) - - -This diagnostic is triggered if created structure does not have field provided in record. - - - - -#### non-exhaustive-let - -Source: [non_exhaustive_let.rs](crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs#3) - - -This diagnostic is triggered if a `let` statement without an `else` branch has a non-exhaustive -pattern. - - - - -#### private-assoc-item - -Source: [private_assoc_item.rs](crates/ide-diagnostics/src/handlers/private_assoc_item.rs#3) - - -This diagnostic is triggered if the referenced associated item is not visible from the current -module. - - - - -#### private-field - -Source: [private_field.rs](crates/ide-diagnostics/src/handlers/private_field.rs#3) - - -This diagnostic is triggered if the accessed field is not visible from the current module. - - - - -#### proc-macro-disabled - -Source: [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#11) - - -This diagnostic is shown for proc macros that have been specifically disabled via `rust-analyzer.procMacro.ignored`. - - - - -#### remove-trailing-return - -Source: [remove_trailing_return.rs](crates/ide-diagnostics/src/handlers/remove_trailing_return.rs#8) - - -This diagnostic is triggered when there is a redundant `return` at the end of a function -or closure. - - - - -#### remove-unnecessary-else - -Source: [remove_unnecessary_else.rs](crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs#17) - - -This diagnostic is triggered when there is an `else` block for an `if` expression whose -then branch diverges (e.g. ends with a `return`, `continue`, `break` e.t.c). - - - - -#### replace-filter-map-next-with-find-map - -Source: [replace_filter_map_next_with_find_map.rs](crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs#11) - - -This diagnostic is triggered when `.filter_map(..).next()` is used, rather than the more concise `.find_map(..)`. - - - - -#### trait-impl-incorrect-safety - -Source: [trait_impl_incorrect_safety.rs](crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs#6) - - -Diagnoses incorrect safety annotations of trait impls. - - - - -#### trait-impl-missing-assoc_item - -Source: [trait_impl_missing_assoc_item.rs](crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs#7) - - -Diagnoses missing trait items in a trait impl. - - - - -#### trait-impl-orphan - -Source: [trait_impl_orphan.rs](crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs#5) - - -Only traits defined in the current crate can be implemented for arbitrary types - - - - -#### trait-impl-redundant-assoc_item - -Source: [trait_impl_redundant_assoc_item.rs](crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs#12) - - -Diagnoses redundant trait items in a trait impl. - - - - -#### type-mismatch - -Source: [type_mismatch.rs](crates/ide-diagnostics/src/handlers/type_mismatch.rs#20) - - -This diagnostic is triggered when the type of an expression or pattern does not match -the expected type. - - - - -#### typed-hole - -Source: [typed_hole.rs](crates/ide-diagnostics/src/handlers/typed_hole.rs#18) - - -This diagnostic is triggered when an underscore expression is used in an invalid position. - - - - -#### undeclared-label - -Source: [undeclared_label.rs](crates/ide-diagnostics/src/handlers/undeclared_label.rs#3) - - - - - - -#### unimplemented-builtin-macro - -Source: [unimplemented_builtin_macro.rs](crates/ide-diagnostics/src/handlers/unimplemented_builtin_macro.rs#3) - - -This diagnostic is shown for builtin macros which are not yet implemented by rust-analyzer - - - - -#### unlinked-file - -Source: [unlinked_file.rs](crates/ide-diagnostics/src/handlers/unlinked_file.rs#20) - - -This diagnostic is shown for files that are not included in any crate, or files that are part of -crates rust-analyzer failed to discover. The file will not have IDE features available. - - - - -#### unnecessary-braces - -Source: [useless_braces.rs](crates/ide-diagnostics/src/handlers/useless_braces.rs#9) - - -Diagnostic for unnecessary braces in `use` items. - - - - -#### unreachable-label - -Source: [unreachable_label.rs](crates/ide-diagnostics/src/handlers/unreachable_label.rs#3) - - - - - - -#### unresolved-assoc-item - -Source: [unresolved_assoc_item.rs](crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs#3) - - -This diagnostic is triggered if the referenced associated item does not exist. - - - - -#### unresolved-extern-crate - -Source: [unresolved_extern_crate.rs](crates/ide-diagnostics/src/handlers/unresolved_extern_crate.rs#3) - - -This diagnostic is triggered if rust-analyzer is unable to discover referred extern crate. - - - - -#### unresolved-field - -Source: [unresolved_field.rs](crates/ide-diagnostics/src/handlers/unresolved_field.rs#23) - - -This diagnostic is triggered if a field does not exist on a given type. - - - - -#### unresolved-ident - -Source: [unresolved_ident.rs](crates/ide-diagnostics/src/handlers/unresolved_ident.rs#3) - - -This diagnostic is triggered if an expr-position ident is invalid. - - - - -#### unresolved-import - -Source: [unresolved_import.rs](crates/ide-diagnostics/src/handlers/unresolved_import.rs#3) - - -This diagnostic is triggered if rust-analyzer is unable to resolve a path in -a `use` declaration. - - - - -#### unresolved-macro-call - -Source: [unresolved_macro_call.rs](crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs#3) - - -This diagnostic is triggered if rust-analyzer is unable to resolve the path -to a macro in a macro invocation. - - - - -#### unresolved-method - -Source: [unresolved_method.rs](crates/ide-diagnostics/src/handlers/unresolved_method.rs#15) - - -This diagnostic is triggered if a method does not exist on a given type. - - - - -#### unresolved-module - -Source: [unresolved_module.rs](crates/ide-diagnostics/src/handlers/unresolved_module.rs#8) - - -This diagnostic is triggered if rust-analyzer is unable to discover referred module. - - - - -#### unused-mut - -Source: [mutability_errors.rs](crates/ide-diagnostics/src/handlers/mutability_errors.rs#62) - - -This diagnostic is triggered when a mutable variable isn't actually mutated. - - - - -#### unused-variables - -Source: [unused_variables.rs](crates/ide-diagnostics/src/handlers/unused_variables.rs#13) - - -This diagnostic is triggered when a local variable is not used. - - diff --git a/src/tools/rust-analyzer/docs/book/src/features_generated.md b/src/tools/rust-analyzer/docs/book/src/features_generated.md deleted file mode 100644 index 2c5829b1f54c0..0000000000000 --- a/src/tools/rust-analyzer/docs/book/src/features_generated.md +++ /dev/null @@ -1,940 +0,0 @@ -//! Generated by `cargo xtask codegen feature-docs`, do not edit by hand. - -### Annotations -**Source:** [annotations.rs](crates/ide/src/annotations.rs#19) - -Provides user with annotations above items for looking up references or impl blocks -and running/debugging binaries. - -![Annotations](https://user-images.githubusercontent.com/48062697/113020672-b7c34f00-917a-11eb-8f6e-858735660a0e.png) - - -### Auto Import -**Source:** [auto_import.rs](crates/ide-assists/src/handlers/auto_import.rs#15) - -Using the `auto-import` assist it is possible to insert missing imports for unresolved items. -When inserting an import it will do so in a structured manner by keeping imports grouped, -separated by a newline in the following order: - -- `std` and `core` -- External Crates -- Current Crate, paths prefixed by `crate` -- Current Module, paths prefixed by `self` -- Super Module, paths prefixed by `super` - -Example: -```rust -use std::fs::File; - -use itertools::Itertools; -use syntax::ast; - -use crate::utils::insert_use; - -use self::auto_import; - -use super::AssistContext; -``` - -#### Import Granularity - -It is possible to configure how use-trees are merged with the `imports.granularity.group` setting. -It has the following configurations: - -- `crate`: Merge imports from the same crate into a single use statement. This kind of - nesting is only supported in Rust versions later than 1.24. -- `module`: Merge imports from the same module into a single use statement. -- `item`: Don't merge imports at all, creating one import per item. -- `preserve`: Do not change the granularity of any imports. For auto-import this has the same - effect as `item`. -- `one`: Merge all imports into a single use statement as long as they have the same visibility - and attributes. - -In `VS Code` the configuration for this is `rust-analyzer.imports.granularity.group`. - -#### Import Prefix - -The style of imports in the same crate is configurable through the `imports.prefix` setting. -It has the following configurations: - -- `crate`: This setting will force paths to be always absolute, starting with the `crate` - prefix, unless the item is defined outside of the current crate. -- `self`: This setting will force paths that are relative to the current module to always - start with `self`. This will result in paths that always start with either `crate`, `self`, - `super` or an extern crate identifier. -- `plain`: This setting does not impose any restrictions in imports. - -In `VS Code` the configuration for this is `rust-analyzer.imports.prefix`. - -![Auto Import](https://user-images.githubusercontent.com/48062697/113020673-b85be580-917a-11eb-9022-59585f35d4f8.gif) - - -### Completion With Autoimport -**Source:** [flyimport.rs](crates/ide-completion/src/completions/flyimport.rs#20) - -When completing names in the current scope, proposes additional imports from other modules or crates, -if they can be qualified in the scope, and their name contains all symbols from the completion input. - -To be considered applicable, the name must contain all input symbols in the given order, not necessarily adjacent. -If any input symbol is not lowercased, the name must contain all symbols in exact case; otherwise the containing is checked case-insensitively. - -``` -fn main() { - pda$0 -} -# pub mod std { pub mod marker { pub struct PhantomData { } } } -``` --> -``` -use std::marker::PhantomData; - -fn main() { - PhantomData -} -# pub mod std { pub mod marker { pub struct PhantomData { } } } -``` - -Also completes associated items, that require trait imports. -If any unresolved and/or partially-qualified path precedes the input, it will be taken into account. -Currently, only the imports with their import path ending with the whole qualifier will be proposed -(no fuzzy matching for qualifier). - -``` -mod foo { - pub mod bar { - pub struct Item; - - impl Item { - pub const TEST_ASSOC: usize = 3; - } - } -} - -fn main() { - bar::Item::TEST_A$0 -} -``` --> -``` -use foo::bar; - -mod foo { - pub mod bar { - pub struct Item; - - impl Item { - pub const TEST_ASSOC: usize = 3; - } - } -} - -fn main() { - bar::Item::TEST_ASSOC -} -``` - -NOTE: currently, if an assoc item comes from a trait that's not currently imported, and it also has an unresolved and/or partially-qualified path, -no imports will be proposed. - -#### Fuzzy search details - -To avoid an excessive amount of the results returned, completion input is checked for inclusion in the names only -(i.e. in `HashMap` in the `std::collections::HashMap` path). -For the same reasons, avoids searching for any path imports for inputs with their length less than 2 symbols -(but shows all associated items for any input length). - -#### Import configuration - -It is possible to configure how use-trees are merged with the `imports.granularity.group` setting. -Mimics the corresponding behavior of the `Auto Import` feature. - -#### LSP and performance implications - -The feature is enabled only if the LSP client supports LSP protocol version 3.16+ and reports the `additionalTextEdits` -(case-sensitive) resolve client capability in its client capabilities. -This way the server is able to defer the costly computations, doing them for a selected completion item only. -For clients with no such support, all edits have to be calculated on the completion request, including the fuzzy search completion ones, -which might be slow ergo the feature is automatically disabled. - -#### Feature toggle - -The feature can be forcefully turned off in the settings with the `rust-analyzer.completion.autoimport.enable` flag. -Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corresponding -capability enabled. - - -### Debug ItemTree -**Source:** [view_item_tree.rs](crates/ide/src/view_item_tree.rs#5) - -Displays the ItemTree of the currently open file, for debugging. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Debug ItemTree** | - - -### Expand Macro Recursively -**Source:** [expand_macro.rs](crates/ide/src/expand_macro.rs#18) - -Shows the full macro expansion of the macro at the current caret position. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Expand macro recursively at caret** | - -![Expand Macro Recursively](https://user-images.githubusercontent.com/48062697/113020648-b3973180-917a-11eb-84a9-ecb921293dc5.gif) - - -### Expand and Shrink Selection -**Source:** [extend_selection.rs](crates/ide/src/extend_selection.rs#15) - -Extends or shrinks the current selection to the encompassing syntactic construct -(expression, statement, item, module, etc). It works with multiple cursors. - -| Editor | Shortcut | -|---------|----------| -| VS Code | Alt+Shift+→, Alt+Shift+← | - -![Expand and Shrink Selection](https://user-images.githubusercontent.com/48062697/113020651-b42fc800-917a-11eb-8a4f-cf1a07859fac.gif) - - -### File Structure -**Source:** [file_structure.rs](crates/ide/src/file_structure.rs#26) - -Provides a tree of the symbols defined in the file. Can be used to - -* fuzzy search symbol in a file (super useful) -* draw breadcrumbs to describe the context around the cursor -* draw outline of the file - -| Editor | Shortcut | -|---------|----------| -| VS Code | Ctrl+Shift+O | - -![File Structure](https://user-images.githubusercontent.com/48062697/113020654-b42fc800-917a-11eb-8388-e7dc4d92b02e.gif) - - -### Find All References -**Source:** [references.rs](crates/ide/src/references.rs#42) - -Shows all references of the item at the cursor location - -| Editor | Shortcut | -|---------|----------| -| VS Code | Shift+Alt+F12 | - -![Find All References](https://user-images.githubusercontent.com/48062697/113020670-b7c34f00-917a-11eb-8003-370ac5f2b3cb.gif) - - -### Folding -**Source:** [folding_ranges.rs](crates/ide/src/folding_ranges.rs#36) - -Defines folding regions for curly braced blocks, runs of consecutive use, mod, const or static -items, and `region` / `endregion` comment markers. - - -### Format String Completion -**Source:** [format_like.rs](crates/ide-completion/src/completions/postfix/format_like.rs#0) - -`"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`. - -The following postfix snippets are available: - -* `format` -> `format!(...)` -* `panic` -> `panic!(...)` -* `println` -> `println!(...)` -* `log`: -** `logd` -> `log::debug!(...)` -** `logt` -> `log::trace!(...)` -** `logi` -> `log::info!(...)` -** `logw` -> `log::warn!(...)` -** `loge` -> `log::error!(...)` - -![Format String Completion](https://user-images.githubusercontent.com/48062697/113020656-b560f500-917a-11eb-87de-02991f61beb8.gif) - - -### Go to Declaration -**Source:** [goto_declaration.rs](crates/ide/src/goto_declaration.rs#13) - -Navigates to the declaration of an identifier. - -This is the same as `Go to Definition` with the following exceptions: -- outline modules will navigate to the `mod name;` item declaration -- trait assoc items will navigate to the assoc item of the trait declaration as opposed to the trait impl -- fields in patterns will navigate to the field declaration of the struct, union or variant - - -### Go to Definition -**Source:** [goto_definition.rs](crates/ide/src/goto_definition.rs#28) - -Navigates to the definition of an identifier. - -For outline modules, this will navigate to the source file of the module. - -| Editor | Shortcut | -|---------|----------| -| VS Code | F12 | - -![Go to Definition](https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif) - - -### Go to Implementation -**Source:** [goto_implementation.rs](crates/ide/src/goto_implementation.rs#11) - -Navigates to the impl items of types. - -| Editor | Shortcut | -|---------|----------| -| VS Code | Ctrl+F12 - -![Go to Implementation](https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif) - - -### Go to Type Definition -**Source:** [goto_type_definition.rs](crates/ide/src/goto_type_definition.rs#7) - -Navigates to the type of an identifier. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **Go to Type Definition** | - -![Go to Type Definition](https://user-images.githubusercontent.com/48062697/113020657-b560f500-917a-11eb-9007-0f809733a338.gif) - - -### Highlight Related -**Source:** [highlight_related.rs](crates/ide/src/highlight_related.rs#42) - -Highlights constructs related to the thing under the cursor: - -1. if on an identifier, highlights all references to that identifier in the current file - * additionally, if the identifier is a trait in a where clause, type parameter trait bound or use item, highlights all references to that trait's assoc items in the corresponding scope -1. if on an `async` or `await` token, highlights all yield points for that async context -1. if on a `return` or `fn` keyword, `?` character or `->` return type arrow, highlights all exit points for that context -1. if on a `break`, `loop`, `while` or `for` token, highlights all break points for that loop or block context -1. if on a `move` or `|` token that belongs to a closure, highlights all captures of the closure. - -Note: `?`, `|` and `->` do not currently trigger this behavior in the VSCode editor. - - -### Hover -**Source:** [hover.rs](crates/ide/src/hover.rs#116) - -Shows additional information, like the type of an expression or the documentation for a definition when "focusing" code. -Focusing is usually hovering with a mouse, but can also be triggered with a shortcut. - -![Hover](https://user-images.githubusercontent.com/48062697/113020658-b5f98b80-917a-11eb-9f88-3dbc27320c95.gif) - - -### Inlay Hints -**Source:** [inlay_hints.rs](crates/ide/src/inlay_hints.rs#41) - -rust-analyzer shows additional information inline with the source code. -Editors usually render this using read-only virtual text snippets interspersed with code. - -rust-analyzer by default shows hints for - -* types of local variables -* names of function arguments -* names of const generic parameters -* types of chained expressions - -Optionally, one can enable additional hints for - -* return types of closure expressions -* elided lifetimes -* compiler inserted reborrows -* names of generic type and lifetime parameters - -Note: inlay hints for function argument names are heuristically omitted to reduce noise and will not appear if -any of the -[following criteria](https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L92-L99) -are met: - -* the parameter name is a suffix of the function's name -* the argument is a qualified constructing or call expression where the qualifier is an ADT -* exact argument<->parameter match(ignoring leading underscore) or parameter is a prefix/suffix - of argument with _ splitting it off -* the parameter name starts with `ra_fixture` -* the parameter name is a -[well known name](https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L200) -in a unary function -* the parameter name is a -[single character](https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L201) -in a unary function - -![Inlay hints](https://user-images.githubusercontent.com/48062697/113020660-b5f98b80-917a-11eb-8d70-3be3fd558cdd.png) - - -### Interpret A Function, Static Or Const. -**Source:** [interpret.rs](crates/ide/src/interpret.rs#8) - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Interpret** | - - -### Join Lines -**Source:** [join_lines.rs](crates/ide/src/join_lines.rs#20) - -Join selected lines into one, smartly fixing up whitespace, trailing commas, and braces. - -See [this gif](https://user-images.githubusercontent.com/1711539/124515923-4504e800-dde9-11eb-8d58-d97945a1a785.gif) for the cases handled specially by joined lines. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Join lines** | - -![Join Lines](https://user-images.githubusercontent.com/48062697/113020661-b6922200-917a-11eb-87c4-b75acc028f11.gif) - - -### Magic Completions -**Source:** [lib.rs](crates/ide-completion/src/lib.rs#78) - -In addition to usual reference completion, rust-analyzer provides some ✨magic✨ -completions as well: - -Keywords like `if`, `else` `while`, `loop` are completed with braces, and cursor -is placed at the appropriate position. Even though `if` is easy to type, you -still want to complete it, to get ` { }` for free! `return` is inserted with a -space or `;` depending on the return type of the function. - -When completing a function call, `()` are automatically inserted. If a function -takes arguments, the cursor is positioned inside the parenthesis. - -There are postfix completions, which can be triggered by typing something like -`foo().if`. The word after `.` determines postfix completion. Possible variants are: - -- `expr.if` -> `if expr {}` or `if let ... {}` for `Option` or `Result` -- `expr.match` -> `match expr {}` -- `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result` -- `expr.ref` -> `&expr` -- `expr.refm` -> `&mut expr` -- `expr.let` -> `let $0 = expr;` -- `expr.lete` -> `let $1 = expr else { $0 };` -- `expr.letm` -> `let mut $0 = expr;` -- `expr.not` -> `!expr` -- `expr.dbg` -> `dbg!(expr)` -- `expr.dbgr` -> `dbg!(&expr)` -- `expr.call` -> `(expr)` - -There also snippet completions: - -#### Expressions - -- `pd` -> `eprintln!(" = {:?}", );` -- `ppd` -> `eprintln!(" = {:#?}", );` - -#### Items - -- `tfn` -> `#[test] fn feature(){}` -- `tmod` -> -```rust -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_name() {} -} -``` - -And the auto import completions, enabled with the `rust-analyzer.completion.autoimport.enable` setting and the corresponding LSP client capabilities. -Those are the additional completion options with automatic `use` import and options from all project importable items, -fuzzy matched against the completion input. - -![Magic Completions](https://user-images.githubusercontent.com/48062697/113020667-b72ab880-917a-11eb-8778-716cf26a0eb3.gif) - - -### Matching Brace -**Source:** [matching_brace.rs](crates/ide/src/matching_brace.rs#6) - -If the cursor is on any brace (`<>(){}[]||`) which is a part of a brace-pair, -moves cursor to the matching brace. It uses the actual parser to determine -braces, so it won't confuse generics with comparisons. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Find matching brace** | - -![Matching Brace](https://user-images.githubusercontent.com/48062697/113065573-04298180-91b1-11eb-8dec-d4e2a202f304.gif) - - -### Memory Usage -**Source:** [apply_change.rs](crates/ide-db/src/apply_change.rs#43) - -Clears rust-analyzer's internal database and prints memory usage statistics. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Memory Usage (Clears Database)** - - -### Move Item -**Source:** [move_item.rs](crates/ide/src/move_item.rs#16) - -Move item under cursor or selection up and down. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Move item up** -| VS Code | **rust-analyzer: Move item down** - -![Move Item](https://user-images.githubusercontent.com/48062697/113065576-04298180-91b1-11eb-91ce-4505e99ed598.gif) - - -### On Enter -**Source:** [on_enter.rs](crates/ide/src/typing/on_enter.rs#17) - -rust-analyzer can override Enter key to make it smarter: - -- Enter inside triple-slash comments automatically inserts `///` -- Enter in the middle or after a trailing space in `//` inserts `//` -- Enter inside `//!` doc comments automatically inserts `//!` -- Enter after `{` indents contents and closing `}` of single-line block - -This action needs to be assigned to shortcut explicitly. - -Note that, depending on the other installed extensions, this feature can visibly slow down typing. -Similarly, if rust-analyzer crashes or stops responding, `Enter` might not work. -In that case, you can still press `Shift-Enter` to insert a newline. - -#### VS Code - -Add the following to `keybindings.json`: -```json -{ - "key": "Enter", - "command": "rust-analyzer.onEnter", - "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust" -} -```` - -When using the Vim plugin: -```json -{ - "key": "Enter", - "command": "rust-analyzer.onEnter", - "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust && vim.mode == 'Insert'" -} -```` - -![On Enter](https://user-images.githubusercontent.com/48062697/113065578-04c21800-91b1-11eb-82b8-22b8c481e645.gif) - - -### On Typing Assists -**Source:** [typing.rs](crates/ide/src/typing.rs#42) - -Some features trigger on typing certain characters: - -- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression -- typing `=` between two expressions adds `;` when in statement position -- typing `=` to turn an assignment into an equality comparison removes `;` when in expression position -- typing `.` in a chain method call auto-indents -- typing `{` or `(` in front of an expression inserts a closing `}` or `)` after the expression -- typing `{` in a use item adds a closing `}` in the right place -- typing `>` to complete a return type `->` will insert a whitespace after it - -#### VS Code - -Add the following to `settings.json`: -```json -"editor.formatOnType": true, -``` - -![On Typing Assists](https://user-images.githubusercontent.com/48062697/113166163-69758500-923a-11eb-81ee-eb33ec380399.gif) -![On Typing Assists](https://user-images.githubusercontent.com/48062697/113171066-105c2000-923f-11eb-87ab-f4a263346567.gif) - - -### Open Docs -**Source:** [doc_links.rs](crates/ide/src/doc_links.rs#118) - -Retrieve a links to documentation for the given symbol. - -The simplest way to use this feature is via the context menu. Right-click on -the selected item. The context menu opens. Select **Open Docs**. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Open Docs** | - - -### Parent Module -**Source:** [parent_module.rs](crates/ide/src/parent_module.rs#14) - -Navigates to the parent module of the current module. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Locate parent module** | - -![Parent Module](https://user-images.githubusercontent.com/48062697/113065580-04c21800-91b1-11eb-9a32-00086161c0bd.gif) - - -### Related Tests -**Source:** [runnables.rs](crates/ide/src/runnables.rs#202) - -Provides a sneak peek of all tests where the current item is used. - -The simplest way to use this feature is via the context menu. Right-click on -the selected item. The context menu opens. Select **Peek Related Tests**. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Peek Related Tests** | - - -### Rename -**Source:** [rename.rs](crates/ide/src/rename.rs#70) - -Renames the item below the cursor and all of its references - -| Editor | Shortcut | -|---------|----------| -| VS Code | F2 | - -![Rename](https://user-images.githubusercontent.com/48062697/113065582-055aae80-91b1-11eb-8ade-2b58e6d81883.gif) - - -### Run -**Source:** [runnables.rs](crates/ide/src/runnables.rs#116) - -Shows a popup suggesting to run a test/benchmark/binary **at the current cursor -location**. Super useful for repeatedly running just a single test. Do bind this -to a shortcut! - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Run** | - -![Run](https://user-images.githubusercontent.com/48062697/113065583-055aae80-91b1-11eb-958f-d67efcaf6a2f.gif) - - -### Semantic Syntax Highlighting -**Source:** [syntax_highlighting.rs](crates/ide/src/syntax_highlighting.rs#68) - -rust-analyzer highlights the code semantically. -For example, `Bar` in `foo::Bar` might be colored differently depending on whether `Bar` is an enum or a trait. -rust-analyzer does not specify colors directly, instead it assigns a tag (like `struct`) and a set of modifiers (like `declaration`) to each token. -It's up to the client to map those to specific colors. - -The general rule is that a reference to an entity gets colored the same way as the entity itself. -We also give special modifier for `mut` and `&mut` local variables. - - -#### Token Tags - -Rust-analyzer currently emits the following token tags: - -- For items: - -| | | -|-----------|--------------------------------| -| attribute | Emitted for attribute macros. | -|enum| Emitted for enums. | -|function| Emitted for free-standing functions. | -|derive| Emitted for derive macros. | -|macro| Emitted for function-like macros. | -|method| Emitted for associated functions, also knowns as methods. | -|namespace| Emitted for modules. | -|struct| Emitted for structs.| -|trait| Emitted for traits.| -|typeAlias| Emitted for type aliases and `Self` in `impl`s.| -|union| Emitted for unions.| - -- For literals: - -| | | -|-----------|--------------------------------| -| boolean| Emitted for the boolean literals `true` and `false`.| -| character| Emitted for character literals.| -| number| Emitted for numeric literals.| -| string| Emitted for string literals.| -| escapeSequence| Emitted for escaped sequences inside strings like `\n`.| -| formatSpecifier| Emitted for format specifiers `{:?}` in `format!`-like macros.| - -- For operators: - -| | | -|-----------|--------------------------------| -|operator| Emitted for general operators.| -|arithmetic| Emitted for the arithmetic operators `+`, `-`, `*`, `/`, `+=`, `-=`, `*=`, `/=`.| -|bitwise| Emitted for the bitwise operators `|`, `&`, `!`, `^`, `|=`, `&=`, `^=`.| -|comparison| Emitted for the comparison oerators `>`, `<`, `==`, `>=`, `<=`, `!=`.| -|logical| Emitted for the logical operatos `||`, `&&`, `!`.| - -- For punctuation: - -| | | -|-----------|--------------------------------| -|punctuation| Emitted for general punctuation.| -|attributeBracket| Emitted for attribute invocation brackets, that is the `#[` and `]` tokens.| -|angle| Emitted for `<>` angle brackets.| -|brace| Emitted for `{}` braces.| -|bracket| Emitted for `[]` brackets.| -|parenthesis| Emitted for `()` parentheses.| -|colon| Emitted for the `:` token.| -|comma| Emitted for the `,` token.| -|dot| Emitted for the `.` token.| -|semi| Emitted for the `;` token.| -|macroBang| Emitted for the `!` token in macro calls.| - -- - -| | | -|-----------|--------------------------------| -|builtinAttribute| Emitted for names to builtin attributes in attribute path, the `repr` in `#[repr(u8)]` for example.| -|builtinType| Emitted for builtin types like `u32`, `str` and `f32`.| -|comment| Emitted for comments.| -|constParameter| Emitted for const parameters.| -|deriveHelper| Emitted for derive helper attributes.| -|enumMember| Emitted for enum variants.| -|generic| Emitted for generic tokens that have no mapping.| -|keyword| Emitted for keywords.| -|label| Emitted for labels.| -|lifetime| Emitted for lifetimes.| -|parameter| Emitted for non-self function parameters.| -|property| Emitted for struct and union fields.| -|selfKeyword| Emitted for the self function parameter and self path-specifier.| -|selfTypeKeyword| Emitted for the Self type parameter.| -|toolModule| Emitted for tool modules.| -|typeParameter| Emitted for type parameters.| -|unresolvedReference| Emitted for unresolved references, names that rust-analyzer can't find the definition of.| -|variable| Emitted for locals, constants and statics.| - - -#### Token Modifiers - -Token modifiers allow to style some elements in the source code more precisely. - -Rust-analyzer currently emits the following token modifiers: - -| | | -|-----------|--------------------------------| -|async| Emitted for async functions and the `async` and `await` keywords.| -|attribute| Emitted for tokens inside attributes.| -|callable| Emitted for locals whose types implements one of the `Fn*` traits.| -|constant| Emitted for const.| -|consuming| Emitted for locals that are being consumed when use in a function call.| -|controlFlow| Emitted for control-flow related tokens, this includes th `?` operator.| -|crateRoot| Emitted for crate names, like `serde` and `crate.| -|declaration| Emitted for names of definitions, like `foo` in `fn foo(){}`.| -|defaultLibrary| Emitted for items from built-in crates (std, core, allc, test and proc_macro).| -|documentation| Emitted for documentation comment.| -|injected| Emitted for doc-string injected highlighting like rust source blocks in documentation.| -|intraDocLink| Emitted for intra doc links in doc-string.| -|library| Emitted for items that are defined outside of the current crae.| -|macro| Emitted for tokens inside macro call.| -|mutable| Emitted for mutable locals and statics as well as functions taking `&mut self`.| -|public| Emitted for items that are from the current crate and are `pub.| -|reference| Emitted for locals behind a reference and functions taking self` by reference.| -|static| Emitted for "static" functions, also known as functions that d not take a `self` param, as well as statics and consts.| -|trait| Emitted for associated trait item.| -|unsafe| Emitted for unsafe operations, like unsafe function calls, as ell as the `unsafe` token.| - -![Semantic Syntax Highlighting](https://user-images.githubusercontent.com/48062697/113164457-06cfb980-9239-11eb-819b-0f93e646acf8.png) -![Semantic Syntax Highlighting](https://user-images.githubusercontent.com/48062697/113187625-f7f50100-9250-11eb-825e-91c58f236071.png) - - -### Show Dependency Tree -**Source:** [fetch_crates.rs](crates/ide/src/fetch_crates.rs#13) - -Shows a view tree with all the dependencies of this project - -| Editor | Panel Name | -|---------|------------| -| VS Code | **Rust Dependencies** | - -![Show Dependency Tree](https://user-images.githubusercontent.com/5748995/229394139-2625beab-f4c9-484b-84ed-ad5dee0b1e1a.png) - - -### Show Syntax Tree -**Source:** [view_syntax_tree.rs](crates/ide/src/view_syntax_tree.rs#14) - -Shows a tree view with the syntax tree of the current file - -| Editor | Panel Name | -|---------|-------------| -| VS Code | **Rust Syntax Tree** | - - -### Status -**Source:** [status.rs](crates/ide/src/status.rs#28) - -Shows internal statistic about memory usage of rust-analyzer. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: Status** | - -![Status](https://user-images.githubusercontent.com/48062697/113065584-05f34500-91b1-11eb-98cc-5c196f76be7f.gif) - - -### Structural Search and Replace -**Source:** [lib.rs](crates/ide-ssr/src/lib.rs#6) - -Search and replace with named wildcards that will match any expression, type, path, pattern or item. -The syntax for a structural search replace command is ` ==>> `. -A `$` placeholder in the search pattern will match any AST node and `$` will reference it in the replacement. -Within a macro call, a placeholder will match up until whatever token follows the placeholder. - -All paths in both the search pattern and the replacement template must resolve in the context -in which this command is invoked. Paths in the search pattern will then match the code if they -resolve to the same item, even if they're written differently. For example if we invoke the -command in the module `foo` with a pattern of `Bar`, then code in the parent module that refers -to `foo::Bar` will match. - -Paths in the replacement template will be rendered appropriately for the context in which the -replacement occurs. For example if our replacement template is `foo::Bar` and we match some -code in the `foo` module, we'll insert just `Bar`. - -Inherent method calls should generally be written in UFCS form. e.g. `foo::Bar::baz($s, $a)` will -match `$s.baz($a)`, provided the method call `baz` resolves to the method `foo::Bar::baz`. When a -placeholder is the receiver of a method call in the search pattern (e.g. `$s.foo()`), but not in -the replacement template (e.g. `bar($s)`), then *, & and &mut will be added as needed to mirror -whatever autoderef and autoref was happening implicitly in the matched code. - -The scope of the search / replace will be restricted to the current selection if any, otherwise -it will apply to the whole workspace. - -Placeholders may be given constraints by writing them as `${::...}`. - -Supported constraints: - -| Constraint | Restricts placeholder | -|---------------|------------------------| -| kind(literal) | Is a literal (e.g. `42` or `"forty two"`) | -| not(a) | Negates the constraint `a` | - -Available via the command `rust-analyzer.ssr`. - -```rust -// Using structural search replace command [foo($a, $b) ==>> ($a).foo($b)] - -// BEFORE -String::from(foo(y + 5, z)) - -// AFTER -String::from((y + 5).foo(z)) -``` - -| Editor | Action Name | -|---------|--------------| -| VS Code | **rust-analyzer: Structural Search Replace** | - -Also available as an assist, by writing a comment containing the structural -search and replace rule. You will only see the assist if the comment can -be parsed as a valid structural search and replace rule. - -```rust -// Place the cursor on the line below to see the assist 💡. -// foo($a, $b) ==>> ($a).foo($b) -``` - - -### User Snippet Completions -**Source:** [snippet.rs](crates/ide-completion/src/snippet.rs#5) - -rust-analyzer allows the user to define custom (postfix)-snippets that may depend on items to be accessible for the current scope to be applicable. - -A custom snippet can be defined by adding it to the `rust-analyzer.completion.snippets.custom` object respectively. - -```json -{ - "rust-analyzer.completion.snippets.custom": { - "thread spawn": { - "prefix": ["spawn", "tspawn"], - "body": [ - "thread::spawn(move || {", - "\t$0", - "});", - ], - "description": "Insert a thread::spawn call", - "requires": "std::thread", - "scope": "expr", - } - } -} -``` - -In the example above: - -* `"thread spawn"` is the name of the snippet. - -* `prefix` defines one or more trigger words that will trigger the snippets completion. -Using `postfix` will instead create a postfix snippet. - -* `body` is one or more lines of content joined via newlines for the final output. - -* `description` is an optional description of the snippet, if unset the snippet name will be used. - -* `requires` is an optional list of item paths that have to be resolvable in the current crate where the completion is rendered. - - -### View Crate Graph -**Source:** [view_crate_graph.rs](crates/ide/src/view_crate_graph.rs#8) - -Renders the currently loaded crate graph as an SVG graphic. Requires the `dot` tool, which -is part of graphviz, to be installed. - -Only workspace crates are included, no crates.io dependencies or sysroot crates. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: View Crate Graph** | - - -### View Hir -**Source:** [view_hir.rs](crates/ide/src/view_hir.rs#5) - -| Editor | Action Name | -|---------|--------------| -| VS Code | **rust-analyzer: View Hir** - -![View Hir](https://user-images.githubusercontent.com/48062697/113065588-068bdb80-91b1-11eb-9a78-0b4ef1e972fb.gif) - - -### View Memory Layout -**Source:** [view_memory_layout.rs](crates/ide/src/view_memory_layout.rs#74) - -Displays the recursive memory layout of a datatype. - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: View Memory Layout** | - - -### View Mir -**Source:** [view_mir.rs](crates/ide/src/view_mir.rs#5) - -| Editor | Action Name | -|---------|-------------| -| VS Code | **rust-analyzer: View Mir** - - -### Workspace Symbol -**Source:** [symbol_index.rs](crates/ide-db/src/symbol_index.rs#174) - -Uses fuzzy-search to find types, modules and functions by name across your -project and dependencies. This is **the** most useful feature, which improves code -navigation tremendously. It mostly works on top of the built-in LSP -functionality, however `#` and `*` symbols can be used to narrow down the -search. Specifically, - -- `Foo` searches for `Foo` type in the current workspace -- `foo#` searches for `foo` function in the current workspace -- `Foo*` searches for `Foo` type among dependencies, including `stdlib` -- `foo#*` searches for `foo` function among dependencies - -That is, `#` switches from "types" to all symbols, `*` switches from the current -workspace to dependencies. - -Note that filtering does not currently work in VSCode due to the editor never -sending the special symbols to the language server. Instead, you can configure -the filtering via the `rust-analyzer.workspace.symbol.search.scope` and -`rust-analyzer.workspace.symbol.search.kind` settings. Symbols prefixed -with `__` are hidden from the search results unless configured otherwise. - -| Editor | Shortcut | -|---------|-----------| -| VS Code | Ctrl+T From 3ae6a540d75b0378d0f9c2d9d01c1d64bd10ebb9 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Mon, 10 Mar 2025 12:31:55 +0530 Subject: [PATCH 0096/2248] doc: add doc to proc-macro-api --- .../src/legacy_protocol/json.rs | 2 + .../proc-macro-api/src/legacy_protocol/msg.rs | 44 ++++++++++++++++++- .../crates/proc-macro-api/src/lib.rs | 12 +++++ .../crates/proc-macro-api/src/process.rs | 14 ++++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/json.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/json.rs index ec89f6a9e65d2..8e50ed5a8589d 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/json.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/json.rs @@ -1,6 +1,7 @@ //! Protocol functions for json. use std::io::{self, BufRead, Write}; +/// Reads a JSON message from the input stream. pub fn read_json<'a>( inp: &mut impl BufRead, buf: &'a mut String, @@ -26,6 +27,7 @@ pub fn read_json<'a>( } } +/// Writes a JSON message to the output stream. pub fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> { tracing::debug!("> {}", msg); out.write_all(msg.as_bytes())?; diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs index 4b831e4acebb9..968150c12b59a 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -20,69 +20,103 @@ pub const VERSION_CHECK_VERSION: u32 = 1; pub const ENCODE_CLOSE_SPAN_VERSION: u32 = 2; pub const HAS_GLOBAL_SPANS: u32 = 3; pub const RUST_ANALYZER_SPAN_SUPPORT: u32 = 4; -/// Whether literals encode their kind as an additional u32 field and idents their rawness as a u32 field +/// Whether literals encode their kind as an additional u32 field and idents their rawness as a u32 field. pub const EXTENDED_LEAF_DATA: u32 = 5; +/// Current API version of the proc-macro protocol. pub const CURRENT_API_VERSION: u32 = EXTENDED_LEAF_DATA; +/// Represents requests sent from the client to the proc-macro-srv. #[derive(Debug, Serialize, Deserialize)] pub enum Request { + /// Retrieves a list of macros from a given dynamic library. /// Since [`NO_VERSION_CHECK_VERSION`] ListMacros { dylib_path: Utf8PathBuf }, + + /// Expands a procedural macro. /// Since [`NO_VERSION_CHECK_VERSION`] ExpandMacro(Box), + + /// Performs an API version check between the client and the server. /// Since [`VERSION_CHECK_VERSION`] ApiVersionCheck {}, + + /// Sets server-specific configurations. /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] SetConfig(ServerConfig), } +/// Defines the mode used for handling span data. #[derive(Copy, Clone, Default, Debug, Serialize, Deserialize)] pub enum SpanMode { + /// Default mode, where spans are identified by an ID. #[default] Id, + + /// Rust Analyzer-specific span handling mode. RustAnalyzer, } +/// Represents responses sent from the proc-macro-srv to the client. #[derive(Debug, Serialize, Deserialize)] pub enum Response { + /// Returns a list of available macros in a dynamic library. /// Since [`NO_VERSION_CHECK_VERSION`] ListMacros(Result, String>), + + /// Returns result of a macro expansion. /// Since [`NO_VERSION_CHECK_VERSION`] ExpandMacro(Result), + + /// Returns the API version supported by the server. /// Since [`NO_VERSION_CHECK_VERSION`] ApiVersionCheck(u32), + + /// Confirms the application of a configuration update. /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] SetConfig(ServerConfig), + + /// Returns the result of a macro expansion, including extended span data. /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] ExpandMacroExtended(Result), } +/// Configuration settings for the proc-macro-srv. #[derive(Debug, Serialize, Deserialize, Default)] #[serde(default)] pub struct ServerConfig { + /// Defines how span data should be handled. pub span_mode: SpanMode, } +/// Represents an extended macro expansion response, including span data mappings. #[derive(Debug, Serialize, Deserialize)] pub struct ExpandMacroExtended { + /// The expanded syntax tree. pub tree: FlatTree, + /// Additional span data mappings. pub span_data_table: Vec, } +/// Represents an error message when a macro expansion results in a panic. #[derive(Debug, Serialize, Deserialize)] pub struct PanicMessage(pub String); +/// Represents a macro expansion request sent from the client. #[derive(Debug, Serialize, Deserialize)] pub struct ExpandMacro { + /// The path to the dynamic library containing the macro. pub lib: Utf8PathBuf, /// Environment variables to set during macro expansion. pub env: Vec<(String, String)>, + /// The current working directory for the macro expansion. pub current_dir: Option, + /// Macro expansion data, including the macro body, name and attributes. #[serde(flatten)] pub data: ExpandMacroData, } +/// Represents the input data required for expanding a macro. #[derive(Debug, Serialize, Deserialize)] pub struct ExpandMacroData { /// Argument of macro call. @@ -103,18 +137,24 @@ pub struct ExpandMacroData { #[serde(skip_serializing_if = "ExpnGlobals::skip_serializing_if")] #[serde(default)] pub has_global_spans: ExpnGlobals, + /// Table of additional span data. #[serde(skip_serializing_if = "Vec::is_empty")] #[serde(default)] pub span_data_table: Vec, } +/// Represents global expansion settings, including span resolution. #[derive(Copy, Clone, Default, Debug, Serialize, Deserialize)] pub struct ExpnGlobals { + /// Determines whether to serialize the expansion settings. #[serde(skip_serializing)] #[serde(default)] pub serialize: bool, + /// Defines the `def_site` span location. pub def_site: usize, + /// Defines the `call_site` span location. pub call_site: usize, + /// Defines the `mixed_site` span location. pub mixed_site: usize, } @@ -150,9 +190,11 @@ pub trait Message: serde::Serialize + DeserializeOwned { impl Message for Request {} impl Message for Response {} +/// Type alias for a function that reads protocol messages from a buffered input stream. #[allow(type_alias_bounds)] type ProtocolRead = for<'i, 'buf> fn(inp: &'i mut R, buf: &'buf mut String) -> io::Result>; +/// Type alias for a function that writes protocol messages to an output stream. #[allow(type_alias_bounds)] type ProtocolWrite = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str) -> io::Result<()>; diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs index dc3328ebcda48..7061f7ea474c7 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs @@ -24,9 +24,12 @@ use crate::{ process::ProcMacroServerProcess, }; +/// Represents different kinds of procedural macros that can be expanded by the external server. #[derive(Copy, Clone, Eq, PartialEq, Debug, serde_derive::Serialize, serde_derive::Deserialize)] pub enum ProcMacroKind { + /// A macro that derives implementations for a struct or enum. CustomDerive, + /// An attribute-like procedural macro. Attr, // This used to be called FuncLike, so that's what the server expects currently. #[serde(alias = "Bang")] @@ -46,11 +49,13 @@ pub struct ProcMacroClient { path: AbsPathBuf, } +/// Represents a dynamically loaded library containing procedural macros. pub struct MacroDylib { path: AbsPathBuf, } impl MacroDylib { + /// Creates a new MacroDylib instance with the given path. pub fn new(path: AbsPathBuf) -> MacroDylib { MacroDylib { path } } @@ -78,6 +83,7 @@ impl PartialEq for ProcMacro { } } +/// Represents errors encountered when communicating with the proc-macro server. #[derive(Clone, Debug)] pub struct ServerError { pub message: String, @@ -106,6 +112,7 @@ impl ProcMacroClient { Ok(ProcMacroClient { process: Arc::new(process), path: process_path.to_owned() }) } + /// Returns the absolute path to the proc-macro server. pub fn server_path(&self) -> &AbsPath { &self.path } @@ -130,20 +137,25 @@ impl ProcMacroClient { } } + /// Checks if the proc-macro server has exited. pub fn exited(&self) -> Option<&ServerError> { self.process.exited() } } impl ProcMacro { + /// Returns the name of the procedural macro. pub fn name(&self) -> &str { &self.name } + /// Returns the type of procedural macro. pub fn kind(&self) -> ProcMacroKind { self.kind } + /// Expands the procedural macro by sending an expansion request to the server. + /// This includes span information and environmental context. pub fn expand( &self, subtree: tt::SubtreeView<'_, Span>, diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs index d998b23d3bbef..d8ae2df7faa94 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs @@ -21,6 +21,7 @@ use crate::{ ProcMacroKind, ServerError, }; +/// Represents a process handling proc-macro communication. #[derive(Debug)] pub(crate) struct ProcMacroServerProcess { /// The state of the proc-macro server process, the protocol is currently strictly sequential @@ -32,6 +33,7 @@ pub(crate) struct ProcMacroServerProcess { exited: OnceLock>, } +/// Maintains the state of the proc-macro server process. #[derive(Debug)] struct ProcessSrvState { process: Process, @@ -40,6 +42,7 @@ struct ProcessSrvState { } impl ProcMacroServerProcess { + /// Starts the proc-macro server and performs a version check pub(crate) fn run( process_path: &AbsPath, env: impl IntoIterator, impl AsRef)> @@ -85,14 +88,17 @@ impl ProcMacroServerProcess { } } + /// Returns the server error if the process has exited. pub(crate) fn exited(&self) -> Option<&ServerError> { self.exited.get().map(|it| &it.0) } + /// Retrieves the API version of the proc-macro server. pub(crate) fn version(&self) -> u32 { self.version } + /// Checks the API version of the running proc-macro server. fn version_check(&self) -> Result { let request = Request::ApiVersionCheck {}; let response = self.send_task(request)?; @@ -103,6 +109,7 @@ impl ProcMacroServerProcess { } } + /// Enable support for rust-analyzer span mode if the server supports it. fn enable_rust_analyzer_spans(&self) -> Result { let request = Request::SetConfig(ServerConfig { span_mode: SpanMode::RustAnalyzer }); let response = self.send_task(request)?; @@ -113,6 +120,7 @@ impl ProcMacroServerProcess { } } + /// Finds proc-macros in a given dynamic library. pub(crate) fn find_proc_macros( &self, dylib_path: &AbsPath, @@ -127,6 +135,7 @@ impl ProcMacroServerProcess { } } + /// Sends a request to the proc-macro server and waits for a response. pub(crate) fn send_task(&self, req: Request) -> Result { if let Some(server_error) = self.exited.get() { return Err(server_error.0.clone()); @@ -177,12 +186,14 @@ impl ProcMacroServerProcess { } } +/// Manages the execution of the proc-macro server process. #[derive(Debug)] struct Process { child: JodChild, } impl Process { + /// Runs a new proc-macro server process with the specified environment variables. fn run( path: &AbsPath, env: impl IntoIterator, impl AsRef)>, @@ -191,6 +202,7 @@ impl Process { Ok(Process { child }) } + /// Retrieves stdin and stdout handles for the process. fn stdio(&mut self) -> Option<(ChildStdin, BufReader)> { let stdin = self.child.stdin.take()?; let stdout = self.child.stdout.take()?; @@ -200,6 +212,7 @@ impl Process { } } +/// Creates and configures a new child process for the proc-macro server. fn mk_child( path: &AbsPath, env: impl IntoIterator, impl AsRef)>, @@ -221,6 +234,7 @@ fn mk_child( cmd.spawn() } +/// Sends a request to the server and reads the response. fn send_request( mut writer: &mut impl Write, mut reader: &mut impl BufRead, From 02ac23a7d6e4a5d9832a720c3f7ffe211091ef17 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Thu, 6 Mar 2025 16:00:08 -0500 Subject: [PATCH 0097/2248] internal: vendor `query-group-macro` --- src/tools/rust-analyzer/Cargo.lock | 365 ++++++++++++++- .../crates/query-group-macro/Cargo.toml | 23 + .../crates/query-group-macro/src/lib.rs | 437 ++++++++++++++++++ .../crates/query-group-macro/src/queries.rs | 329 +++++++++++++ .../crates/query-group-macro/tests/arity.rs | 28 ++ .../crates/query-group-macro/tests/cycle.rs | 275 +++++++++++ .../query-group-macro/tests/hello_world.rs | 125 +++++ .../query-group-macro/tests/interned.rs | 52 +++ .../query-group-macro/tests/logger_db.rs | 60 +++ .../crates/query-group-macro/tests/lru.rs | 67 +++ .../query-group-macro/tests/multiple_dbs.rs | 23 + .../query-group-macro/tests/old_and_new.rs | 115 +++++ .../crates/query-group-macro/tests/result.rs | 50 ++ .../query-group-macro/tests/supertrait.rs | 19 + .../crates/query-group-macro/tests/tuples.rs | 38 ++ .../ra-salsa/ra-salsa-macros/Cargo.toml | 2 +- src/tools/rust-analyzer/xtask/src/tidy.rs | 1 + 17 files changed, 1988 insertions(+), 21 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/tests/arity.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/tests/cycle.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/tests/hello_world.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/tests/lru.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/tests/multiple_dbs.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/tests/result.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs create mode 100644 src/tools/rust-analyzer/crates/query-group-macro/tests/tuples.rs diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index c57953ba65476..7b83a859792e7 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -17,6 +17,21 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "always-assert" version = "0.2.0" @@ -71,7 +86,7 @@ dependencies = [ "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lz4_flex", "rustc-hash 2.0.0", - "salsa", + "salsa 0.0.0", "semver", "span", "stdx", @@ -108,6 +123,15 @@ dependencies = [ "cfg_aliases 0.2.1", ] +[[package]] +name = "boxcar" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225450ee9328e1e828319b48a89726cffc1b0ad26fd9211ad435de9fa376acae" +dependencies = [ + "loom", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -289,6 +313,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -312,7 +345,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -449,6 +496,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -473,6 +526,19 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a" +[[package]] +name = "generator" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd" +dependencies = [ + "cfg-if", + "libc", + "log", + "rustversion", + "windows 0.58.0", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -496,11 +562,31 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.2", +] + [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" @@ -545,12 +631,12 @@ dependencies = [ "bitflags 2.7.0", "cfg", "cov-mark", - "dashmap", + "dashmap 5.5.3", "drop_bomb", "either", "expect-test", "fst", - "hashbrown", + "hashbrown 0.14.5", "hir-expand", "indexmap", "intern", @@ -584,7 +670,7 @@ dependencies = [ "cov-mark", "either", "expect-test", - "hashbrown", + "hashbrown 0.14.5", "intern", "itertools", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -811,7 +897,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -838,8 +924,8 @@ dependencies = [ name = "intern" version = "0.0.0" dependencies = [ - "dashmap", - "hashbrown", + "dashmap 5.5.3", + "hashbrown 0.14.5", "rustc-hash 2.0.0", "triomphe", ] @@ -999,6 +1085,19 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + [[package]] name = "lsp-server" version = "0.7.7" @@ -1043,6 +1142,15 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "mbe" version = "0.0.0" @@ -1170,6 +1278,16 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.50.1" @@ -1240,6 +1358,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking_lot" version = "0.12.3" @@ -1329,6 +1453,12 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +[[package]] +name = "portable-atomic" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + [[package]] name = "powerfmt" version = "0.2.0" @@ -1414,7 +1544,7 @@ dependencies = [ "indexmap", "nix", "tracing", - "windows", + "windows 0.56.0", ] [[package]] @@ -1493,6 +1623,18 @@ dependencies = [ "pulldown-cmark", ] +[[package]] +name = "query-group-macro" +version = "0.0.0" +dependencies = [ + "expect-test", + "heck", + "proc-macro2", + "quote", + "salsa 0.19.0", + "syn", +] + [[package]] name = "quote" version = "1.0.36" @@ -1648,6 +1790,50 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "rowan" version = "0.15.15" @@ -1655,7 +1841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a58fa8a7ccff2aec4f39cc45bf5f985cec7125ab271cf681c279fd00192b49" dependencies = [ "countme", - "hashbrown", + "hashbrown 0.14.5", "memoffset", "rustc-hash 1.1.0", "text-size", @@ -1760,6 +1946,12 @@ dependencies = [ "smallvec", ] +[[package]] +name = "rustversion" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" + [[package]] name = "ryu" version = "1.0.18" @@ -1780,12 +1972,40 @@ dependencies = [ "parking_lot", "rand", "rustc-hash 2.0.0", - "salsa-macros", + "salsa-macros 0.0.0", "smallvec", "tracing", "triomphe", ] +[[package]] +name = "salsa" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd55c6549513b2a42884dae31e3d4f4ac8a6cc51062e68e24d162133889f327c" +dependencies = [ + "boxcar", + "crossbeam-queue", + "dashmap 6.1.0", + "hashbrown 0.15.2", + "hashlink", + "indexmap", + "parking_lot", + "portable-atomic", + "rayon", + "rustc-hash 2.0.0", + "salsa-macro-rules", + "salsa-macros 0.19.0", + "smallvec", + "tracing", +] + +[[package]] +name = "salsa-macro-rules" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2619b4b451beab0a7e4364ff1e6f31950e7e418888fd9bf2f28889671563166a" + [[package]] name = "salsa-macros" version = "0.0.0" @@ -1796,6 +2016,19 @@ dependencies = [ "syn", ] +[[package]] +name = "salsa-macros" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be57a99b3896e8d26850428a6874fb86849e2db874e1db3528e5cee4337d277" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "same-file" version = "1.0.6" @@ -1923,10 +2156,10 @@ dependencies = [ name = "span" version = "0.0.0" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 2.0.0", - "salsa", + "salsa 0.0.0", "stdx", "syntax", "text-size", @@ -2246,9 +2479,15 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "matchers", + "nu-ansi-term 0.46.0", + "once_cell", + "regex", "sharded-slab", + "smallvec", "thread_local", "time", + "tracing", "tracing-core", "tracing-log", ] @@ -2259,7 +2498,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b56c62d2c80033cb36fae448730a2f2ef99410fe3ecbffc916681a32f6807dbe" dependencies = [ - "nu-ansi-term", + "nu-ansi-term 0.50.1", "tracing-core", "tracing-log", "tracing-subscriber", @@ -2405,6 +2644,22 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" @@ -2414,13 +2669,29 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows" version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" dependencies = [ - "windows-core", + "windows-core 0.56.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", "windows-targets 0.52.6", ] @@ -2430,9 +2701,22 @@ version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" dependencies = [ - "windows-implement", - "windows-interface", - "windows-result", + "windows-implement 0.56.0", + "windows-interface 0.56.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings", "windows-targets 0.52.6", ] @@ -2447,6 +2731,17 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-interface" version = "0.56.0" @@ -2458,6 +2753,17 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-result" version = "0.1.2" @@ -2467,6 +2773,25 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml new file mode 100644 index 0000000000000..24e059f40bee5 --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "query-group-macro" +version = "0.0.0" +repository.workspace = true +description = "A macro mimicking the `#[salsa::query_group]` macro for migrating to new Salsa" + +authors.workspace = true +edition.workspace = true +license.workspace = true +rust-version.workspace = true + +[lib] +proc-macro = true + +[dependencies] +heck = "0.5.0" +proc-macro2 = "1.0" +quote = "1.0" +syn = { version = "2.0", features = ["full", "extra-traits"] } +salsa = { version = "0.19.0" } + +[dev-dependencies] +expect-test = "1.5.0" diff --git a/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs b/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs new file mode 100644 index 0000000000000..af49081db5bd6 --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs @@ -0,0 +1,437 @@ +//! A macro that mimics the old Salsa-style `#[query_group]` macro. + +use core::fmt; +use std::vec; + +use proc_macro::TokenStream; +use proc_macro2::Span; +use queries::{ + GeneratedInputStruct, InputQuery, InputSetter, InputSetterWithDurability, Intern, Lookup, + Queries, SetterKind, TrackedQuery, Transparent, +}; +use quote::{format_ident, quote, ToTokens}; +use syn::spanned::Spanned; +use syn::visit_mut::VisitMut; +use syn::{parse_quote, Attribute, FnArg, ItemTrait, Path, TraitItem, TraitItemFn}; + +mod queries; + +#[proc_macro_attribute] +pub fn query_group(args: TokenStream, input: TokenStream) -> TokenStream { + match query_group_impl(args, input.clone()) { + Ok(tokens) => tokens, + Err(e) => token_stream_with_error(input, e), + } +} + +#[derive(Debug)] +struct InputStructField { + name: proc_macro2::TokenStream, + ty: proc_macro2::TokenStream, +} + +impl fmt::Display for InputStructField { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.name) + } +} + +struct SalsaAttr { + name: String, + tts: TokenStream, + span: Span, +} + +impl std::fmt::Debug for SalsaAttr { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(fmt, "{:?}", self.name) + } +} + +impl TryFrom for SalsaAttr { + type Error = syn::Attribute; + + fn try_from(attr: syn::Attribute) -> Result { + if is_not_salsa_attr_path(attr.path()) { + return Err(attr); + } + + let span = attr.span(); + + let name = attr.path().segments[1].ident.to_string(); + let tts = match attr.meta { + syn::Meta::Path(path) => path.into_token_stream(), + syn::Meta::List(ref list) => { + let tts = list + .into_token_stream() + .into_iter() + .skip(attr.path().to_token_stream().into_iter().count()); + proc_macro2::TokenStream::from_iter(tts) + } + syn::Meta::NameValue(nv) => nv.into_token_stream(), + } + .into(); + + Ok(SalsaAttr { name, tts, span }) + } +} + +fn is_not_salsa_attr_path(path: &syn::Path) -> bool { + path.segments.first().map(|s| s.ident != "salsa").unwrap_or(true) || path.segments.len() != 2 +} + +fn filter_attrs(attrs: Vec) -> (Vec, Vec) { + let mut other = vec![]; + let mut salsa = vec![]; + // Leave non-salsa attributes untouched. These are + // attributes that don't start with `salsa::` or don't have + // exactly two segments in their path. + for attr in attrs { + match SalsaAttr::try_from(attr) { + Ok(it) => salsa.push(it), + Err(it) => other.push(it), + } + } + (other, salsa) +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum QueryKind { + Input, + Tracked, + TrackedWithSalsaStruct, + Transparent, + Interned, +} + +pub(crate) fn query_group_impl( + _args: proc_macro::TokenStream, + input: proc_macro::TokenStream, +) -> Result { + let mut item_trait = syn::parse::(input)?; + + let supertraits = &item_trait.supertraits; + + let db_attr: Attribute = parse_quote! { + #[salsa::db] + }; + item_trait.attrs.push(db_attr); + + let trait_name_ident = &item_trait.ident.clone(); + let input_struct_name = format_ident!("{}Data", trait_name_ident); + let create_data_ident = format_ident!("create_data_{}", trait_name_ident); + + let mut input_struct_fields: Vec = vec![]; + let mut trait_methods = vec![]; + let mut setter_trait_methods = vec![]; + let mut lookup_signatures = vec![]; + let mut lookup_methods = vec![]; + + for item in item_trait.clone().items { + if let syn::TraitItem::Fn(method) = item { + let method_name = &method.sig.ident; + let signature = &method.sig.clone(); + + let (_attrs, salsa_attrs) = filter_attrs(method.attrs); + + let mut query_kind = QueryKind::Tracked; + let mut invoke = None; + let mut cycle = None; + let mut interned_struct_path = None; + let mut lru = None; + + let params: Vec = signature.inputs.clone().into_iter().collect(); + let pat_and_tys = params + .into_iter() + .filter(|fn_arg| matches!(fn_arg, FnArg::Typed(_))) + .map(|fn_arg| match fn_arg { + FnArg::Typed(pat_type) => pat_type.clone(), + FnArg::Receiver(_) => unreachable!("this should have been filtered out"), + }) + .collect::>(); + + for SalsaAttr { name, tts, span } in salsa_attrs { + match name.as_str() { + "cycle" => { + let path = syn::parse::>(tts)?; + cycle = Some(path.0.clone()) + } + "input" => { + if !pat_and_tys.is_empty() { + return Err(syn::Error::new( + span, + "input methods cannot have a parameter", + )); + } + query_kind = QueryKind::Input; + } + "interned" => { + let syn::ReturnType::Type(_, ty) = &signature.output else { + return Err(syn::Error::new( + span, + "interned queries must have return type", + )); + }; + let syn::Type::Path(path) = &**ty else { + return Err(syn::Error::new( + span, + "interned queries must have return type", + )); + }; + interned_struct_path = Some(path.path.clone()); + query_kind = QueryKind::Interned; + } + "invoke" => { + let path = syn::parse::>(tts)?; + invoke = Some(path.0.clone()); + } + "invoke_actual" => { + let path = syn::parse::>(tts)?; + invoke = Some(path.0.clone()); + query_kind = QueryKind::TrackedWithSalsaStruct; + } + "lru" => { + let lru_count = syn::parse::>(tts)?; + let lru_count = lru_count.0.base10_parse::()?; + + lru = Some(lru_count); + } + "transparent" => { + query_kind = QueryKind::Transparent; + } + _ => return Err(syn::Error::new(span, format!("unknown attribute `{name}`"))), + } + } + + let syn::ReturnType::Type(_, return_ty) = signature.output.clone() else { + return Err(syn::Error::new(signature.span(), "Queries must have a return type")); + }; + + if let syn::Type::Path(ref ty_path) = *return_ty { + if matches!(query_kind, QueryKind::Input) { + let field = InputStructField { + name: method_name.to_token_stream(), + ty: ty_path.path.to_token_stream(), + }; + + input_struct_fields.push(field); + } + } + + match (query_kind, invoke) { + // input + (QueryKind::Input, None) => { + let query = InputQuery { + signature: method.sig.clone(), + create_data_ident: create_data_ident.clone(), + }; + let value = Queries::InputQuery(query); + trait_methods.push(value); + + let setter = InputSetter { + signature: method.sig.clone(), + return_type: *return_ty.clone(), + create_data_ident: create_data_ident.clone(), + }; + setter_trait_methods.push(SetterKind::Plain(setter)); + + let setter = InputSetterWithDurability { + signature: method.sig.clone(), + return_type: *return_ty.clone(), + create_data_ident: create_data_ident.clone(), + }; + setter_trait_methods.push(SetterKind::WithDurability(setter)); + } + (QueryKind::Interned, None) => { + let interned_struct_path = interned_struct_path.unwrap(); + let method = Intern { + signature: signature.clone(), + pat_and_tys: pat_and_tys.clone(), + interned_struct_path: interned_struct_path.clone(), + }; + + trait_methods.push(Queries::Intern(method)); + + let mut method = Lookup { + signature: signature.clone(), + pat_and_tys: pat_and_tys.clone(), + return_ty: *return_ty, + interned_struct_path, + }; + method.prepare_signature(); + + lookup_signatures + .push(TraitItem::Fn(make_trait_method(method.signature.clone()))); + lookup_methods.push(method); + } + // tracked function. it might have an invoke, or might not. + (QueryKind::Tracked, invoke) => { + let method = TrackedQuery { + trait_name: trait_name_ident.clone(), + generated_struct: Some(GeneratedInputStruct { + input_struct_name: input_struct_name.clone(), + create_data_ident: create_data_ident.clone(), + }), + signature: signature.clone(), + pat_and_tys: pat_and_tys.clone(), + invoke, + cycle, + lru, + }; + + trait_methods.push(Queries::TrackedQuery(method)); + } + (QueryKind::TrackedWithSalsaStruct, Some(invoke)) => { + let method = TrackedQuery { + trait_name: trait_name_ident.clone(), + generated_struct: None, + signature: signature.clone(), + pat_and_tys: pat_and_tys.clone(), + invoke: Some(invoke), + cycle, + lru, + }; + + trait_methods.push(Queries::TrackedQuery(method)) + } + // while it is possible to make this reachable, it's not really worthwhile for a migration aid. + // doing this would require attaching an attribute to the salsa struct parameter in the query. + (QueryKind::TrackedWithSalsaStruct, None) => unreachable!(), + (QueryKind::Transparent, invoke) => { + let method = Transparent { + signature: method.sig.clone(), + pat_and_tys: pat_and_tys.clone(), + invoke, + }; + trait_methods.push(Queries::Transparent(method)); + } + // error/invalid constructions + (QueryKind::Interned, Some(path)) => { + return Err(syn::Error::new( + path.span(), + "Interned queries cannot be used with an `#[invoke]`".to_string(), + )) + } + (QueryKind::Input, Some(path)) => { + return Err(syn::Error::new( + path.span(), + "Inputs cannot be used with an `#[invoke]`".to_string(), + )) + } + } + } + } + + let fields = input_struct_fields + .into_iter() + .map(|input| { + let name = input.name; + let ret = input.ty; + quote! { #name: Option<#ret> } + }) + .collect::>(); + + let input_struct = quote! { + #[salsa::input] + pub(crate) struct #input_struct_name { + #(#fields),* + } + }; + + let field_params = std::iter::repeat_n(quote! { None }, fields.len()) + .collect::>(); + + let create_data_method = quote! { + #[allow(non_snake_case)] + #[salsa::tracked] + fn #create_data_ident(db: &dyn #trait_name_ident) -> #input_struct_name { + #input_struct_name::new(db, #(#field_params),*) + } + }; + + let mut setter_signatures = vec![]; + let mut setter_methods = vec![]; + for trait_item in setter_trait_methods + .iter() + .map(|method| method.to_token_stream()) + .map(|tokens| syn::parse2::(tokens).unwrap()) + { + let mut methods_sans_body = trait_item.clone(); + methods_sans_body.default = None; + methods_sans_body.semi_token = Some(syn::Token![;](trait_item.span())); + + setter_signatures.push(TraitItem::Fn(methods_sans_body)); + setter_methods.push(TraitItem::Fn(trait_item)); + } + + item_trait.items.append(&mut setter_signatures); + item_trait.items.append(&mut lookup_signatures); + + let trait_impl = quote! { + #[salsa::db] + impl #trait_name_ident for DB + where + DB: #supertraits, + { + #(#trait_methods)* + + #(#setter_methods)* + + #(#lookup_methods)* + } + }; + RemoveAttrsFromTraitMethods.visit_item_trait_mut(&mut item_trait); + + let out = quote! { + #item_trait + + #trait_impl + + #input_struct + + #create_data_method + } + .into(); + + Ok(out) +} + +/// Parenthesis helper +pub(crate) struct Parenthesized(pub(crate) T); + +impl syn::parse::Parse for Parenthesized +where + T: syn::parse::Parse, +{ + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { + let content; + syn::parenthesized!(content in input); + content.parse::().map(Parenthesized) + } +} + +fn make_trait_method(sig: syn::Signature) -> TraitItemFn { + TraitItemFn { + attrs: vec![], + sig: sig.clone(), + semi_token: Some(syn::Token![;](sig.span())), + default: None, + } +} + +struct RemoveAttrsFromTraitMethods; + +impl VisitMut for RemoveAttrsFromTraitMethods { + fn visit_item_trait_mut(&mut self, i: &mut syn::ItemTrait) { + for item in &mut i.items { + if let TraitItem::Fn(trait_item_fn) = item { + trait_item_fn.attrs = vec![]; + } + } + } +} + +pub(crate) fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenStream { + tokens.extend(TokenStream::from(error.into_compile_error())); + tokens +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs b/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs new file mode 100644 index 0000000000000..8c6bb8a0a729c --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs @@ -0,0 +1,329 @@ +//! The IR of the `#[query_group]` macro. + +use quote::{format_ident, quote, ToTokens}; +use syn::{parse_quote, FnArg, Ident, PatType, Path, Receiver, ReturnType, Type}; + +pub(crate) struct TrackedQuery { + pub(crate) trait_name: Ident, + pub(crate) signature: syn::Signature, + pub(crate) pat_and_tys: Vec, + pub(crate) invoke: Option, + pub(crate) cycle: Option, + pub(crate) lru: Option, + pub(crate) generated_struct: Option, +} + +pub(crate) struct GeneratedInputStruct { + pub(crate) input_struct_name: Ident, + pub(crate) create_data_ident: Ident, +} + +impl ToTokens for TrackedQuery { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let sig = &self.signature; + let trait_name = &self.trait_name; + + let ret = &sig.output; + + let invoke = match &self.invoke { + Some(path) => path.to_token_stream(), + None => sig.ident.to_token_stream(), + }; + + let fn_ident = &sig.ident; + let shim: Ident = format_ident!("{}_shim", fn_ident); + + let annotation = match (self.cycle.clone(), self.lru) { + (Some(cycle), Some(lru)) => quote!(#[salsa::tracked(lru = #lru, recovery_fn = #cycle)]), + (Some(cycle), None) => quote!(#[salsa::tracked(recovery_fn = #cycle)]), + (None, Some(lru)) => quote!(#[salsa::tracked(lru = #lru)]), + (None, None) => quote!(#[salsa::tracked]), + }; + + let pat_and_tys = &self.pat_and_tys; + let params = self + .pat_and_tys + .iter() + .map(|pat_type| pat_type.pat.clone()) + .collect::>>(); + + let method = match &self.generated_struct { + Some(generated_struct) => { + let input_struct_name = &generated_struct.input_struct_name; + let create_data_ident = &generated_struct.create_data_ident; + + quote! { + #sig { + #annotation + fn #shim( + db: &dyn #trait_name, + _input: #input_struct_name, + #(#pat_and_tys),* + ) #ret { + #invoke(db, #(#params),*) + } + #shim(self, #create_data_ident(self), #(#params),*) + } + } + } + None => { + quote! { + #sig { + #annotation + fn #shim( + db: &dyn #trait_name, + #(#pat_and_tys),* + ) #ret { + #invoke(db, #(#params),*) + } + #shim(self, #(#params),*) + } + } + } + }; + + method.to_tokens(tokens); + } +} + +pub(crate) struct InputQuery { + pub(crate) signature: syn::Signature, + pub(crate) create_data_ident: Ident, +} + +impl ToTokens for InputQuery { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let sig = &self.signature; + let fn_ident = &sig.ident; + let create_data_ident = &self.create_data_ident; + + let method = quote! { + #sig { + let data = #create_data_ident(self); + data.#fn_ident(self).unwrap() + } + }; + method.to_tokens(tokens); + } +} + +pub(crate) struct InputSetter { + pub(crate) signature: syn::Signature, + pub(crate) return_type: syn::Type, + pub(crate) create_data_ident: Ident, +} + +impl ToTokens for InputSetter { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let sig = &mut self.signature.clone(); + + let ty = &self.return_type; + let fn_ident = &sig.ident; + let create_data_ident = &self.create_data_ident; + + let setter_ident = format_ident!("set_{}", fn_ident); + sig.ident = setter_ident.clone(); + + let value_argument: PatType = parse_quote!(__value: #ty); + sig.inputs.push(FnArg::Typed(value_argument.clone())); + + // make `&self` `&mut self` instead. + let mut_receiver: Receiver = parse_quote!(&mut self); + if let Some(og) = sig.inputs.first_mut() { + *og = FnArg::Receiver(mut_receiver) + } + + // remove the return value. + sig.output = ReturnType::Default; + + let value = &value_argument.pat; + let method = quote! { + #sig { + use salsa::Setter; + let data = #create_data_ident(self); + data.#setter_ident(self).to(Some(#value)); + } + }; + method.to_tokens(tokens); + } +} + +pub(crate) struct InputSetterWithDurability { + pub(crate) signature: syn::Signature, + pub(crate) return_type: syn::Type, + pub(crate) create_data_ident: Ident, +} + +impl ToTokens for InputSetterWithDurability { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let sig = &mut self.signature.clone(); + + let ty = &self.return_type; + let fn_ident = &sig.ident; + let setter_ident = format_ident!("set_{}", fn_ident); + + let create_data_ident = &self.create_data_ident; + + sig.ident = format_ident!("set_{}_with_durability", fn_ident); + + let value_argument: PatType = parse_quote!(__value: #ty); + sig.inputs.push(FnArg::Typed(value_argument.clone())); + + let durability_argument: PatType = parse_quote!(durability: salsa::Durability); + sig.inputs.push(FnArg::Typed(durability_argument.clone())); + + // make `&self` `&mut self` instead. + let mut_receiver: Receiver = parse_quote!(&mut self); + if let Some(og) = sig.inputs.first_mut() { + *og = FnArg::Receiver(mut_receiver) + } + + // remove the return value. + sig.output = ReturnType::Default; + + let value = &value_argument.pat; + let durability = &durability_argument.pat; + let method = quote! { + #sig { + use salsa::Setter; + let data = #create_data_ident(self); + data.#setter_ident(self) + .with_durability(#durability) + .to(Some(#value)); + } + }; + method.to_tokens(tokens); + } +} + +pub(crate) enum SetterKind { + Plain(InputSetter), + WithDurability(InputSetterWithDurability), +} + +impl ToTokens for SetterKind { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + match self { + SetterKind::Plain(input_setter) => input_setter.to_tokens(tokens), + SetterKind::WithDurability(input_setter_with_durability) => { + input_setter_with_durability.to_tokens(tokens) + } + } + } +} + +pub(crate) struct Transparent { + pub(crate) signature: syn::Signature, + pub(crate) pat_and_tys: Vec, + pub(crate) invoke: Option, +} + +impl ToTokens for Transparent { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let sig = &self.signature; + + let ty = self + .pat_and_tys + .iter() + .map(|pat_type| pat_type.pat.clone()) + .collect::>>(); + + let invoke = match &self.invoke { + Some(path) => path.to_token_stream(), + None => sig.ident.to_token_stream(), + }; + + let method = quote! { + #sig { + #invoke(self, #(#ty),*) + } + }; + + method.to_tokens(tokens); + } +} +pub(crate) struct Intern { + pub(crate) signature: syn::Signature, + pub(crate) pat_and_tys: Vec, + pub(crate) interned_struct_path: Path, +} + +impl ToTokens for Intern { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let sig = &self.signature; + + let ty = self.pat_and_tys.to_vec(); + + let interned_pat = ty.first().expect("at least one pat; this is a bug"); + let interned_pat = &interned_pat.pat; + + let wrapper_struct = self.interned_struct_path.to_token_stream(); + + let method = quote! { + #sig { + #wrapper_struct::new(self, #interned_pat) + } + }; + + method.to_tokens(tokens); + } +} + +pub(crate) struct Lookup { + pub(crate) signature: syn::Signature, + pub(crate) pat_and_tys: Vec, + pub(crate) return_ty: Type, + pub(crate) interned_struct_path: Path, +} + +impl Lookup { + pub(crate) fn prepare_signature(&mut self) { + let sig = &self.signature; + + let ident = format_ident!("lookup_{}", sig.ident); + + let ty = self.pat_and_tys.to_vec(); + + let interned_key = &self.return_ty; + + let interned_pat = ty.first().expect("at least one pat; this is a bug"); + let interned_return_ty = &interned_pat.ty; + + self.signature = parse_quote!( + fn #ident(&self, id: #interned_key) -> #interned_return_ty + ); + } +} + +impl ToTokens for Lookup { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let sig = &self.signature; + + let wrapper_struct = self.interned_struct_path.to_token_stream(); + let method = quote! { + #sig { + #wrapper_struct::ingredient(self).data(self.as_dyn_database(), id.as_id()).0.clone() + } + }; + + method.to_tokens(tokens); + } +} + +pub(crate) enum Queries { + TrackedQuery(TrackedQuery), + InputQuery(InputQuery), + Intern(Intern), + Transparent(Transparent), +} + +impl ToTokens for Queries { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + match self { + Queries::TrackedQuery(tracked_query) => tracked_query.to_tokens(tokens), + Queries::InputQuery(input_query) => input_query.to_tokens(tokens), + Queries::Transparent(transparent) => transparent.to_tokens(tokens), + Queries::Intern(intern) => intern.to_tokens(tokens), + } + } +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/arity.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/arity.rs new file mode 100644 index 0000000000000..440db7b821371 --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/arity.rs @@ -0,0 +1,28 @@ +use query_group_macro::query_group; + +#[query_group] +pub trait ArityDb: salsa::Database { + fn one(&self, a: ()) -> String; + + fn two(&self, a: (), b: ()) -> String; + + fn three(&self, a: (), b: (), c: ()) -> String; + + fn none(&self) -> String; +} + +fn one(_db: &dyn ArityDb, _a: ()) -> String { + String::new() +} + +fn two(_db: &dyn ArityDb, _a: (), _b: ()) -> String { + String::new() +} + +fn three(_db: &dyn ArityDb, _a: (), _b: (), _c: ()) -> String { + String::new() +} + +fn none(_db: &dyn ArityDb) -> String { + String::new() +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/cycle.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/cycle.rs new file mode 100644 index 0000000000000..12df4ae3eff33 --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/cycle.rs @@ -0,0 +1,275 @@ +use std::panic::UnwindSafe; + +use expect_test::expect; +use query_group_macro::query_group; +use salsa::Setter; + +/// The queries A, B, and C in `Database` can be configured +/// to invoke one another in arbitrary ways using this +/// enum. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum CycleQuery { + None, + A, + B, + C, + AthenC, +} + +#[salsa::input] +struct ABC { + a: CycleQuery, + b: CycleQuery, + c: CycleQuery, +} + +impl CycleQuery { + fn invoke(self, db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> { + match self { + CycleQuery::A => db.cycle_a(abc), + CycleQuery::B => db.cycle_b(abc), + CycleQuery::C => db.cycle_c(abc), + CycleQuery::AthenC => { + let _ = db.cycle_a(abc); + db.cycle_c(abc) + } + CycleQuery::None => Ok(()), + } + } +} + +#[salsa::input] +struct MyInput {} + +#[salsa::tracked] +fn memoized_a(db: &dyn CycleDatabase, input: MyInput) { + memoized_b(db, input) +} + +#[salsa::tracked] +fn memoized_b(db: &dyn CycleDatabase, input: MyInput) { + memoized_a(db, input) +} + +#[salsa::tracked] +fn volatile_a(db: &dyn CycleDatabase, input: MyInput) { + db.report_untracked_read(); + volatile_b(db, input) +} + +#[salsa::tracked] +fn volatile_b(db: &dyn CycleDatabase, input: MyInput) { + db.report_untracked_read(); + volatile_a(db, input) +} + +#[track_caller] +fn extract_cycle(f: impl FnOnce() + UnwindSafe) -> salsa::Cycle { + let v = std::panic::catch_unwind(f); + if let Err(d) = &v { + if let Some(cycle) = d.downcast_ref::() { + return cycle.clone(); + } + } + panic!("unexpected value: {:?}", v) +} + +#[derive(PartialEq, Eq, Hash, Clone, Debug)] +struct Error { + cycle: Vec, +} + +#[query_group] +trait CycleDatabase: salsa::Database { + #[salsa::cycle(recover_a)] + fn cycle_a(&self, abc: ABC) -> Result<(), Error>; + + #[salsa::cycle(recover_b)] + fn cycle_b(&self, abc: ABC) -> Result<(), Error>; + + fn cycle_c(&self, abc: ABC) -> Result<(), Error>; +} + +fn cycle_a(db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> { + abc.a(db).invoke(db, abc) +} + +fn recover_a( + _db: &dyn CycleDatabase, + cycle: &salsa::Cycle, + _: CycleDatabaseData, + _abc: ABC, +) -> Result<(), Error> { + Err(Error { cycle: cycle.participant_keys().map(|k| format!("{k:?}")).collect() }) +} + +fn cycle_b(db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> { + abc.b(db).invoke(db, abc) +} + +fn recover_b( + _db: &dyn CycleDatabase, + cycle: &salsa::Cycle, + _: CycleDatabaseData, + _abc: ABC, +) -> Result<(), Error> { + Err(Error { cycle: cycle.participant_keys().map(|k| format!("{k:?}")).collect() }) +} + +fn cycle_c(db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> { + abc.c(db).invoke(db, abc) +} + +#[test] +fn cycle_memoized() { + let db = salsa::DatabaseImpl::new(); + + let input = MyInput::new(&db); + let cycle = extract_cycle(|| memoized_a(&db, input)); + let expected = expect![[r#" + [ + DatabaseKeyIndex( + IngredientIndex( + 1, + ), + Id(0), + ), + DatabaseKeyIndex( + IngredientIndex( + 2, + ), + Id(0), + ), + ] + "#]]; + expected.assert_debug_eq(&cycle.all_participants(&db)); +} + +#[test] +fn inner_cycle() { + // A --> B <-- C + // ^ | + // +-----+ + let db = salsa::DatabaseImpl::new(); + + let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::B); + let err = db.cycle_c(abc); + assert!(err.is_err()); + let expected = expect![[r#" + [ + "cycle_a_shim(Id(1400))", + "cycle_b_shim(Id(1000))", + ] + "#]]; + expected.assert_debug_eq(&err.unwrap_err().cycle); +} + +#[test] +fn cycle_revalidate() { + // A --> B + // ^ | + // +-----+ + let mut db = salsa::DatabaseImpl::new(); + let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::None); + assert!(db.cycle_a(abc).is_err()); + abc.set_b(&mut db).to(CycleQuery::A); // same value as default + assert!(db.cycle_a(abc).is_err()); +} + +#[test] +fn cycle_recovery_unchanged_twice() { + // A --> B + // ^ | + // +-----+ + let mut db = salsa::DatabaseImpl::new(); + let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::None); + assert!(db.cycle_a(abc).is_err()); + + abc.set_c(&mut db).to(CycleQuery::A); // force new revision + assert!(db.cycle_a(abc).is_err()); +} + +#[test] +fn cycle_appears() { + let mut db = salsa::DatabaseImpl::new(); + // A --> B + let abc = ABC::new(&db, CycleQuery::B, CycleQuery::None, CycleQuery::None); + assert!(db.cycle_a(abc).is_ok()); + + // A --> B + // ^ | + // +-----+ + abc.set_b(&mut db).to(CycleQuery::A); + assert!(db.cycle_a(abc).is_err()); +} + +#[test] +fn cycle_disappears() { + let mut db = salsa::DatabaseImpl::new(); + + // A --> B + // ^ | + // +-----+ + let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::None); + assert!(db.cycle_a(abc).is_err()); + + // A --> B + abc.set_b(&mut db).to(CycleQuery::None); + assert!(db.cycle_a(abc).is_ok()); +} + +#[test] +fn cycle_multiple() { + // No matter whether we start from A or B, we get the same set of participants: + let db = salsa::DatabaseImpl::new(); + + // Configuration: + // + // A --> B <-- C + // ^ | ^ + // +-----+ | + // | | + // +-----+ + // + // Here, conceptually, B encounters a cycle with A and then + // recovers. + let abc = ABC::new(&db, CycleQuery::B, CycleQuery::AthenC, CycleQuery::A); + + let c = db.cycle_c(abc); + let b = db.cycle_b(abc); + let a = db.cycle_a(abc); + let expected = expect![[r#" + ( + [ + "cycle_a_shim(Id(1000))", + "cycle_b_shim(Id(1400))", + ], + [ + "cycle_a_shim(Id(1000))", + "cycle_b_shim(Id(1400))", + ], + [ + "cycle_a_shim(Id(1000))", + "cycle_b_shim(Id(1400))", + ], + ) + "#]]; + expected.assert_debug_eq(&(c.unwrap_err().cycle, b.unwrap_err().cycle, a.unwrap_err().cycle)); +} + +#[test] +fn cycle_mixed_1() { + let db = salsa::DatabaseImpl::new(); + // A --> B <-- C + // | ^ + // +-----+ + let abc = ABC::new(&db, CycleQuery::B, CycleQuery::C, CycleQuery::B); + + let expected = expect![[r#" + [ + "cycle_b_shim(Id(1000))", + "cycle_c_shim(Id(c00))", + ] + "#]]; + expected.assert_debug_eq(&db.cycle_c(abc).unwrap_err().cycle); +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/hello_world.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/hello_world.rs new file mode 100644 index 0000000000000..86cf591f52126 --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/hello_world.rs @@ -0,0 +1,125 @@ +use expect_test::expect; +use query_group_macro::query_group; + +mod logger_db; +use logger_db::LoggerDb; + +#[query_group] +pub trait HelloWorldDatabase: salsa::Database { + // input + // // input with no params + #[salsa::input] + fn input_string(&self) -> String; + + // unadorned query + fn length_query(&self, key: ()) -> usize; + + // unadorned query + fn length_query_with_no_params(&self) -> usize; + + // renamed/invoke query + #[salsa::invoke(invoke_length_query_actual)] + fn invoke_length_query(&self, key: ()) -> usize; + + // not a query. should not invoked + #[salsa::transparent] + fn transparent_length(&self, key: ()) -> usize; + + #[salsa::transparent] + #[salsa::invoke(transparent_and_invoke_length_actual)] + fn transparent_and_invoke_length(&self, key: ()) -> usize; +} + +fn length_query(db: &dyn HelloWorldDatabase, _key: ()) -> usize { + db.input_string().len() +} + +fn length_query_with_no_params(db: &dyn HelloWorldDatabase) -> usize { + db.input_string().len() +} + +fn invoke_length_query_actual(db: &dyn HelloWorldDatabase, _key: ()) -> usize { + db.input_string().len() +} + +fn transparent_length(db: &dyn HelloWorldDatabase, _key: ()) -> usize { + db.input_string().len() +} + +fn transparent_and_invoke_length_actual(db: &dyn HelloWorldDatabase, _key: ()) -> usize { + db.input_string().len() +} + +#[test] +fn unadorned_query() { + let mut db = LoggerDb::default(); + + db.set_input_string(String::from("Hello, world!")); + let len = db.length_query(()); + + assert_eq!(len, 13); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_HelloWorldDatabase(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(DidValidateMemoizedValue { database_key: create_data_HelloWorldDatabase(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: length_query_shim(Id(800)) })", + "salsa_event(WillCheckCancellation)", + ]"#]]); +} + +#[test] +fn invoke_query() { + let mut db = LoggerDb::default(); + + db.set_input_string(String::from("Hello, world!")); + let len = db.invoke_length_query(()); + + assert_eq!(len, 13); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_HelloWorldDatabase(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(DidValidateMemoizedValue { database_key: create_data_HelloWorldDatabase(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: invoke_length_query_shim(Id(800)) })", + "salsa_event(WillCheckCancellation)", + ]"#]]); +} + +#[test] +fn transparent() { + let mut db = LoggerDb::default(); + + db.set_input_string(String::from("Hello, world!")); + let len = db.transparent_length(()); + + assert_eq!(len, 13); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_HelloWorldDatabase(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(DidValidateMemoizedValue { database_key: create_data_HelloWorldDatabase(Id(0)) })", + ]"#]]); +} + +#[test] +fn transparent_invoke() { + let mut db = LoggerDb::default(); + + db.set_input_string(String::from("Hello, world!")); + let len = db.transparent_and_invoke_length(()); + + assert_eq!(len, 13); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_HelloWorldDatabase(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(DidValidateMemoizedValue { database_key: create_data_HelloWorldDatabase(Id(0)) })", + ]"#]]); +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs new file mode 100644 index 0000000000000..be4fc4f52b62b --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs @@ -0,0 +1,52 @@ +use query_group_macro::query_group; + +use expect_test::expect; +use salsa::plumbing::AsId; + +mod logger_db; +use logger_db::LoggerDb; + +#[salsa::interned(no_lifetime)] +pub struct InternedString { + data: String, +} + +#[query_group] +pub trait InternedDB: salsa::Database { + #[salsa::interned] + fn intern_string(&self, data: String) -> InternedString; + + fn interned_len(&self, id: InternedString) -> usize; +} + +fn interned_len(db: &dyn InternedDB, id: InternedString) -> usize { + db.lookup_intern_string(id).len() +} + +#[test] +fn intern_round_trip() { + let db = LoggerDb::default(); + + let id = db.intern_string(String::from("Hello, world!")); + let s = db.lookup_intern_string(id); + + assert_eq!(s.len(), 13); + db.assert_logs(expect![[r#"[]"#]]); +} + +#[test] +fn intern_with_query() { + let db = LoggerDb::default(); + + let id = db.intern_string(String::from("Hello, world!")); + let len = db.interned_len(id); + + assert_eq!(len, 13); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_InternedDB(Id(400)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: interned_len_shim(Id(c00)) })", + ]"#]]); +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs new file mode 100644 index 0000000000000..b3457c1046e5e --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs @@ -0,0 +1,60 @@ +use std::sync::{Arc, Mutex}; + +#[salsa::db] +#[derive(Default, Clone)] +pub(crate) struct LoggerDb { + storage: salsa::Storage, + logger: Logger, +} + +#[derive(Default, Clone)] +struct Logger { + logs: Arc>>, +} + +#[salsa::db] +impl salsa::Database for LoggerDb { + fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) { + let event = event(); + match event.kind { + salsa::EventKind::WillExecute { .. } + | salsa::EventKind::WillCheckCancellation { .. } + | salsa::EventKind::DidValidateMemoizedValue { .. } + | salsa::EventKind::WillDiscardStaleOutput { .. } + | salsa::EventKind::DidDiscard { .. } => { + self.push_log(format!("salsa_event({:?})", event.kind)); + } + _ => {} + } + } +} + +impl LoggerDb { + /// Log an event from inside a tracked function. + pub(crate) fn push_log(&self, string: String) { + self.logger.logs.lock().unwrap().push(string); + } + + /// Asserts what the (formatted) logs should look like, + /// clearing the logged events. This takes `&mut self` because + /// it is meant to be run from outside any tracked functions. + pub(crate) fn assert_logs(&self, expected: expect_test::Expect) { + let logs = std::mem::take(&mut *self.logger.logs.lock().unwrap()); + expected.assert_eq(&format!("{:#?}", logs)); + } +} + +/// Test the logger database. +/// +/// This test isn't very interesting, but it *does* remove a dead code warning. +#[test] +fn test_logger_db() { + let db = LoggerDb::default(); + db.push_log("test".to_string()); + db.assert_logs(expect_test::expect![ + r#" + [ + "test", + ]"# + ]); +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/lru.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/lru.rs new file mode 100644 index 0000000000000..d2eee42ba8c6d --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/lru.rs @@ -0,0 +1,67 @@ +use expect_test::expect; + +mod logger_db; +use logger_db::LoggerDb; +use query_group_macro::query_group; + +#[query_group] +pub trait LruDB: salsa::Database { + // // input with no params + #[salsa::input] + fn input_string(&self) -> String; + + #[salsa::lru(16)] + fn length_query(&self, key: ()) -> usize; + + #[salsa::lru(16)] + #[salsa::invoke(invoked_query)] + fn length_query_invoke(&self, key: ()) -> usize; +} + +fn length_query(db: &dyn LruDB, _key: ()) -> usize { + db.input_string().len() +} + +fn invoked_query(db: &dyn LruDB, _key: ()) -> usize { + db.input_string().len() +} + +#[test] +fn plain_lru() { + let mut db = LoggerDb::default(); + + db.set_input_string(String::from("Hello, world!")); + let len = db.length_query(()); + + assert_eq!(len, 13); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_LruDB(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(DidValidateMemoizedValue { database_key: create_data_LruDB(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: length_query_shim(Id(800)) })", + "salsa_event(WillCheckCancellation)", + ]"#]]); +} + +#[test] +fn invoke_lru() { + let mut db = LoggerDb::default(); + + db.set_input_string(String::from("Hello, world!")); + let len = db.length_query_invoke(()); + + assert_eq!(len, 13); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_LruDB(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(DidValidateMemoizedValue { database_key: create_data_LruDB(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: length_query_invoke_shim(Id(800)) })", + "salsa_event(WillCheckCancellation)", + ]"#]]); +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/multiple_dbs.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/multiple_dbs.rs new file mode 100644 index 0000000000000..802077bfd3cb2 --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/multiple_dbs.rs @@ -0,0 +1,23 @@ +use query_group_macro::query_group; + +#[query_group] +pub trait DatabaseOne: salsa::Database { + #[salsa::input] + fn input_string(&self) -> String; + + // unadorned query + fn length(&self, key: ()) -> usize; +} + +#[query_group] +pub trait DatabaseTwo: DatabaseOne { + fn second_length(&self, key: ()) -> usize; +} + +fn length(db: &dyn DatabaseOne, _key: ()) -> usize { + db.input_string().len() +} + +fn second_length(db: &dyn DatabaseTwo, _key: ()) -> usize { + db.input_string().len() +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs new file mode 100644 index 0000000000000..733b3793ae002 --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs @@ -0,0 +1,115 @@ +use expect_test::expect; + +mod logger_db; +use logger_db::LoggerDb; +use query_group_macro::query_group; + +#[salsa::input] +struct Input { + str: String, +} + +#[query_group] +trait PartialMigrationDatabase: salsa::Database { + fn length_query(&self, input: Input) -> usize; + + // renamed/invoke query + #[salsa::invoke(invoke_length_query_actual)] + fn invoke_length_query(&self, input: Input) -> usize; + + // invoke tracked function + #[salsa::invoke(invoke_length_tracked_actual)] + fn invoke_length_tracked(&self, input: Input) -> usize; +} + +fn length_query(db: &dyn PartialMigrationDatabase, input: Input) -> usize { + input.str(db).len() +} + +fn invoke_length_query_actual(db: &dyn PartialMigrationDatabase, input: Input) -> usize { + input.str(db).len() +} + +#[salsa::tracked] +fn invoke_length_tracked_actual(db: &dyn PartialMigrationDatabase, input: Input) -> usize { + input.str(db).len() +} + +#[test] +fn unadorned_query() { + let db = LoggerDb::default(); + + let input = Input::new(&db, String::from("Hello, world!")); + let len = db.length_query(input); + + assert_eq!(len, 13); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_PartialMigrationDatabase(Id(400)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: length_query_shim(Id(c00)) })", + ]"#]]); +} + +#[test] +fn invoke_query() { + let db = LoggerDb::default(); + + let input = Input::new(&db, String::from("Hello, world!")); + let len = db.invoke_length_query(input); + + assert_eq!(len, 13); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_PartialMigrationDatabase(Id(400)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: invoke_length_query_shim(Id(c00)) })", + ]"#]]); +} + +// todo: does this even make sense? +#[test] +fn invoke_tracked_query() { + let db = LoggerDb::default(); + + let input = Input::new(&db, String::from("Hello, world!")); + let len = db.invoke_length_tracked(input); + + assert_eq!(len, 13); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_PartialMigrationDatabase(Id(400)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: invoke_length_tracked_shim(Id(c00)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: invoke_length_tracked_actual(Id(0)) })", + ]"#]]); +} + +#[test] +fn new_salsa_baseline() { + let db = LoggerDb::default(); + + #[salsa::input] + struct Input { + str: String, + } + + #[salsa::tracked] + fn new_salsa_length_query(db: &dyn PartialMigrationDatabase, input: Input) -> usize { + input.str(db).len() + } + + let input = Input::new(&db, String::from("Hello, world!")); + let len = new_salsa_length_query(&db, input); + + assert_eq!(len, 13); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: new_salsa_length_query(Id(0)) })", + ]"#]]); +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/result.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/result.rs new file mode 100644 index 0000000000000..51adde2a7ec0b --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/result.rs @@ -0,0 +1,50 @@ +mod logger_db; +use expect_test::expect; +use logger_db::LoggerDb; + +use query_group_macro::query_group; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Error; + +#[query_group] +pub trait ResultDatabase: salsa::Database { + #[salsa::input] + fn input_string(&self) -> String; + + fn length(&self, key: ()) -> Result; + + fn length2(&self, key: ()) -> Result; +} + +fn length(db: &dyn ResultDatabase, _key: ()) -> Result { + Ok(db.input_string().len()) +} + +fn length2(db: &dyn ResultDatabase, _key: ()) -> Result { + Ok(db.input_string().len()) +} + +#[test] +fn test_queries_with_results() { + let mut db = LoggerDb::default(); + let input = "hello"; + db.set_input_string(input.to_owned()); + assert_eq!(db.length(()), Ok(input.len())); + assert_eq!(db.length2(()), Ok(input.len())); + + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_ResultDatabase(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(DidValidateMemoizedValue { database_key: create_data_ResultDatabase(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: length_shim(Id(800)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: length2_shim(Id(c00)) })", + "salsa_event(WillCheckCancellation)", + ]"#]]); +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs new file mode 100644 index 0000000000000..f7361eaa90fc5 --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs @@ -0,0 +1,19 @@ +use query_group_macro::query_group; + +#[salsa::db] +pub trait SourceDb: salsa::Database { + /// Text of the file. + fn file_text(&self, id: usize) -> String; +} + +#[query_group] +pub trait RootDb: SourceDb { + fn parse(&self, id: usize) -> String; +} + +fn parse(db: &dyn RootDb, id: usize) -> String { + // this is the test: does the following compile? + db.file_text(id); + + String::new() +} diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/tuples.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/tuples.rs new file mode 100644 index 0000000000000..01f225ee10104 --- /dev/null +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/tuples.rs @@ -0,0 +1,38 @@ +use query_group_macro::query_group; + +mod logger_db; +use expect_test::expect; +use logger_db::LoggerDb; + +#[query_group] +pub trait HelloWorldDatabase: salsa::Database { + #[salsa::input] + fn input_string(&self) -> String; + + fn length_query(&self, key: ()) -> (usize, usize); +} + +fn length_query(db: &dyn HelloWorldDatabase, _key: ()) -> (usize, usize) { + let len = db.input_string().len(); + (len, len) +} + +#[test] +fn query() { + let mut db = LoggerDb::default(); + + db.set_input_string(String::from("Hello, world!")); + let len = db.length_query(()); + + assert_eq!(len, (13, 13)); + db.assert_logs(expect![[r#" + [ + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: create_data_HelloWorldDatabase(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(DidValidateMemoizedValue { database_key: create_data_HelloWorldDatabase(Id(0)) })", + "salsa_event(WillCheckCancellation)", + "salsa_event(WillExecute { database_key: length_query_shim(Id(800)) })", + "salsa_event(WillCheckCancellation)", + ]"#]]); +} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/Cargo.toml b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/Cargo.toml index 5613d75c75225..3c2daacaf9501 100644 --- a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/Cargo.toml @@ -14,7 +14,7 @@ proc-macro = true name = "ra_salsa_macros" [dependencies] -heck = "0.4" +heck = "0.5.0" proc-macro2 = "1.0" quote = "1.0" syn = { version = "2.0", features = ["full", "extra-traits"] } diff --git a/src/tools/rust-analyzer/xtask/src/tidy.rs b/src/tools/rust-analyzer/xtask/src/tidy.rs index b500b251ed355..04952de731893 100644 --- a/src/tools/rust-analyzer/xtask/src/tidy.rs +++ b/src/tools/rust-analyzer/xtask/src/tidy.rs @@ -147,6 +147,7 @@ MIT/Apache-2.0 MPL-2.0 Unlicense OR MIT Unlicense/MIT +Zlib Zlib OR Apache-2.0 OR MIT " .lines() From 83c1c4c2bb7c5744fe7e39869c941f52d54d80b7 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Mon, 10 Mar 2025 12:16:59 -0400 Subject: [PATCH 0098/2248] internal(config): use `FxIndexMap` for default completion snippets --- src/tools/rust-analyzer/Cargo.lock | 2 + src/tools/rust-analyzer/Cargo.toml | 2 +- .../crates/rust-analyzer/Cargo.toml | 1 + .../crates/rust-analyzer/src/config.rs | 50 ++++++++++--------- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 4e9b4f7e41b43..a50e1e8f49add 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -897,6 +897,7 @@ checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", "hashbrown 0.14.5", + "serde", ] [[package]] @@ -1866,6 +1867,7 @@ dependencies = [ "ide-completion", "ide-db", "ide-ssr", + "indexmap", "intern", "itertools", "load-cargo", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index ce2d66000e396..35afbdd1b5c2d 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -117,7 +117,7 @@ expect-test = "1.4.0" hashbrown = { version = "0.14", features = [ "inline-more", ], default-features = false } -indexmap = "2.1.0" +indexmap = { version = "2.1.0", features = ["serde"] } itertools = "0.12.0" libc = "0.2.150" libloading = "0.8.0" diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index 6c81c238fd3f2..9d30c5d38eb42 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml @@ -25,6 +25,7 @@ crossbeam-channel.workspace = true dirs = "5.0.1" dissimilar.workspace = true ide-completion.workspace = true +indexmap.workspace = true itertools.workspace = true scip = "0.5.1" lsp-types = { version = "=0.95.0", features = ["proposed"] } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 45ac68339b38c..8d5440b85843c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -41,6 +41,8 @@ use crate::{ lsp_ext::{WorkspaceSymbolSearchKind, WorkspaceSymbolSearchScope}, }; +type FxIndexMap = indexmap::IndexMap; + mod patch_old_style; // Conventions for configuration keys to preserve maximal extendability without breakage: @@ -81,7 +83,7 @@ config_data! { cachePriming_numThreads: NumThreads = NumThreads::Physical, /// Custom completion snippets. - completion_snippets_custom: FxHashMap = Config::completion_snippets_default(), + completion_snippets_custom: FxIndexMap = Config::completion_snippets_default(), /// These paths (file/directories) will be ignored by rust-analyzer. They are @@ -931,7 +933,7 @@ impl Config { patch_old_style::patch_json_for_outdated_configs(&mut json); let mut json_errors = vec![]; - let snips = get_field_json::>( + let snips = get_field_json::>( &mut json, &mut json_errors, "completion_snippets_custom", @@ -2032,21 +2034,13 @@ impl Config { *self.cfg_setTest(source_root) } - pub(crate) fn completion_snippets_default() -> FxHashMap { + pub(crate) fn completion_snippets_default() -> FxIndexMap { serde_json::from_str( r#"{ - "Arc::new": { - "postfix": "arc", - "body": "Arc::new(${receiver})", - "requires": "std::sync::Arc", - "description": "Put the expression into an `Arc`", - "scope": "expr" - }, - "Rc::new": { - "postfix": "rc", - "body": "Rc::new(${receiver})", - "requires": "std::rc::Rc", - "description": "Put the expression into an `Rc`", + "Ok": { + "postfix": "ok", + "body": "Ok(${receiver})", + "description": "Wrap the expression in a `Result::Ok`", "scope": "expr" }, "Box::pin": { @@ -2056,10 +2050,17 @@ impl Config { "description": "Put the expression into a pinned `Box`", "scope": "expr" }, - "Ok": { - "postfix": "ok", - "body": "Ok(${receiver})", - "description": "Wrap the expression in a `Result::Ok`", + "Arc::new": { + "postfix": "arc", + "body": "Arc::new(${receiver})", + "requires": "std::sync::Arc", + "description": "Put the expression into an `Arc`", + "scope": "expr" + }, + "Some": { + "postfix": "some", + "body": "Some(${receiver})", + "description": "Wrap the expression in an `Option::Some`", "scope": "expr" }, "Err": { @@ -2068,10 +2069,11 @@ impl Config { "description": "Wrap the expression in a `Result::Err`", "scope": "expr" }, - "Some": { - "postfix": "some", - "body": "Some(${receiver})", - "description": "Wrap the expression in an `Option::Some`", + "Rc::new": { + "postfix": "rc", + "body": "Rc::new(${receiver})", + "requires": "std::rc::Rc", + "description": "Put the expression into an `Rc`", "scope": "expr" } }"#, @@ -3210,7 +3212,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json "FxHashMap, Box<[Box]>>" => set! { "type": "object", }, - "FxHashMap" => set! { + "FxIndexMap" => set! { "type": "object", }, "FxHashMap" => set! { From a5c071633be35085edff186cef7fcfb2d17c22af Mon Sep 17 00:00:00 2001 From: David Barsky Date: Tue, 5 Nov 2024 12:24:41 -0500 Subject: [PATCH 0099/2248] internal: port rust-analyzer to new Salsa --- src/tools/rust-analyzer/Cargo.lock | 855 ++++++++++++------ src/tools/rust-analyzer/Cargo.toml | 3 +- .../rust-analyzer/crates/base-db/Cargo.toml | 4 +- .../crates/base-db/src/change.rs | 15 +- .../rust-analyzer/crates/base-db/src/lib.rs | 338 ++++--- .../rust-analyzer/crates/edition/src/lib.rs | 10 + .../rust-analyzer/crates/hir-def/Cargo.toml | 4 +- .../rust-analyzer/crates/hir-def/src/attr.rs | 7 +- .../crates/hir-def/src/data/adt.rs | 1 + .../rust-analyzer/crates/hir-def/src/db.rs | 184 ++-- .../crates/hir-def/src/expr_store.rs | 7 +- .../crates/hir-def/src/expr_store/lower.rs | 19 +- .../crates/hir-def/src/expr_store/scope.rs | 27 +- .../hir-def/src/expr_store/tests/block.rs | 4 +- .../crates/hir-def/src/generics.rs | 6 +- .../crates/hir-def/src/import_map.rs | 2 +- .../crates/hir-def/src/item_tree/pretty.rs | 2 +- .../crates/hir-def/src/item_tree/tests.rs | 2 +- .../rust-analyzer/crates/hir-def/src/lib.rs | 100 +- .../hir-def/src/macro_expansion_tests/mbe.rs | 30 +- .../hir-def/src/macro_expansion_tests/mod.rs | 13 +- .../src/macro_expansion_tests/proc_macros.rs | 6 +- .../crates/hir-def/src/nameres.rs | 7 +- .../crates/hir-def/src/nameres/collector.rs | 6 +- .../hir-def/src/nameres/mod_resolution.rs | 5 +- .../crates/hir-def/src/nameres/tests.rs | 2 +- .../hir-def/src/nameres/tests/incremental.rs | 22 +- .../crates/hir-def/src/path/lower.rs | 2 +- .../crates/hir-def/src/resolver.rs | 25 +- .../crates/hir-def/src/test_db.rs | 134 ++- .../crates/hir-expand/Cargo.toml | 2 + .../crates/hir-expand/src/builtin/fn_macro.rs | 25 +- .../crates/hir-expand/src/builtin/quote.rs | 4 +- .../crates/hir-expand/src/change.rs | 8 +- .../rust-analyzer/crates/hir-expand/src/db.rs | 131 +-- .../crates/hir-expand/src/declarative.rs | 5 +- .../crates/hir-expand/src/eager.rs | 10 +- .../crates/hir-expand/src/files.rs | 20 +- .../crates/hir-expand/src/hygiene.rs | 137 ++- .../crates/hir-expand/src/lib.rs | 41 +- .../crates/hir-expand/src/mod_path.rs | 4 +- .../src/prettify_macro_expansion_.rs | 3 +- .../crates/hir-expand/src/span_map.rs | 12 +- .../rust-analyzer/crates/hir-ty/Cargo.toml | 3 + .../crates/hir-ty/src/chalk_db.rs | 4 +- .../crates/hir-ty/src/consteval.rs | 26 +- .../crates/hir-ty/src/consteval/tests.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/db.rs | 219 +++-- .../hir-ty/src/diagnostics/decl_check.rs | 4 +- .../crates/hir-ty/src/diagnostics/expr.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/drop.rs | 9 +- .../crates/hir-ty/src/infer/expr.rs | 2 +- .../crates/hir-ty/src/interner.rs | 5 +- .../rust-analyzer/crates/hir-ty/src/layout.rs | 17 +- .../crates/hir-ty/src/layout/adt.rs | 13 +- .../rust-analyzer/crates/hir-ty/src/lib.rs | 2 - .../rust-analyzer/crates/hir-ty/src/lower.rs | 37 +- .../crates/hir-ty/src/mapping.rs | 49 +- .../crates/hir-ty/src/method_resolution.rs | 1 + .../rust-analyzer/crates/hir-ty/src/mir.rs | 9 +- .../crates/hir-ty/src/mir/borrowck.rs | 8 +- .../crates/hir-ty/src/mir/eval.rs | 1 + .../crates/hir-ty/src/mir/lower.rs | 6 +- .../crates/hir-ty/src/mir/monomorphization.rs | 14 +- .../crates/hir-ty/src/test_db.rs | 121 ++- .../rust-analyzer/crates/hir-ty/src/tests.rs | 2 +- .../hir-ty/src/tests/closure_captures.rs | 6 +- .../crates/hir-ty/src/tests/incremental.rs | 10 +- .../rust-analyzer/crates/hir-ty/src/traits.rs | 2 +- .../crates/hir-ty/src/variance.rs | 6 +- src/tools/rust-analyzer/crates/hir/src/db.rs | 81 +- .../crates/hir/src/has_source.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 10 +- .../rust-analyzer/crates/hir/src/semantics.rs | 20 +- .../hir/src/semantics/child_by_source.rs | 2 +- .../crates/hir/src/semantics/source_to_def.rs | 16 +- .../crates/hir/src/source_analyzer.rs | 3 +- .../rust-analyzer/crates/hir/src/symbols.rs | 6 +- .../crates/ide-assists/src/assist_context.rs | 6 +- .../src/handlers/add_missing_match_arms.rs | 8 +- .../src/handlers/convert_bool_to_enum.rs | 2 +- .../src/handlers/convert_closure_to_fn.rs | 2 +- .../src/handlers/extract_module.rs | 12 +- .../src/handlers/generate_function.rs | 7 +- .../src/handlers/remove_unused_param.rs | 10 +- .../crates/ide-assists/src/tests.rs | 19 +- .../ide-completion/src/completions/mod_.rs | 7 +- .../ide-completion/src/completions/postfix.rs | 2 +- .../crates/ide-completion/src/context.rs | 17 +- .../crates/ide-completion/src/lib.rs | 7 +- .../crates/ide-completion/src/render.rs | 2 +- .../crates/ide-completion/src/tests.rs | 2 +- .../src/tests/raw_identifiers.rs | 2 +- .../rust-analyzer/crates/ide-db/Cargo.toml | 4 + .../crates/ide-db/src/apply_change.rs | 361 ++++---- .../crates/ide-db/src/famous_defs.rs | 2 +- .../crates/ide-db/src/helpers.rs | 6 +- .../ide-db/src/imports/insert_use/tests.rs | 7 + .../rust-analyzer/crates/ide-db/src/lib.rs | 181 ++-- .../crates/ide-db/src/prime_caches.rs | 18 +- .../rust-analyzer/crates/ide-db/src/search.rs | 43 +- .../crates/ide-db/src/symbol_index.rs | 39 +- .../ide-db/src/syntax_helpers/suggest_name.rs | 6 +- .../ide-db/src/test_data/test_doc_alias.txt | 14 +- .../test_symbol_index_collection.txt | 60 +- .../rust-analyzer/crates/ide-db/src/traits.rs | 13 +- .../src/handlers/type_mismatch.rs | 2 +- .../src/handlers/unlinked_file.rs | 16 +- .../crates/ide-diagnostics/src/lib.rs | 49 +- .../crates/ide-diagnostics/src/tests.rs | 10 +- .../crates/ide-ssr/src/from_comment.rs | 11 +- .../rust-analyzer/crates/ide-ssr/src/lib.rs | 24 +- .../crates/ide-ssr/src/matching.rs | 2 +- .../crates/ide-ssr/src/resolving.rs | 9 +- .../crates/ide-ssr/src/search.rs | 12 +- .../rust-analyzer/crates/ide-ssr/src/tests.rs | 4 +- .../rust-analyzer/crates/ide/src/doc_links.rs | 2 +- .../crates/ide/src/doc_links/tests.rs | 4 +- .../crates/ide/src/expand_macro.rs | 6 +- .../crates/ide/src/fetch_crates.rs | 2 +- .../crates/ide/src/goto_definition.rs | 7 +- .../crates/ide/src/highlight_related.rs | 6 +- .../crates/ide/src/hover/render.rs | 2 +- .../crates/ide/src/hover/tests.rs | 14 +- .../crates/ide/src/inlay_hints.rs | 10 +- .../crates/ide/src/inlay_hints/bind_pat.rs | 8 +- .../rust-analyzer/crates/ide/src/interpret.rs | 17 +- src/tools/rust-analyzer/crates/ide/src/lib.rs | 68 +- .../crates/ide/src/parent_module.rs | 6 +- .../rust-analyzer/crates/ide/src/rename.rs | 5 +- .../rust-analyzer/crates/ide/src/runnables.rs | 2 +- src/tools/rust-analyzer/crates/ide/src/ssr.rs | 2 +- .../crates/ide/src/static_index.rs | 8 +- .../rust-analyzer/crates/ide/src/status.rs | 237 +---- .../crates/ide/src/syntax_highlighting.rs | 8 +- .../ide/src/syntax_highlighting/html.rs | 5 +- .../test_data/highlight_rainbow.html | 12 +- .../crates/ide/src/test_explorer.rs | 2 +- .../rust-analyzer/crates/ide/src/typing.rs | 13 +- .../crates/ide/src/typing/on_enter.rs | 10 +- .../crates/ide/src/view_crate_graph.rs | 9 +- .../crates/load-cargo/src/lib.rs | 2 +- .../rust-analyzer/crates/mbe/src/tests.rs | 160 ++-- .../crates/query-group-macro/Cargo.toml | 2 +- .../rust-analyzer/src/cli/analysis_stats.rs | 92 +- .../rust-analyzer/src/cli/diagnostics.rs | 6 +- .../crates/rust-analyzer/src/cli/run_tests.rs | 10 +- .../rust-analyzer/src/cli/rustc_tests.rs | 4 +- .../crates/rust-analyzer/src/cli/ssr.rs | 6 +- .../src/cli/unresolved_references.rs | 12 +- .../crates/rust-analyzer/src/global_state.rs | 31 +- .../rust-analyzer/src/handlers/dispatch.rs | 5 +- .../src/handlers/notification.rs | 3 +- .../rust-analyzer/src/handlers/request.rs | 25 +- .../crates/rust-analyzer/src/main_loop.rs | 18 +- .../crates/rust-analyzer/src/reload.rs | 2 +- .../rust-analyzer/crates/span/Cargo.toml | 5 +- .../rust-analyzer/crates/span/src/hygiene.rs | 381 ++++++-- .../rust-analyzer/crates/span/src/lib.rs | 135 +-- .../crates/test-fixture/src/lib.rs | 9 +- src/tools/rust-analyzer/xtask/src/tidy.rs | 5 +- 161 files changed, 3042 insertions(+), 2298 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index a50e1e8f49add..efd7362594c21 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" @@ -40,41 +40,41 @@ checksum = "a1078fa1ce1e34b1872d8611ad921196d76bdd7027e949fbe31231abde201892" [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", - "object 0.36.3", + "object 0.36.7", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -82,11 +82,13 @@ name = "base-db" version = "0.0.0" dependencies = [ "cfg", + "dashmap 5.5.3", "intern", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lz4_flex", - "rustc-hash 2.0.0", - "salsa 0.0.0", + "query-group-macro", + "rustc-hash 2.1.1", + "salsa 0.19.0", "semver", "span", "stdx", @@ -110,17 +112,17 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.7.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "borsh" -version = "1.5.1" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" +checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc" dependencies = [ - "cfg_aliases 0.2.1", + "cfg_aliases", ] [[package]] @@ -140,18 +142,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "camino" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -172,9 +174,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.22" +version = "1.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" +checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" dependencies = [ "shlex", ] @@ -188,7 +190,7 @@ dependencies = [ "expect-test", "intern", "oorandom", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "syntax", "syntax-bridge", "tracing", @@ -201,12 +203,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "cfg_aliases" version = "0.2.1" @@ -231,7 +227,7 @@ version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f114996bda14c0213f014a4ef31a7867dcf5f539a3900477fc6b20138e7a17b" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "chalk-derive", ] @@ -287,18 +283,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -324,18 +320,18 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "ctrlc" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" dependencies = [ "nix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -376,9 +372,9 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", @@ -415,11 +411,22 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dissimilar" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d" +checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921" [[package]] name = "dot" @@ -439,9 +446,9 @@ version = "0.0.0" [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "ena" @@ -454,15 +461,15 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "expect-test" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e0be0a561335815e06dab7c62e50353134c796e7a6155402a64bcff66b6a5e0" +checksum = "63af43ff4431e848fb47472a920f14fa71c24de13255a5692e93d4e90302acb0" dependencies = [ "dissimilar", "once_cell", @@ -470,9 +477,9 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", @@ -488,9 +495,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.31" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" +checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" dependencies = [ "crc32fast", "miniz_oxide", @@ -552,9 +559,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "hashbrown" @@ -609,7 +616,7 @@ dependencies = [ "indexmap", "intern", "itertools", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "smallvec", "span", "stdx", @@ -628,7 +635,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.7.0", + "bitflags 2.9.0", "cfg", "cov-mark", "dashmap 5.5.3", @@ -643,11 +650,13 @@ dependencies = [ "itertools", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "mbe", + "query-group-macro", "ra-ap-rustc_abi", "ra-ap-rustc_hashes", "ra-ap-rustc_parse_format", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "rustc_apfloat", + "salsa 0.19.0", "smallvec", "span", "stdx", @@ -676,7 +685,9 @@ dependencies = [ "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "mbe", "parser", - "rustc-hash 2.0.0", + "query-group-macro", + "rustc-hash 2.1.1", + "salsa 0.19.0", "smallvec", "span", "stdx", @@ -693,12 +704,13 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.7.0", + "bitflags 2.9.0", "chalk-derive", "chalk-ir", "chalk-recursive", "chalk-solve", "cov-mark", + "dashmap 5.5.3", "either", "ena", "expect-test", @@ -711,11 +723,13 @@ dependencies = [ "nohash-hasher", "oorandom", "project-model", + "query-group-macro", "ra-ap-rustc_abi", "ra-ap-rustc_index", "ra-ap-rustc_pattern_analysis", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "rustc_apfloat", + "salsa 0.19.0", "scoped-tls", "smallvec", "span", @@ -732,11 +746,129 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -816,9 +948,10 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.7.0", + "bitflags 2.9.0", "cov-mark", "crossbeam-channel", + "dashmap 5.5.3", "either", "expect-test", "fst", @@ -830,8 +963,10 @@ dependencies = [ "nohash-hasher", "parser", "profile", + "query-group-macro", "rayon", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", + "salsa 0.19.0", "span", "stdx", "syntax", @@ -839,6 +974,7 @@ dependencies = [ "test-utils", "tracing", "triomphe", + "vfs", ] [[package]] @@ -881,22 +1017,33 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] name = "indexmap" -version = "2.3.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.2", "serde", ] @@ -906,7 +1053,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "inotify-sys", "libc", ] @@ -926,7 +1073,7 @@ version = "0.0.0" dependencies = [ "dashmap 5.5.3", "hashbrown 0.14.5", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "triomphe", ] @@ -941,9 +1088,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jod-thread" @@ -989,15 +1136,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.169" +version = "0.2.170" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -1019,7 +1166,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "libc", "redox_syscall", ] @@ -1049,6 +1196,12 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +[[package]] +name = "litemap" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" + [[package]] name = "load-cargo" version = "0.0.0" @@ -1081,9 +1234,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "loom" @@ -1100,24 +1253,25 @@ dependencies = [ [[package]] name = "lsp-server" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "550446e84739dcaf6d48a4a093973850669e13e8a34d8f8d64851041be267cd9" +version = "0.7.8" dependencies = [ "crossbeam-channel", + "ctrlc", "log", + "lsp-types", "serde", + "serde_derive", "serde_json", ] [[package]] name = "lsp-server" version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9462c4dc73e17f971ec1f171d44bfffb72e65a130117233388a0ebc7ec5656f9" dependencies = [ "crossbeam-channel", - "ctrlc", "log", - "lsp-types", "serde", "serde_derive", "serde_json", @@ -1161,7 +1315,7 @@ dependencies = [ "intern", "parser", "ra-ap-rustc_lexer", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "smallvec", "span", "stdx", @@ -1207,11 +1361,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -1237,13 +1391,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "cfg-if", - "cfg_aliases 0.1.1", + "cfg_aliases", "libc", ] @@ -1259,7 +1413,7 @@ version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "filetime", "fsevent-sys", "inotify", @@ -1333,24 +1487,24 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad" [[package]] name = "oorandom" -version = "11.1.4" +version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "option-ext" @@ -1449,9 +1603,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "portable-atomic" @@ -1467,9 +1621,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] @@ -1481,7 +1635,7 @@ dependencies = [ "indexmap", "intern", "paths", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "serde", "serde_derive", "serde_json", @@ -1528,23 +1682,23 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "process-wrap" -version = "8.0.2" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ee68ae331824036479c84060534b18254c864fa73366c58d86db3b7b811619" +checksum = "d35f4dc9988d1326b065b4def5e950c3ed727aa03e3151b86cc9e2aec6b03f54" dependencies = [ "indexmap", "nix", "tracing", - "windows 0.56.0", + "windows 0.59.0", ] [[package]] @@ -1571,7 +1725,7 @@ dependencies = [ "itertools", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "paths", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "semver", "serde", "serde_derive", @@ -1609,7 +1763,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "memchr", "unicase", ] @@ -1637,9 +1791,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" dependencies = [ "proc-macro2", ] @@ -1650,7 +1804,7 @@ version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1651b0f7e8c3eb7c27a88f39d277e69c32bfe58e3be174d286c1a24d6a7a4d8" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "ra-ap-rustc_hashes", "ra-ap-rustc_index", "tracing", @@ -1714,7 +1868,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef3ff73fa4653252ffe1d1e9177a446f49ef46d97140e4816b7ff2dad59ed53" dependencies = [ "ra-ap-rustc_index", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "rustc_apfloat", "smallvec", "tracing", @@ -1772,18 +1926,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -1871,7 +2025,7 @@ dependencies = [ "intern", "itertools", "load-cargo", - "lsp-server 0.7.7", + "lsp-server 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-types", "memchr", "mimalloc", @@ -1886,7 +2040,7 @@ dependencies = [ "profile", "project-model", "rayon", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "scip", "semver", "serde", @@ -1927,23 +2081,23 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc-stable-hash" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2febf9acc5ee5e99d1ad0afcdbccc02d87aa3f857a1f01f825b80eacf8edfcd1" +checksum = "781442f29170c5c93b7185ad559492601acdc71d5bb0706f5868094f45cfcd08" [[package]] name = "rustc_apfloat" -version = "0.2.1+llvm-462a31f5a5ab" +version = "0.2.2+llvm-462a31f5a5ab" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "886d94c63c812a8037c4faca2607453a0fa4cf82f734665266876b022244543f" +checksum = "121e2195ff969977a4e2b5c9965ea867fce7e4cb5aee5b09dee698a7932d574f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.0", "smallvec", ] @@ -1955,9 +2109,9 @@ checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "salsa" @@ -1972,7 +2126,7 @@ dependencies = [ "oorandom", "parking_lot", "rand", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "salsa-macros 0.0.0", "smallvec", "tracing", @@ -1994,7 +2148,7 @@ dependencies = [ "parking_lot", "portable-atomic", "rayon", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "salsa-macro-rules", "salsa-macros 0.19.0", "smallvec", @@ -2041,9 +2195,9 @@ dependencies = [ [[package]] name = "scip" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dfafd2fa14c6237fa1fc4310f739d02fa915d92977fa069426591f1de046f81" +checksum = "fb2b449a5e4660ce817676a0871cd1b4e2ff1023e33a1ac046670fa594b543a2" dependencies = [ "protobuf", ] @@ -2062,27 +2216,27 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.216" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.216" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -2091,9 +2245,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.124" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "indexmap", "itoa", @@ -2104,9 +2258,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", @@ -2115,9 +2269,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -2139,9 +2293,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "smallvec" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" [[package]] name = "smol_str" @@ -2159,14 +2313,20 @@ version = "0.0.0" dependencies = [ "hashbrown 0.14.5", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 2.0.0", - "salsa 0.0.0", + "rustc-hash 2.1.1", + "salsa 0.19.0", "stdx", "syntax", "text-size", "vfs", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "stdx" version = "0.0.0" @@ -2183,9 +2343,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -2216,7 +2376,7 @@ dependencies = [ "ra-ap-rustc_lexer", "rayon", "rowan", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "rustc_apfloat", "smol_str", "stdx", @@ -2231,7 +2391,7 @@ version = "0.0.0" dependencies = [ "intern", "parser", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "span", "stdx", "syntax", @@ -2254,7 +2414,7 @@ dependencies = [ "cfg", "hir-expand", "intern", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "span", "stdx", "test-utils", @@ -2268,7 +2428,7 @@ dependencies = [ "dissimilar", "paths", "profile", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "stdx", "text-size", "tracing", @@ -2282,18 +2442,18 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -2343,9 +2503,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" dependencies = [ "deranged", "itoa", @@ -2360,40 +2520,35 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" dependencies = [ "num-conv", "time-core", ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "toml" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ "serde", "serde_spanned", @@ -2412,9 +2567,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap", "serde", @@ -2433,9 +2588,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -2444,9 +2599,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -2455,9 +2610,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -2476,9 +2631,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term 0.46.0", @@ -2536,51 +2691,33 @@ checksum = "a3e5df347f0bf3ec1d670aad6ca5c6a1859cd9ea61d2113125794654ccced68f" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-properties" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -2589,16 +2726,22 @@ dependencies = [ ] [[package]] -name = "valuable" -version = "0.1.0" +name = "utf16_iter" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" [[package]] -name = "version_check" -version = "0.9.5" +name = "utf8_iter" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "vfs" @@ -2609,7 +2752,7 @@ dependencies = [ "indexmap", "nohash-hasher", "paths", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "stdx", "tracing", ] @@ -2622,7 +2765,7 @@ dependencies = [ "notify", "paths", "rayon", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "stdx", "tracing", "vfs", @@ -2676,16 +2819,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.56.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" -dependencies = [ - "windows-core 0.56.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows" version = "0.58.0" @@ -2697,15 +2830,13 @@ dependencies = [ ] [[package]] -name = "windows-core" -version = "0.56.0" +name = "windows" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1" dependencies = [ - "windows-implement 0.56.0", - "windows-interface 0.56.0", - "windows-result 0.1.2", - "windows-targets 0.52.6", + "windows-core 0.59.0", + "windows-targets 0.53.0", ] [[package]] @@ -2717,19 +2848,21 @@ dependencies = [ "windows-implement 0.58.0", "windows-interface 0.58.0", "windows-result 0.2.0", - "windows-strings", + "windows-strings 0.1.0", "windows-targets 0.52.6", ] [[package]] -name = "windows-implement" -version = "0.56.0" +name = "windows-core" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce" dependencies = [ - "proc-macro2", - "quote", - "syn", + "windows-implement 0.59.0", + "windows-interface 0.59.0", + "windows-result 0.3.1", + "windows-strings 0.3.1", + "windows-targets 0.53.0", ] [[package]] @@ -2744,10 +2877,10 @@ dependencies = [ ] [[package]] -name = "windows-interface" -version = "0.56.0" +name = "windows-implement" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" dependencies = [ "proc-macro2", "quote", @@ -2766,14 +2899,22 @@ dependencies = [ ] [[package]] -name = "windows-result" -version = "0.1.2" +name = "windows-interface" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01" dependencies = [ - "windows-targets 0.52.6", + "proc-macro2", + "quote", + "syn", ] +[[package]] +name = "windows-link" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" + [[package]] name = "windows-result" version = "0.2.0" @@ -2783,6 +2924,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-strings" version = "0.1.0" @@ -2793,6 +2943,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -2844,13 +3003,29 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -2863,6 +3038,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -2875,6 +3056,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -2887,12 +3074,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -2905,6 +3104,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -2917,6 +3122,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -2929,6 +3140,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -2941,11 +3158,17 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" -version = "0.6.18" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" dependencies = [ "memchr", ] @@ -2956,6 +3179,18 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23f6174b2566cc4a74f95e1367ec343e7fa80c93cc8087f5c4a3d6a1088b2118" +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "xflags" version = "0.3.2" @@ -3007,21 +3242,87 @@ dependencies = [ "zip", ] +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 35afbdd1b5c2d..7dd5f2bb1faa9 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -72,7 +72,7 @@ proc-macro-srv = { path = "./crates/proc-macro-srv", version = "0.0.0" } proc-macro-srv-cli = { path = "./crates/proc-macro-srv-cli", version = "0.0.0" } profile = { path = "./crates/profile", version = "0.0.0" } project-model = { path = "./crates/project-model", version = "0.0.0" } -ra-salsa = { path = "./crates/ra-salsa", package = "salsa", version = "0.0.0" } +query-group = { package = "query-group-macro", path = "./crates/query-group-macro", version = "0.0.0" } span = { path = "./crates/span", version = "0.0.0" } stdx = { path = "./crates/stdx", version = "0.0.0" } syntax = { path = "./crates/syntax", version = "0.0.0" } @@ -135,6 +135,7 @@ process-wrap = { version = "8.0.2", features = ["std"] } pulldown-cmark-to-cmark = "10.0.4" pulldown-cmark = { version = "0.9.0", default-features = false } rayon = "1.8.0" +salsa = "0.19" rustc-hash = "2.0.0" semver = "1.0.14" serde = { version = "1.0.192" } diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml index 042dd36488aa9..4780d5191befb 100644 --- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml +++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml @@ -15,7 +15,9 @@ rust-version.workspace = true lz4_flex = { version = "0.11", default-features = false } la-arena.workspace = true -ra-salsa.workspace = true +dashmap.workspace = true +salsa.workspace = true +query-group.workspace = true rustc-hash.workspace = true triomphe.workspace = true semver.workspace = true diff --git a/src/tools/rust-analyzer/crates/base-db/src/change.rs b/src/tools/rust-analyzer/crates/base-db/src/change.rs index 7e40f5408f144..90413a573aef3 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/change.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/change.rs @@ -3,15 +3,12 @@ use std::fmt; -use ra_salsa::Durability; use rustc_hash::FxHashMap; +use salsa::Durability; use triomphe::Arc; use vfs::FileId; -use crate::{ - CrateGraph, CrateId, CrateWorkspaceData, SourceDatabaseFileInputExt, SourceRoot, - SourceRootDatabase, SourceRootId, -}; +use crate::{CrateGraph, CrateId, CrateWorkspaceData, RootQueryDb, SourceRoot, SourceRootId}; /// Encapsulate a bunch of raw `.set` calls on the database. #[derive(Default)] @@ -59,7 +56,7 @@ impl FileChange { self.ws_data = Some(data); } - pub fn apply(self, db: &mut dyn SourceRootDatabase) { + pub fn apply(self, db: &mut dyn RootQueryDb) { let _p = tracing::info_span!("FileChange::apply").entered(); if let Some(roots) = self.roots { for (idx, root) in roots.into_iter().enumerate() { @@ -68,14 +65,16 @@ impl FileChange { for file_id in root.iter() { db.set_file_source_root_with_durability(file_id, root_id, durability); } + db.set_source_root_with_durability(root_id, Arc::new(root), durability); } } for (file_id, text) in self.files_changed { let source_root_id = db.file_source_root(file_id); - let source_root = db.source_root(source_root_id); - let durability = durability(&source_root); + let source_root = db.source_root(source_root_id.source_root_id(db)); + + let durability = durability(&source_root.source_root(db)); // XXX: can't actually remove the file, just reset the text let text = text.unwrap_or_default(); db.set_file_text_with_durability(file_id, &text, durability) diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index eed8c88683951..9ec9100968d22 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -3,14 +3,7 @@ mod change; mod input; -use std::panic; - -use ra_salsa::Durability; -use rustc_hash::FxHashMap; -use span::EditionedFileId; -use syntax::{ast, Parse, SourceFile, SyntaxError}; -use triomphe::Arc; -use vfs::FileId; +use std::hash::BuildHasherDefault; pub use crate::{ change::FileChange, @@ -20,20 +13,30 @@ pub use crate::{ TargetLayoutLoadResult, }, }; -pub use ra_salsa::{self, Cancelled}; -pub use vfs::{file_set::FileSet, AnchoredPath, AnchoredPathBuf, VfsPath}; - +use dashmap::{mapref::entry::Entry, DashMap}; +pub use query_group::{self}; +use rustc_hash::{FxHashMap, FxHasher}; +pub use salsa::{self}; +use salsa::{Durability, Setter}; pub use semver::{BuildMetadata, Prerelease, Version, VersionReq}; +use syntax::{ast, Parse, SyntaxError}; +use triomphe::Arc; +pub use vfs::{file_set::FileSet, AnchoredPath, AnchoredPathBuf, FileId, VfsPath}; #[macro_export] macro_rules! impl_intern_key { - ($name:ident) => { - impl $crate::ra_salsa::InternKey for $name { - fn from_intern_id(v: $crate::ra_salsa::InternId) -> Self { - $name(v) - } - fn as_intern_id(&self) -> $crate::ra_salsa::InternId { - self.0 + ($id:ident, $loc:ident) => { + #[salsa::interned(no_debug, no_lifetime)] + pub struct $id { + pub loc: $loc, + } + + // If we derive this salsa prints the values recursively, and this causes us to blow. + impl ::std::fmt::Debug for $id { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + f.debug_tuple(stringify!($id)) + .field(&format_args!("{:04x}", self.0.as_u32())) + .finish() } } }; @@ -47,39 +50,213 @@ pub const DEFAULT_FILE_TEXT_LRU_CAP: u16 = 16; pub const DEFAULT_PARSE_LRU_CAP: u16 = 128; pub const DEFAULT_BORROWCK_LRU_CAP: u16 = 2024; -pub trait FileLoader { - fn resolve_path(&self, path: AnchoredPath<'_>) -> Option; - /// Crates whose root's source root is the same as the source root of `file_id` - fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>; +#[derive(Debug, Default)] +pub struct Files { + files: Arc>>, + source_roots: Arc>>, + file_source_roots: Arc>>, } -/// Database which stores all significant input facts: source code and project -/// model. Everything else in rust-analyzer is derived from these queries. -#[ra_salsa::query_group(SourceDatabaseStorage)] -pub trait SourceDatabase: FileLoader + std::fmt::Debug { - #[ra_salsa::input] - fn compressed_file_text(&self, file_id: FileId) -> Arc<[u8]>; +impl Files { + pub fn file_text(&self, file_id: vfs::FileId) -> FileText { + *self.files.get(&file_id).expect("Unable to fetch file; this is a bug") + } - /// Text of the file. - #[ra_salsa::lru] - fn file_text(&self, file_id: FileId) -> Arc; + pub fn set_file_text(&self, db: &mut dyn SourceDatabase, file_id: vfs::FileId, text: &str) { + let files = Arc::clone(&self.files); + match files.entry(file_id) { + Entry::Occupied(mut occupied) => { + occupied.get_mut().set_text(db).to(Arc::from(text)); + } + Entry::Vacant(vacant) => { + let text = FileText::new(db, Arc::from(text), file_id); + vacant.insert(text); + } + }; + } + pub fn set_file_text_with_durability( + &self, + db: &mut dyn SourceDatabase, + file_id: vfs::FileId, + text: &str, + durability: Durability, + ) { + let files = Arc::clone(&self.files); + match files.entry(file_id) { + Entry::Occupied(mut occupied) => { + occupied.get_mut().set_text(db).to(Arc::from(text)); + } + Entry::Vacant(vacant) => { + let text = + FileText::builder(Arc::from(text), file_id).durability(durability).new(db); + vacant.insert(text); + } + }; + } + + /// Source root of the file. + pub fn source_root(&self, source_root_id: SourceRootId) -> SourceRootInput { + let source_root = self + .source_roots + .get(&source_root_id) + .expect("Unable to fetch source root id; this is a bug"); + + *source_root + } + + pub fn set_source_root_with_durability( + &self, + db: &mut dyn SourceDatabase, + source_root_id: SourceRootId, + source_root: Arc, + durability: Durability, + ) { + let source_roots = Arc::clone(&self.source_roots); + match source_roots.entry(source_root_id) { + Entry::Occupied(mut occupied) => { + occupied.get_mut().set_source_root(db).to(source_root); + } + Entry::Vacant(vacant) => { + let source_root = + SourceRootInput::builder(source_root).durability(durability).new(db); + vacant.insert(source_root); + } + }; + } + + pub fn file_source_root(&self, id: vfs::FileId) -> FileSourceRootInput { + let file_source_root = self + .file_source_roots + .get(&id) + .expect("Unable to fetch FileSourceRootInput; this is a bug"); + *file_source_root + } + + pub fn set_file_source_root_with_durability( + &self, + db: &mut dyn SourceDatabase, + id: vfs::FileId, + source_root_id: SourceRootId, + durability: Durability, + ) { + let file_source_roots = Arc::clone(&self.file_source_roots); + // let db = self; + match file_source_roots.entry(id) { + Entry::Occupied(mut occupied) => { + occupied.get_mut().set_source_root_id(db).to(source_root_id); + } + Entry::Vacant(vacant) => { + let file_source_root = + FileSourceRootInput::builder(source_root_id).durability(durability).new(db); + vacant.insert(file_source_root); + } + }; + } +} + +#[salsa::interned(no_lifetime)] +pub struct EditionedFileId { + pub editioned_file_id: span::EditionedFileId, +} + +impl EditionedFileId { + pub fn file_id(&self, db: &dyn salsa::Database) -> vfs::FileId { + let id = self.editioned_file_id(db); + id.file_id() + } + + fn unpack(&self, db: &dyn salsa::Database) -> (vfs::FileId, span::Edition) { + let id = self.editioned_file_id(db); + (id.file_id(), id.edition()) + } +} + +#[salsa::input] +pub struct FileText { + pub text: Arc, + pub file_id: vfs::FileId, +} + +#[salsa::input] +pub struct FileSourceRootInput { + pub source_root_id: SourceRootId, +} + +#[salsa::input] +pub struct SourceRootInput { + pub source_root: Arc, +} + +/// Database which stores all significant input facts: source code and project +/// model. Everything else in rust-analyzer is derived from these queries. +#[query_group::query_group] +pub trait RootQueryDb: SourceDatabase + salsa::Database { /// Parses the file into the syntax tree. - #[ra_salsa::lru] + #[salsa::invoke_actual(parse)] + #[salsa::lru(128)] fn parse(&self, file_id: EditionedFileId) -> Parse; /// Returns the set of errors obtained from parsing the file including validation errors. fn parse_errors(&self, file_id: EditionedFileId) -> Option>; /// The crate graph. - #[ra_salsa::input] + #[salsa::input] fn crate_graph(&self) -> Arc; - #[ra_salsa::input] + #[salsa::input] fn crate_workspace_data(&self) -> Arc>>; - #[ra_salsa::transparent] + #[salsa::transparent] fn toolchain_channel(&self, krate: CrateId) -> Option; + + /// Crates whose root file is in `id`. + fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>; + + #[salsa::transparent] + fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>; +} + +#[salsa::db] +pub trait SourceDatabase: salsa::Database { + /// Text of the file. + fn file_text(&self, file_id: vfs::FileId) -> FileText; + + fn set_file_text(&mut self, file_id: vfs::FileId, text: &str); + + fn set_file_text_with_durability( + &mut self, + file_id: vfs::FileId, + text: &str, + durability: Durability, + ); + + /// Contents of the source root. + fn source_root(&self, id: SourceRootId) -> SourceRootInput; + + fn file_source_root(&self, id: vfs::FileId) -> FileSourceRootInput; + + fn set_file_source_root_with_durability( + &mut self, + id: vfs::FileId, + source_root_id: SourceRootId, + durability: Durability, + ); + + /// Source root of the file. + fn set_source_root_with_durability( + &mut self, + source_root_id: SourceRootId, + source_root: Arc, + durability: Durability, + ); + + fn resolve_path(&self, path: AnchoredPath<'_>) -> Option { + // FIXME: this *somehow* should be platform agnostic... + let source_root = self.file_source_root(path.anchor); + let source_root = self.source_root(source_root.source_root_id(self)); + source_root.source_root(self).resolve_path(path) + } } /// Crate related data shared by the whole workspace. @@ -91,7 +268,7 @@ pub struct CrateWorkspaceData { pub toolchain: Option, } -fn toolchain_channel(db: &dyn SourceDatabase, krate: CrateId) -> Option { +fn toolchain_channel(db: &dyn RootQueryDb, krate: CrateId) -> Option { db.crate_workspace_data() .get(&krate)? .toolchain @@ -99,14 +276,14 @@ fn toolchain_channel(db: &dyn SourceDatabase, krate: CrateId) -> Option Parse { +fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse { let _p = tracing::info_span!("parse", ?file_id).entered(); - let (file_id, edition) = file_id.unpack(); - let text = db.file_text(file_id); - SourceFile::parse(&text, edition) + let (file_id, edition) = file_id.unpack(db.as_dyn_database()); + let text = db.file_text(file_id).text(db); + ast::SourceFile::parse(&text, edition) } -fn parse_errors(db: &dyn SourceDatabase, file_id: EditionedFileId) -> Option> { +fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option> { let errors = db.parse(file_id).errors(); match &*errors { [] => None, @@ -114,67 +291,13 @@ fn parse_errors(db: &dyn SourceDatabase, file_id: EditionedFileId) -> Option Arc { - let bytes = db.compressed_file_text(file_id); - let bytes = - lz4_flex::decompress_size_prepended(&bytes).expect("lz4 decompression should not fail"); - let text = std::str::from_utf8(&bytes).expect("file contents should be valid UTF-8"); - Arc::from(text) -} - -/// We don't want to give HIR knowledge of source roots, hence we extract these -/// methods into a separate DB. -#[ra_salsa::query_group(SourceRootDatabaseStorage)] -pub trait SourceRootDatabase: SourceDatabase { - /// Path to a file, relative to the root of its source root. - /// Source root of the file. - #[ra_salsa::input] - fn file_source_root(&self, file_id: FileId) -> SourceRootId; - /// Contents of the source root. - #[ra_salsa::input] - fn source_root(&self, id: SourceRootId) -> Arc; - - /// Crates whose root file is in `id`. - fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>; -} - -pub trait SourceDatabaseFileInputExt { - fn set_file_text(&mut self, file_id: FileId, text: &str) { - self.set_file_text_with_durability(file_id, text, Durability::LOW); - } - - fn set_file_text_with_durability( - &mut self, - file_id: FileId, - text: &str, - durability: Durability, - ); -} - -impl SourceDatabaseFileInputExt for Db { - fn set_file_text_with_durability( - &mut self, - file_id: FileId, - text: &str, - durability: Durability, - ) { - let bytes = text.as_bytes(); - let compressed = lz4_flex::compress_prepend_size(bytes); - self.set_compressed_file_text_with_durability( - file_id, - Arc::from(compressed.as_slice()), - durability, - ) - } -} - -fn source_root_crates(db: &dyn SourceRootDatabase, id: SourceRootId) -> Arc<[CrateId]> { +fn source_root_crates(db: &dyn RootQueryDb, id: SourceRootId) -> Arc<[CrateId]> { let graph = db.crate_graph(); let mut crates = graph .iter() .filter(|&krate| { let root_file = graph[krate].root_file_id; - db.file_source_root(root_file) == id + db.file_source_root(root_file).source_root_id(db) == id }) .collect::>(); crates.sort(); @@ -182,22 +305,9 @@ fn source_root_crates(db: &dyn SourceRootDatabase, id: SourceRootId) -> Arc<[Cra crates.into_iter().collect() } -// FIXME: Would be nice to get rid of this somehow -/// Silly workaround for cyclic deps due to the SourceRootDatabase and SourceDatabase split -/// regarding FileLoader -pub struct FileLoaderDelegate(pub T); +fn relevant_crates(db: &dyn RootQueryDb, file_id: FileId) -> Arc<[CrateId]> { + let _p = tracing::info_span!("relevant_crates").entered(); -impl FileLoader for FileLoaderDelegate<&'_ T> { - fn resolve_path(&self, path: AnchoredPath<'_>) -> Option { - // FIXME: this *somehow* should be platform agnostic... - let source_root = self.0.file_source_root(path.anchor); - let source_root = self.0.source_root(source_root); - source_root.resolve_path(path) - } - - fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { - let _p = tracing::info_span!("relevant_crates").entered(); - let source_root = self.0.file_source_root(file_id); - self.0.source_root_crates(source_root) - } + let source_root = db.file_source_root(file_id); + db.source_root_crates(source_root.source_root_id(db)) } diff --git a/src/tools/rust-analyzer/crates/edition/src/lib.rs b/src/tools/rust-analyzer/crates/edition/src/lib.rs index 7e9c94af408c1..a2269bf54d435 100644 --- a/src/tools/rust-analyzer/crates/edition/src/lib.rs +++ b/src/tools/rust-analyzer/crates/edition/src/lib.rs @@ -19,6 +19,16 @@ impl Edition { /// The current latest stable edition, note this is usually not the right choice in code. pub const CURRENT_FIXME: Edition = Edition::Edition2021; + pub fn from_u32(u32: u32) -> Edition { + match u32 { + 0 => Edition::Edition2015, + 1 => Edition::Edition2018, + 2 => Edition::Edition2021, + 3 => Edition::Edition2024, + _ => panic!("invalid edition"), + } + } + pub fn at_least_2024(self) -> bool { self >= Edition::Edition2024 } diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml index a22961c26c84c..1b1d430ffdfd5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml @@ -29,6 +29,8 @@ hashbrown.workspace = true triomphe.workspace = true rustc_apfloat = "0.2.0" text-size.workspace = true +salsa.workspace = true +query-group.workspace = true ra-ap-rustc_hashes.workspace = true ra-ap-rustc_parse_format.workspace = true @@ -45,7 +47,6 @@ cfg.workspace = true tt.workspace = true span.workspace = true - [dev-dependencies] expect-test.workspace = true @@ -53,6 +54,7 @@ expect-test.workspace = true test-utils.workspace = true test-fixture.workspace = true syntax-bridge.workspace = true + [features] in-rust-tree = ["hir-expand/in-rust-tree"] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 710bffcefe900..52a72bce91dce 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -601,17 +601,14 @@ impl<'attr> AttrQuery<'attr> { fn any_has_attrs<'db>( db: &(dyn DefDatabase + 'db), - id: impl Lookup< - Database<'db> = dyn DefDatabase + 'db, - Data = impl HasSource, - >, + id: impl Lookup>, ) -> InFile { id.lookup(db).source(db).map(ast::AnyHasAttrs::new) } fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( db: &(dyn DefDatabase + 'db), - lookup: impl Lookup = dyn DefDatabase + 'db, Data = impl ItemTreeLoc>, + lookup: impl Lookup>, ) -> RawAttrs { let id = lookup.lookup(db).item_tree_id(); let tree = id.item_tree(db); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index c94622016d355..28992ec600aeb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -228,6 +228,7 @@ impl StructData { None, ); let types_map = strukt.types_map.clone(); + ( Arc::new(StructData { name: strukt.name.clone(), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 598a850898bb6..0772d00f03c8a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -1,5 +1,5 @@ //! Defines database & queries for name resolution. -use base_db::{ra_salsa, CrateId, SourceDatabase, Upcast}; +use base_db::{CrateId, RootQueryDb, SourceDatabase, Upcast}; use either::Either; use hir_expand::{db::ExpandDatabase, HirFileId, MacroDefId}; use intern::sym; @@ -33,178 +33,204 @@ use crate::{ UseId, UseLoc, VariantId, }; -#[ra_salsa::query_group(InternDatabaseStorage)] -pub trait InternDatabase: SourceDatabase { +use salsa::plumbing::AsId; + +#[query_group::query_group(InternDatabaseStorage)] +pub trait InternDatabase: RootQueryDb { // region: items - #[ra_salsa::interned] + #[salsa::interned] fn intern_use(&self, loc: UseLoc) -> UseId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_extern_crate(&self, loc: ExternCrateLoc) -> ExternCrateId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_function(&self, loc: FunctionLoc) -> FunctionId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_struct(&self, loc: StructLoc) -> StructId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_union(&self, loc: UnionLoc) -> UnionId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_enum(&self, loc: EnumLoc) -> EnumId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_enum_variant(&self, loc: EnumVariantLoc) -> EnumVariantId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_const(&self, loc: ConstLoc) -> ConstId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_static(&self, loc: StaticLoc) -> StaticId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_trait(&self, loc: TraitLoc) -> TraitId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_trait_alias(&self, loc: TraitAliasLoc) -> TraitAliasId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_impl(&self, loc: ImplLoc) -> ImplId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_extern_block(&self, loc: ExternBlockLoc) -> ExternBlockId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_macro2(&self, loc: Macro2Loc) -> Macro2Id; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_proc_macro(&self, loc: ProcMacroLoc) -> ProcMacroId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId; - // endregion: items + // // endregion: items - #[ra_salsa::interned] + #[salsa::interned] fn intern_block(&self, loc: BlockLoc) -> BlockId; - #[ra_salsa::interned] + #[salsa::interned] fn intern_anonymous_const(&self, id: ConstBlockLoc) -> ConstBlockId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_in_type_const(&self, id: InTypeConstLoc) -> InTypeConstId; } -#[ra_salsa::query_group(DefDatabaseStorage)] -pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast { +#[query_group::query_group] +pub trait DefDatabase: + InternDatabase + + ExpandDatabase + + SourceDatabase + + Upcast + + Upcast +{ /// Whether to expand procedural macros during name resolution. - #[ra_salsa::input] + #[salsa::input] fn expand_proc_attr_macros(&self) -> bool; /// Computes an [`ItemTree`] for the given file or macro expansion. - #[ra_salsa::invoke(ItemTree::file_item_tree_query)] + #[salsa::invoke(ItemTree::file_item_tree_query)] fn file_item_tree(&self, file_id: HirFileId) -> Arc; - #[ra_salsa::invoke(ItemTree::block_item_tree_query)] + #[salsa::invoke_actual(ItemTree::block_item_tree_query)] fn block_item_tree(&self, block_id: BlockId) -> Arc; - #[ra_salsa::invoke(ItemTree::file_item_tree_with_source_map_query)] + #[salsa::invoke(ItemTree::file_item_tree_with_source_map_query)] fn file_item_tree_with_source_map( &self, file_id: HirFileId, ) -> (Arc, Arc); - #[ra_salsa::invoke(ItemTree::block_item_tree_with_source_map_query)] + #[salsa::invoke_actual(ItemTree::block_item_tree_with_source_map_query)] fn block_item_tree_with_source_map( &self, block_id: BlockId, ) -> (Arc, Arc); - #[ra_salsa::invoke(DefMap::crate_def_map_query)] + #[salsa::invoke(DefMap::crate_def_map_query)] fn crate_def_map(&self, krate: CrateId) -> Arc; /// Computes the block-level `DefMap`. - #[ra_salsa::invoke(DefMap::block_def_map_query)] + #[salsa::invoke_actual(DefMap::block_def_map_query)] fn block_def_map(&self, block: BlockId) -> Arc; /// Turns a MacroId into a MacroDefId, describing the macro's definition post name resolution. + #[salsa::invoke_actual(macro_def)] fn macro_def(&self, m: MacroId) -> MacroDefId; // region:data - #[ra_salsa::transparent] - #[ra_salsa::invoke(StructData::struct_data_query)] + #[salsa::transparent] + #[salsa::invoke_actual(StructData::struct_data_query)] fn struct_data(&self, id: StructId) -> Arc; - #[ra_salsa::invoke(StructData::struct_data_with_diagnostics_query)] + #[salsa::invoke_actual(StructData::struct_data_with_diagnostics_query)] fn struct_data_with_diagnostics(&self, id: StructId) -> (Arc, DefDiagnostics); - #[ra_salsa::transparent] - #[ra_salsa::invoke(StructData::union_data_query)] + #[salsa::transparent] + #[salsa::invoke_actual(StructData::union_data_query)] fn union_data(&self, id: UnionId) -> Arc; - #[ra_salsa::invoke(StructData::union_data_with_diagnostics_query)] + #[salsa::invoke_actual(StructData::union_data_with_diagnostics_query)] fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc, DefDiagnostics); - #[ra_salsa::invoke(EnumData::enum_data_query)] + #[salsa::invoke_actual(EnumData::enum_data_query)] fn enum_data(&self, e: EnumId) -> Arc; - #[ra_salsa::transparent] - #[ra_salsa::invoke(EnumVariantData::enum_variant_data_query)] + #[salsa::transparent] + #[salsa::invoke_actual(EnumVariantData::enum_variant_data_query)] fn enum_variant_data(&self, id: EnumVariantId) -> Arc; - #[ra_salsa::invoke(EnumVariantData::enum_variant_data_with_diagnostics_query)] + #[salsa::invoke_actual(EnumVariantData::enum_variant_data_with_diagnostics_query)] fn enum_variant_data_with_diagnostics( &self, id: EnumVariantId, ) -> (Arc, DefDiagnostics); - #[ra_salsa::transparent] - #[ra_salsa::invoke(VariantData::variant_data)] + #[salsa::transparent] + #[salsa::invoke_actual(VariantData::variant_data)] fn variant_data(&self, id: VariantId) -> Arc; - #[ra_salsa::transparent] - #[ra_salsa::invoke(ImplData::impl_data_query)] + #[salsa::transparent] + #[salsa::invoke_actual(ImplData::impl_data_query)] fn impl_data(&self, e: ImplId) -> Arc; - #[ra_salsa::invoke(ImplData::impl_data_with_diagnostics_query)] + #[salsa::invoke_actual(ImplData::impl_data_with_diagnostics_query)] fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc, DefDiagnostics); - #[ra_salsa::transparent] - #[ra_salsa::invoke(TraitData::trait_data_query)] + #[salsa::transparent] + #[salsa::invoke_actual(TraitData::trait_data_query)] fn trait_data(&self, e: TraitId) -> Arc; - #[ra_salsa::invoke(TraitData::trait_data_with_diagnostics_query)] + #[salsa::invoke_actual(TraitData::trait_data_with_diagnostics_query)] fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc, DefDiagnostics); - #[ra_salsa::invoke(TraitAliasData::trait_alias_query)] + #[salsa::invoke_actual(TraitAliasData::trait_alias_query)] fn trait_alias_data(&self, e: TraitAliasId) -> Arc; - #[ra_salsa::invoke(TypeAliasData::type_alias_data_query)] + #[salsa::invoke_actual(TypeAliasData::type_alias_data_query)] fn type_alias_data(&self, e: TypeAliasId) -> Arc; - #[ra_salsa::invoke(FunctionData::fn_data_query)] + #[salsa::invoke_actual(FunctionData::fn_data_query)] fn function_data(&self, func: FunctionId) -> Arc; - #[ra_salsa::invoke(ConstData::const_data_query)] + #[salsa::invoke_actual(ConstData::const_data_query)] fn const_data(&self, konst: ConstId) -> Arc; - #[ra_salsa::invoke(StaticData::static_data_query)] + #[salsa::invoke_actual(StaticData::static_data_query)] fn static_data(&self, statik: StaticId) -> Arc; - #[ra_salsa::invoke(Macro2Data::macro2_data_query)] + #[salsa::invoke_actual(Macro2Data::macro2_data_query)] fn macro2_data(&self, makro: Macro2Id) -> Arc; - #[ra_salsa::invoke(MacroRulesData::macro_rules_data_query)] + #[salsa::invoke_actual(MacroRulesData::macro_rules_data_query)] fn macro_rules_data(&self, makro: MacroRulesId) -> Arc; - #[ra_salsa::invoke(ProcMacroData::proc_macro_data_query)] + #[salsa::invoke_actual(ProcMacroData::proc_macro_data_query)] fn proc_macro_data(&self, makro: ProcMacroId) -> Arc; - #[ra_salsa::invoke(ExternCrateDeclData::extern_crate_decl_data_query)] + #[salsa::invoke_actual(ExternCrateDeclData::extern_crate_decl_data_query)] fn extern_crate_decl_data(&self, extern_crate: ExternCrateId) -> Arc; // endregion:data - #[ra_salsa::invoke(Body::body_with_source_map_query)] - #[ra_salsa::lru] + #[salsa::invoke(Body::body_with_source_map_query)] + #[salsa::lru(512)] fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc, Arc); - #[ra_salsa::invoke(Body::body_query)] + #[salsa::invoke(Body::body_query)] fn body(&self, def: DefWithBodyId) -> Arc; - #[ra_salsa::invoke(ExprScopes::expr_scopes_query)] + #[salsa::invoke_actual(ExprScopes::expr_scopes_query)] fn expr_scopes(&self, def: DefWithBodyId) -> Arc; - #[ra_salsa::invoke(GenericParams::generic_params_query)] + #[salsa::invoke_actual(GenericParams::generic_params_query)] fn generic_params(&self, def: GenericDefId) -> Arc; /// If this returns `None` for the source map, that means it is the same as with the item tree. - #[ra_salsa::invoke(GenericParams::generic_params_with_source_map_query)] + #[salsa::invoke_actual(GenericParams::generic_params_with_source_map_query)] fn generic_params_with_source_map( &self, def: GenericDefId, @@ -212,51 +238,51 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Arc>; // should this really be a query? - #[ra_salsa::invoke(crate::attr::fields_attrs_source_map)] + #[salsa::invoke_actual(crate::attr::fields_attrs_source_map)] fn fields_attrs_source_map( &self, def: VariantId, ) -> Arc>>>; - #[ra_salsa::invoke(AttrsWithOwner::attrs_query)] + #[salsa::invoke(AttrsWithOwner::attrs_query)] fn attrs(&self, def: AttrDefId) -> Attrs; - #[ra_salsa::transparent] - #[ra_salsa::invoke(lang_item::lang_attr)] + #[salsa::transparent] + #[salsa::invoke(lang_item::lang_attr)] fn lang_attr(&self, def: AttrDefId) -> Option; // endregion:attrs - #[ra_salsa::invoke(LangItems::lang_item_query)] + #[salsa::invoke(LangItems::lang_item_query)] fn lang_item(&self, start_crate: CrateId, item: LangItem) -> Option; - #[ra_salsa::invoke(ImportMap::import_map_query)] + #[salsa::invoke(ImportMap::import_map_query)] fn import_map(&self, krate: CrateId) -> Arc; // region:visibilities - #[ra_salsa::invoke(visibility::field_visibilities_query)] + #[salsa::invoke(visibility::field_visibilities_query)] fn field_visibilities(&self, var: VariantId) -> Arc>; // FIXME: unify function_visibility and const_visibility? - #[ra_salsa::invoke(visibility::function_visibility_query)] + #[salsa::invoke_actual(visibility::function_visibility_query)] fn function_visibility(&self, def: FunctionId) -> Visibility; - #[ra_salsa::invoke(visibility::const_visibility_query)] + #[salsa::invoke_actual(visibility::const_visibility_query)] fn const_visibility(&self, def: ConstId) -> Visibility; // endregion:visibilities - #[ra_salsa::invoke(LangItems::crate_lang_items_query)] + #[salsa::invoke(LangItems::crate_lang_items_query)] fn crate_lang_items(&self, krate: CrateId) -> Option>; - #[ra_salsa::invoke(crate::lang_item::notable_traits_in_deps)] + #[salsa::invoke(crate::lang_item::notable_traits_in_deps)] fn notable_traits_in_deps(&self, krate: CrateId) -> Arc<[Arc<[TraitId]>]>; - #[ra_salsa::invoke(crate::lang_item::crate_notable_traits)] + #[salsa::invoke(crate::lang_item::crate_notable_traits)] fn crate_notable_traits(&self, krate: CrateId) -> Option>; fn crate_supports_no_std(&self, crate_id: CrateId) -> bool; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs index 5ff6a7ffe5669..616d2c9fd89a4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs @@ -16,7 +16,7 @@ use hir_expand::{name::Name, ExpandError, InFile}; use la_arena::{Arena, ArenaMap}; use rustc_hash::FxHashMap; use smallvec::SmallVec; -use span::{Edition, MacroFileId, SyntaxContextData}; +use span::{Edition, MacroFileId, SyntaxContext}; use syntax::{ast, AstPtr, SyntaxNodePtr}; use triomphe::Arc; use tt::TextRange; @@ -49,8 +49,9 @@ impl HygieneId { Self(ctx) } - pub(crate) fn lookup(self, db: &dyn DefDatabase) -> SyntaxContextData { - db.lookup_intern_syntax_context(self.0) + // FIXME: Inline this + pub(crate) fn lookup(self) -> SyntaxContext { + self.0 } pub(crate) fn is_root(self) -> bool { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 6e505a6b1126e..c3ca610faecbe 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -1931,11 +1931,11 @@ impl ExprCollector<'_> { None => (HygieneId::ROOT, None), Some(span_map) => { let span = span_map.span_at(lifetime.syntax().text_range().start()); - let ctx = self.db.lookup_intern_syntax_context(span.ctx); - let hygiene_id = HygieneId::new(ctx.opaque_and_semitransparent); - let hygiene_info = ctx.outer_expn.map(|expansion| { + let ctx = span.ctx; + let hygiene_id = HygieneId::new(ctx.opaque_and_semitransparent(self.db)); + let hygiene_info = ctx.outer_expn(self.db).map(|expansion| { let expansion = self.db.lookup_intern_macro_call(expansion); - (ctx.parent, expansion.def) + (ctx.parent(self.db), expansion.def) }); (hygiene_id, hygiene_info) } @@ -1962,11 +1962,12 @@ impl ExprCollector<'_> { // A macro is allowed to refer to labels from before its declaration. // Therefore, if we got to the rib of its declaration, give up its hygiene // and use its parent expansion. - let parent_ctx = self.db.lookup_intern_syntax_context(parent_ctx); - hygiene_id = HygieneId::new(parent_ctx.opaque_and_semitransparent); - hygiene_info = parent_ctx.outer_expn.map(|expansion| { + + hygiene_id = + HygieneId::new(parent_ctx.opaque_and_semitransparent(self.db)); + hygiene_info = parent_ctx.outer_expn(self.db).map(|expansion| { let expansion = self.db.lookup_intern_macro_call(expansion); - (parent_ctx.parent, expansion.def) + (parent_ctx.parent(self.db), expansion.def) }); } } @@ -2593,7 +2594,7 @@ impl ExprCollector<'_> { None => HygieneId::ROOT, Some(span_map) => { let ctx = span_map.span_at(span_start).ctx; - HygieneId::new(self.db.lookup_intern_syntax_context(ctx).opaque_and_semitransparent) + HygieneId::new(ctx.opaque_and_semitransparent(self.db)) } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs index 859a706177aab..42a8eae4064dc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs @@ -324,8 +324,9 @@ fn compute_expr_scopes( #[cfg(test)] mod tests { - use base_db::SourceDatabase; + use base_db::RootQueryDb; use hir_expand::{name::AsName, InFile}; + use salsa::AsDynDatabase; use span::FileId; use syntax::{algo::find_node_at_offset, ast, AstNode}; use test_fixture::WithFixture; @@ -357,18 +358,22 @@ mod tests { }; let (db, position) = TestDB::with_position(&code); - let file_id = position.file_id; + let editioned_file_id = position.file_id; let offset = position.offset; - let file_syntax = db.parse(file_id).syntax_node(); + let (file_id, _) = editioned_file_id.unpack(); + let editioned_file_id_wrapper = + base_db::EditionedFileId::new(db.as_dyn_database(), editioned_file_id); + + let file_syntax = db.parse(editioned_file_id_wrapper).syntax_node(); let marker: ast::PathExpr = find_node_at_offset(&file_syntax, offset).unwrap(); - let function = find_function(&db, file_id.file_id()); + let function = find_function(&db, file_id); let scopes = db.expr_scopes(function.into()); let (_body, source_map) = db.body_with_source_map(function.into()); let expr_id = source_map - .node_expr(InFile { file_id: file_id.into(), value: &marker.into() }) + .node_expr(InFile { file_id: editioned_file_id.into(), value: &marker.into() }) .unwrap() .as_expr() .unwrap(); @@ -511,15 +516,19 @@ fn foo() { fn do_check_local_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected_offset: u32) { let (db, position) = TestDB::with_position(ra_fixture); - let file_id = position.file_id; + let editioned_file_id = position.file_id; let offset = position.offset; - let file = db.parse(file_id).ok().unwrap(); + let (file_id, _) = editioned_file_id.unpack(); + let file_id_wrapper = + base_db::EditionedFileId::new(db.as_dyn_database(), editioned_file_id); + + let file = db.parse(file_id_wrapper).ok().unwrap(); let expected_name = find_node_at_offset::(file.syntax(), expected_offset.into()) .expect("failed to find a name at the target offset"); let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), offset).unwrap(); - let function = find_function(&db, file_id.file_id()); + let function = find_function(&db, file_id); let scopes = db.expr_scopes(function.into()); let (_, source_map) = db.body_with_source_map(function.into()); @@ -527,7 +536,7 @@ fn foo() { let expr_scope = { let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap(); let expr_id = source_map - .node_expr(InFile { file_id: file_id.into(), value: &expr_ast }) + .node_expr(InFile { file_id: editioned_file_id.into(), value: &expr_ast }) .unwrap() .as_expr() .unwrap(); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/block.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/block.rs index e136dd18a55e5..df0bbe5c3ef38 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/block.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/block.rs @@ -189,8 +189,8 @@ fn f() { } "#, expect![[r#" - BlockId(1) in BlockRelativeModuleId { block: Some(BlockId(0)), local_id: Idx::(1) } - BlockId(0) in BlockRelativeModuleId { block: None, local_id: Idx::(0) } + BlockId(4c01) in BlockRelativeModuleId { block: Some(BlockId(4c00)), local_id: Idx::(1) } + BlockId(4c00) in BlockRelativeModuleId { block: None, local_id: Idx::(0) } crate scope "#]], ); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs index e2b36da79b232..80820193796de 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs @@ -362,10 +362,7 @@ impl GenericParams { }; fn id_to_generics( db: &dyn DefDatabase, - id: impl for<'db> Lookup< - Database<'db> = dyn DefDatabase + 'db, - Data = impl ItemTreeLoc, - >, + id: impl Lookup>, enabled_params: impl Fn( &Arc, &ItemTree, @@ -378,6 +375,7 @@ impl GenericParams { let id = id.lookup(db).item_tree_id(); let tree = id.item_tree(db); let item = &tree[id.value]; + (enabled_params(item.generic_params(), &tree, id.value.into()), None) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs index d43776b8a66ad..64c1d0d274f34 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs @@ -475,7 +475,7 @@ fn search_maps( #[cfg(test)] mod tests { - use base_db::{SourceDatabase, Upcast}; + use base_db::{RootQueryDb, Upcast}; use expect_test::{expect, Expect}; use test_fixture::WithFixture; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index 70bf2f13c88a1..d113a500ef76f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -546,7 +546,7 @@ impl Printer<'_> { let MacroCall { path, ast_id, expand_to, ctxt } = &self.tree[it]; let _ = writeln!( self, - "// AstId: {:?}, SyntaxContext: {}, ExpandTo: {:?}", + "// AstId: {:?}, SyntaxContextId: {}, ExpandTo: {:?}", ast_id.erase().into_raw(), ctxt, expand_to diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs index 80b699649fba8..b442e877343fc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs @@ -270,7 +270,7 @@ m!(); // AstId: 2 pub macro m2 { ... } - // AstId: 3, SyntaxContext: 2, ExpandTo: Items + // AstId: 3, SyntaxContextId: 4294967037, ExpandTo: Items m!(...); "#]], ); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 9c947df35e990..15ef8364ed215 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -69,16 +69,9 @@ mod pretty; #[cfg(test)] mod test_db; -use std::{ - hash::{Hash, Hasher}, - panic::{RefUnwindSafe, UnwindSafe}, -}; +use std::hash::{Hash, Hasher}; -use base_db::{ - impl_intern_key, - ra_salsa::{self, InternValueTrivial}, - CrateId, -}; +use base_db::{impl_intern_key, CrateId}; use hir_expand::{ builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander}, db::ExpandDatabase, @@ -192,8 +185,7 @@ pub trait ItemTreeLoc { macro_rules! impl_intern { ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => { - impl_intern_key!($id); - impl InternValueTrivial for $loc {} + impl_intern_key!($id, $loc); impl_intern_lookup!(DefDatabase, $id, $loc, $intern, $lookup); }; } @@ -213,87 +205,58 @@ macro_rules! impl_loc { }; } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct FunctionId(ra_salsa::InternId); type FunctionLoc = AssocItemLoc; impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function); impl_loc!(FunctionLoc, id: Function, container: ItemContainerId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct StructId(ra_salsa::InternId); type StructLoc = ItemLoc; impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); impl_loc!(StructLoc, id: Struct, container: ModuleId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct UnionId(ra_salsa::InternId); pub type UnionLoc = ItemLoc; impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); impl_loc!(UnionLoc, id: Union, container: ModuleId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct EnumId(ra_salsa::InternId); pub type EnumLoc = ItemLoc; impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); impl_loc!(EnumLoc, id: Enum, container: ModuleId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct ConstId(ra_salsa::InternId); type ConstLoc = AssocItemLoc; impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const); impl_loc!(ConstLoc, id: Const, container: ItemContainerId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct StaticId(ra_salsa::InternId); pub type StaticLoc = AssocItemLoc; impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static); impl_loc!(StaticLoc, id: Static, container: ItemContainerId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct TraitId(ra_salsa::InternId); pub type TraitLoc = ItemLoc; impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait); impl_loc!(TraitLoc, id: Trait, container: ModuleId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct TraitAliasId(ra_salsa::InternId); pub type TraitAliasLoc = ItemLoc; impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias); impl_loc!(TraitAliasLoc, id: TraitAlias, container: ModuleId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct TypeAliasId(ra_salsa::InternId); type TypeAliasLoc = AssocItemLoc; impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias); impl_loc!(TypeAliasLoc, id: TypeAlias, container: ItemContainerId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] -pub struct ImplId(ra_salsa::InternId); type ImplLoc = ItemLoc; impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); impl_loc!(ImplLoc, id: Impl, container: ModuleId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] -pub struct UseId(ra_salsa::InternId); type UseLoc = ItemLoc; impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use); impl_loc!(UseLoc, id: Use, container: ModuleId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] -pub struct ExternCrateId(ra_salsa::InternId); type ExternCrateLoc = ItemLoc; impl_intern!(ExternCrateId, ExternCrateLoc, intern_extern_crate, lookup_intern_extern_crate); impl_loc!(ExternCrateLoc, id: ExternCrate, container: ModuleId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] -pub struct ExternBlockId(ra_salsa::InternId); type ExternBlockLoc = ItemLoc; impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block); impl_loc!(ExternBlockLoc, id: ExternBlock, container: ModuleId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct EnumVariantId(ra_salsa::InternId); - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumVariantLoc { pub id: ItemTreeId, @@ -302,9 +265,6 @@ pub struct EnumVariantLoc { } impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant); impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId); - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] -pub struct Macro2Id(ra_salsa::InternId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Macro2Loc { pub container: ModuleId, @@ -316,8 +276,6 @@ pub struct Macro2Loc { impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2); impl_loc!(Macro2Loc, id: Macro2, container: ModuleId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] -pub struct MacroRulesId(ra_salsa::InternId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroRulesLoc { pub container: ModuleId, @@ -345,8 +303,7 @@ pub enum MacroExpander { BuiltInDerive(BuiltinDeriveExpander), BuiltInEager(EagerExpander), } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] -pub struct ProcMacroId(ra_salsa::InternId); + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ProcMacroLoc { pub container: CrateRootModuleId, @@ -358,8 +315,6 @@ pub struct ProcMacroLoc { impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro); impl_loc!(ProcMacroLoc, id: Function, container: CrateRootModuleId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] -pub struct BlockId(ra_salsa::InternId); #[derive(Debug, Hash, PartialEq, Eq, Clone)] pub struct BlockLoc { pub ast_id: AstId, @@ -368,10 +323,8 @@ pub struct BlockLoc { } impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block); -/// Id of the anonymous const block expression and patterns. This is very similar to `ClosureId` and -/// shouldn't be a `DefWithBodyId` since its type inference is dependent on its parent. -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -pub struct ConstBlockId(ra_salsa::InternId); +// Id of the anonymous const block expression and patterns. This is very similar to `ClosureId` and +// shouldn't be a `DefWithBodyId` since its type inference is dependent on its parent. impl_intern!(ConstBlockId, ConstBlockLoc, intern_anonymous_const, lookup_intern_anonymous_const); #[derive(Debug, Hash, PartialEq, Eq, Clone)] @@ -536,12 +489,11 @@ pub struct TupleFieldId { pub index: u32, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct TypeOrConstParamId { pub parent: GenericDefId, pub local_id: LocalTypeOrConstParamId, } -impl InternValueTrivial for TypeOrConstParamId {} /// A TypeOrConstParamId with an invariant that it actually belongs to a type #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -603,7 +555,6 @@ pub struct LifetimeParamId { pub local_id: LocalLifetimeParamId, } pub type LocalLifetimeParamId = Idx; -impl InternValueTrivial for LifetimeParamId {} #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ItemContainerId { @@ -615,7 +566,7 @@ pub enum ItemContainerId { impl_from!(ModuleId for ItemContainerId); /// A Data Type -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] pub enum AdtId { StructId(StructId), UnionId(UnionId), @@ -624,7 +575,7 @@ pub enum AdtId { impl_from!(StructId, UnionId, EnumId for AdtId); /// A macro -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] pub enum MacroId { Macro2Id(Macro2Id), MacroRulesId(MacroRulesId), @@ -760,9 +711,7 @@ impl From for TypeOwnerId { /// currently only used in `InTypeConstId` for storing the type (which has type `Ty` defined in /// the `hir-ty` crate) of the constant in its id, which is a temporary hack so we may want /// to remove this after removing that. -pub trait OpaqueInternableThing: - std::any::Any + std::fmt::Debug + Sync + Send + UnwindSafe + RefUnwindSafe -{ +pub trait OpaqueInternableThing: std::any::Any + std::fmt::Debug + Sync + Send { fn as_any(&self) -> &dyn std::any::Any; fn box_any(&self) -> Box; fn dyn_hash(&self, state: &mut dyn Hasher); @@ -809,11 +758,9 @@ impl Clone for Box { // and the name of the struct that contains this constant is resolved, so a query that only traverses the // type owner by its syntax tree might have a hard time here. -/// A constant in a type as a substitution for const generics (like `Foo<{ 2 + 2 }>`) or as an array -/// length (like `[u8; 2 + 2]`). These constants are body owner and are a variant of `DefWithBodyId`. These -/// are not called `AnonymousConstId` to prevent confusion with [`ConstBlockId`]. -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -pub struct InTypeConstId(ra_salsa::InternId); +// A constant in a type as a substitution for const generics (like `Foo<{ 2 + 2 }>`) or as an array +// length (like `[u8; 2 + 2]`). These constants are body owner and are a variant of `DefWithBodyId`. These +// are not called `AnonymousConstId` to prevent confusion with [`ConstBlockId`]. impl_intern!(InTypeConstId, InTypeConstLoc, intern_in_type_const, lookup_intern_in_type_const); // We would like to set `derive(PartialEq)` @@ -838,8 +785,8 @@ impl InTypeConstId { pub fn source(&self, db: &dyn DefDatabase) -> ast::ConstArg { let src = self.lookup(db).id; let file_id = src.file_id; - let root = &db.parse_or_expand(file_id); - db.ast_id_map(file_id).get(src.value).to_node(root) + let root = db.parse_or_expand(file_id); + db.ast_id_map(file_id).get(src.value).to_node(&root) } } @@ -884,7 +831,7 @@ impl GeneralConstId { } /// The defs which have a body. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] pub enum DefWithBodyId { FunctionId(FunctionId), StaticId(StaticId), @@ -892,7 +839,6 @@ pub enum DefWithBodyId { InTypeConstId(InTypeConstId), VariantId(EnumVariantId), } - impl_from!(FunctionId, ConstId, StaticId, InTypeConstId for DefWithBodyId); impl From for DefWithBodyId { @@ -928,7 +874,7 @@ pub enum AssocItemId { // casting them, and somehow making the constructors private, which would be annoying. impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId); -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] pub enum GenericDefId { AdtId(AdtId), // consts can have type parameters from their parents (i.e. associated consts of traits) @@ -962,7 +908,7 @@ impl GenericDefId { ) -> (HirFileId, Option) { fn file_id_and_params_of_item_loc( db: &dyn DefDatabase, - def: impl for<'db> Lookup = dyn DefDatabase + 'db, Data = Loc>, + def: impl Lookup, ) -> (HirFileId, Option) where Loc: src::HasSource, @@ -1017,15 +963,13 @@ impl From for GenericDefId { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] pub enum CallableDefId { FunctionId(FunctionId), StructId(StructId), EnumVariantId(EnumVariantId), } -impl InternValueTrivial for CallableDefId {} - impl_from!(FunctionId, StructId, EnumVariantId for CallableDefId); impl From for ModuleDefId { fn from(def: CallableDefId) -> ModuleDefId { @@ -1135,7 +1079,7 @@ impl From for AttrDefId { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] pub enum VariantId { EnumVariantId(EnumVariantId), StructId(StructId), @@ -1197,7 +1141,7 @@ pub trait HasModule { impl HasModule for ItemId where N: ItemTreeNode, - ItemId: for<'db> Lookup = dyn DefDatabase + 'db, Data = ItemLoc> + Copy, + ItemId: Lookup> + Copy, { #[inline] fn module(&self, db: &dyn DefDatabase) -> ModuleId { @@ -1222,7 +1166,7 @@ where #[inline] fn module_for_assoc_item_loc<'db>( db: &(dyn 'db + DefDatabase), - id: impl Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, + id: impl Lookup>, ) -> ModuleId { id.lookup(db).container.module(db) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs index 8c5bd3b6d3696..66e344d72452d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -35,9 +35,9 @@ macro_rules! f { }; } -struct#0:1@58..64#4# MyTraitMap2#0:2@31..42#2# {#0:1@72..73#4# - map#0:1@86..89#4#:#0:1@89..90#4# #0:1@89..90#4#::#0:1@91..93#4#std#0:1@93..96#4#::#0:1@96..98#4#collections#0:1@98..109#4#::#0:1@109..111#4#HashSet#0:1@111..118#4#<#0:1@118..119#4#(#0:1@119..120#4#)#0:1@120..121#4#>#0:1@121..122#4#,#0:1@122..123#4# -}#0:1@132..133#4# +struct#0:1@58..64#20480# MyTraitMap2#0:2@31..42#4294967037# {#0:1@72..73#20480# + map#0:1@86..89#20480#:#0:1@89..90#20480# #0:1@89..90#20480#::#0:1@91..93#20480#std#0:1@93..96#20480#::#0:1@96..98#20480#collections#0:1@98..109#20480#::#0:1@109..111#20480#HashSet#0:1@111..118#20480#<#0:1@118..119#20480#(#0:1@119..120#20480#)#0:1@120..121#20480#>#0:1@121..122#20480#,#0:1@122..123#20480# +}#0:1@132..133#20480# "#]], ); } @@ -75,12 +75,12 @@ macro_rules! f { }; } -fn#0:2@30..32#2# main#0:2@33..37#2#(#0:2@37..38#2#)#0:2@38..39#2# {#0:2@40..41#2# - 1#0:2@50..51#2#;#0:2@51..52#2# - 1.0#0:2@61..64#2#;#0:2@64..65#2# - (#0:2@74..75#2#(#0:2@75..76#2#1#0:2@76..77#2#,#0:2@77..78#2# )#0:2@78..79#2#,#0:2@79..80#2# )#0:2@80..81#2#.#0:2@81..82#2#0#0:2@82..85#2#.#0:2@82..85#2#0#0:2@82..85#2#;#0:2@85..86#2# - let#0:2@95..98#2# x#0:2@99..100#2# =#0:2@101..102#2# 1#0:2@103..104#2#;#0:2@104..105#2# -}#0:2@110..111#2# +fn#0:2@30..32#4294967037# main#0:2@33..37#4294967037#(#0:2@37..38#4294967037#)#0:2@38..39#4294967037# {#0:2@40..41#4294967037# + 1#0:2@50..51#4294967037#;#0:2@51..52#4294967037# + 1.0#0:2@61..64#4294967037#;#0:2@64..65#4294967037# + (#0:2@74..75#4294967037#(#0:2@75..76#4294967037#1#0:2@76..77#4294967037#,#0:2@77..78#4294967037# )#0:2@78..79#4294967037#,#0:2@79..80#4294967037# )#0:2@80..81#4294967037#.#0:2@81..82#4294967037#0#0:2@82..85#4294967037#.#0:2@82..85#4294967037#0#0:2@82..85#4294967037#;#0:2@85..86#4294967037# + let#0:2@95..98#4294967037# x#0:2@99..100#4294967037# =#0:2@101..102#4294967037# 1#0:2@103..104#4294967037#;#0:2@104..105#4294967037# +}#0:2@110..111#4294967037# "#]], @@ -171,7 +171,7 @@ fn main(foo: ()) { } fn main(foo: ()) { - /* error: unresolved macro unresolved */"helloworld!"#0:3@236..321#2#; + /* error: unresolved macro unresolved */"helloworld!"#0:3@236..321#4294967037#; } } @@ -197,7 +197,7 @@ macro_rules! mk_struct { #[macro_use] mod foo; -struct#1:1@59..65#4# Foo#0:2@32..35#2#(#1:1@70..71#4#u32#0:2@41..44#2#)#1:1@74..75#4#;#1:1@75..76#4# +struct#1:1@59..65#20480# Foo#0:2@32..35#4294967037#(#1:1@70..71#20480#u32#0:2@41..44#4294967037#)#1:1@74..75#20480#;#1:1@75..76#20480# "#]], ); } @@ -423,10 +423,10 @@ m! { foo, bar } macro_rules! m { ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } ); } -impl#\4# Bar#\4# {#\4# - fn#\4# foo#\2#(#\4#)#\4# {#\4#}#\4# - fn#\4# bar#\2#(#\4#)#\4# {#\4#}#\4# -}#\4# +impl#\20480# Bar#\20480# {#\20480# + fn#\20480# foo#\4294967037#(#\20480#)#\20480# {#\20480#}#\20480# + fn#\20480# bar#\4294967037#(#\20480#)#\20480# {#\20480#}#\20480# +}#\20480# "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs index a2d0ba3deb845..d0678a40652fd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -16,7 +16,7 @@ mod proc_macros; use std::{iter, ops::Range, sync}; -use base_db::SourceDatabase; +use base_db::RootQueryDb; use expect_test::Expect; use hir_expand::{ db::ExpandDatabase, @@ -26,6 +26,7 @@ use hir_expand::{ }; use intern::Symbol; use itertools::Itertools; +use salsa::AsDynDatabase; use span::{Edition, Span}; use stdx::{format_to, format_to_acc}; use syntax::{ @@ -63,9 +64,13 @@ fn check_errors(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) MacroCallKind::Derive { ast_id, .. } => ast_id.map(|it| it.erase()), MacroCallKind::Attr { ast_id, .. } => ast_id.map(|it| it.erase()), }; - let ast = db - .parse(ast_id.file_id.file_id().expect("macros inside macros are not supported")) - .syntax_node(); + + let editioned_file_id = + ast_id.file_id.file_id().expect("macros inside macros are not supported"); + let editioned_file_id = + base_db::EditionedFileId::new(db.as_dyn_database(), editioned_file_id); + + let ast = db.parse(editioned_file_id).syntax_node(); let ast_id_map = db.ast_id_map(ast_id.file_id); let node = ast_id_map.get_erased(ast_id.value).to_node(&ast); Some((node.text_range(), errors)) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs index a43c0eb9d70bb..650807fb4acf1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs @@ -181,9 +181,9 @@ fn foo(&self) { self.0. 1; } -fn#0:1@45..47#2# foo#0:1@48..51#2#(#0:1@51..52#2#�:1@52..53#2#self#0:1@53..57#2# )#0:1@57..58#2# {#0:1@59..60#2# - self#0:1@65..69#2# .#0:1@69..70#2#0#0:1@70..71#2#.#0:1@71..72#2#1#0:1@73..74#2#;#0:1@74..75#2# -}#0:1@76..77#2#"#]], +fn#0:1@45..47#4294967037# foo#0:1@48..51#4294967037#(#0:1@51..52#4294967037#�:1@52..53#4294967037#self#0:1@53..57#4294967037# )#0:1@57..58#4294967037# {#0:1@59..60#4294967037# + self#0:1@65..69#4294967037# .#0:1@69..70#4294967037#0#0:1@70..71#4294967037#.#0:1@71..72#4294967037#1#0:1@73..74#4294967037#;#0:1@74..75#4294967037# +}#0:1@76..77#4294967037#"#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index 3b6e3c5916e32..5b3d75c4ee669 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -295,9 +295,12 @@ impl ModuleOrigin { /// That is, a file or a `mod foo {}` with items. pub fn definition_source(&self, db: &dyn DefDatabase) -> InFile { match self { - &ModuleOrigin::File { definition, .. } | &ModuleOrigin::CrateRoot { definition } => { + &ModuleOrigin::File { definition: editioned_file_id, .. } + | &ModuleOrigin::CrateRoot { definition: editioned_file_id } => { + let definition = base_db::EditionedFileId::new(db, editioned_file_id); + let sf = db.parse(definition).tree(); - InFile::new(definition.into(), ModuleSource::SourceFile(sf)) + InFile::new(editioned_file_id.into(), ModuleSource::SourceFile(sf)) } &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new( definition_tree_id.file_id(), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 16f3fd56eb9ed..bf013c25ef5e3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -376,7 +376,7 @@ impl DefCollector<'_> { 'resolve_attr: loop { let _p = tracing::info_span!("resolve_macros loop").entered(); 'resolve_macros: loop { - self.db.unwind_if_cancelled(); + self.db.unwind_if_revision_cancelled(); { let _p = tracing::info_span!("resolve_imports loop").entered(); @@ -977,7 +977,7 @@ impl DefCollector<'_> { vis: Visibility, import: Option, ) { - self.db.unwind_if_cancelled(); + self.db.unwind_if_revision_cancelled(); self.update_recursive(module_id, resolutions, vis, import, 0) } @@ -2517,7 +2517,7 @@ impl ModCollector<'_, '_> { #[cfg(test)] mod tests { - use base_db::SourceDatabase; + use base_db::RootQueryDb; use test_fixture::WithFixture; use crate::{nameres::DefMapCrateData, test_db::TestDB}; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs index 17d09bcbd0478..a012eb6ff7eb9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs @@ -1,6 +1,6 @@ //! This module resolves `mod foo;` declaration to file. use arrayvec::ArrayVec; -use base_db::AnchoredPath; +use base_db::{AnchoredPath, RootQueryDb}; use hir_expand::{name::Name, HirFileIdExt}; use span::EditionedFileId; @@ -80,7 +80,8 @@ impl ModDir { let orig_file_id = file_id.original_file_respecting_includes(db.upcast()); for candidate in candidate_files.iter() { let path = AnchoredPath { anchor: orig_file_id.file_id(), path: candidate.as_str() }; - if let Some(file_id) = db.resolve_path(path) { + if let Some(file_id) = base_db::Upcast::::upcast(db).resolve_path(path) + { let is_mod_rs = candidate.ends_with("/mod.rs"); let root_dir_owner = is_mod_rs || attr_path.is_some(); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs index 73fc6787bfe81..7c9fad91865db 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs @@ -4,7 +4,7 @@ mod macros; mod mod_resolution; mod primitives; -use base_db::SourceDatabase; +use base_db::RootQueryDb; use expect_test::{expect, Expect}; use test_fixture::WithFixture; use triomphe::Arc; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs index c8b7ec463a0fd..cd590205766da 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs @@ -1,4 +1,4 @@ -use base_db::SourceDatabaseFileInputExt as _; +use base_db::SourceDatabase; use test_fixture::WithFixture; use crate::{db::DefDatabase, nameres::tests::TestDB, AdtId, ModuleDefId}; @@ -255,10 +255,10 @@ m!(Z); assert_eq!(module_data.scope.resolutions().count(), 4); }); let n_recalculated_item_trees = - events.iter().filter(|it| it.contains("item_tree(")).count(); + events.iter().filter(|it| it.contains("file_item_tree_shim")).count(); assert_eq!(n_recalculated_item_trees, 6); let n_reparsed_macros = - events.iter().filter(|it| it.contains("parse_macro_expansion(")).count(); + events.iter().filter(|it| it.contains("parse_macro_expansion_shim")).count(); assert_eq!(n_reparsed_macros, 3); } @@ -276,10 +276,11 @@ m!(Z); let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); assert_eq!(module_data.scope.resolutions().count(), 4); }); - let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); - assert_eq!(n_recalculated_item_trees, 1); + let n_recalculated_item_trees = + events.iter().filter(|it| it.contains("file_item_tree_shim")).count(); + assert_eq!(n_recalculated_item_trees, 0); let n_reparsed_macros = - events.iter().filter(|it| it.contains("parse_macro_expansion(")).count(); + events.iter().filter(|it| it.contains("parse_macro_expansion_shim")).count(); assert_eq!(n_reparsed_macros, 0); } } @@ -310,14 +311,15 @@ pub type Ty = (); let events = db.log_executed(|| { db.file_item_tree(pos.file_id.into()); }); - let n_calculated_item_trees = events.iter().filter(|it| it.contains("item_tree(")).count(); + let n_calculated_item_trees = + events.iter().filter(|it| it.contains("file_item_tree_shim")).count(); assert_eq!(n_calculated_item_trees, 1); - let n_parsed_files = events.iter().filter(|it| it.contains("parse(")).count(); + let n_parsed_files = events.iter().filter(|it| it.contains("parse")).count(); assert_eq!(n_parsed_files, 1); } - // Delete the parse tree. - base_db::ParseQuery.in_db(&db).purge(); + // FIXME(salsa-transition): bring this back + // base_db::ParseQuery.in_db(&db).purge(); { let events = db.log_executed(|| { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs index 3b7e7653fba55..7a6d6973298b7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs @@ -185,7 +185,7 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option< if segments.len() == 1 && kind == PathKind::Plain { if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { let syn_ctxt = ctx.span_map().span_for_range(path.segment()?.syntax().text_range()).ctx; - if let Some(macro_call_id) = ctx.db.lookup_intern_syntax_context(syn_ctxt).outer_expn { + if let Some(macro_call_id) = syn_ctxt.outer_expn(ctx.db) { if ctx.db.lookup_intern_macro_call(macro_call_id).def.local_inner { kind = match resolve_crate_root(ctx.db.upcast(), syn_ctxt) { Some(crate_root) => PathKind::DollarCrate(crate_root), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index a2e6e4cc04368..f4773de08555b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -207,7 +207,13 @@ impl Resolver { return self.module_scope.resolve_path_in_type_ns(db, path); } - let remaining_idx = || if path.segments().len() == 1 { None } else { Some(1) }; + let remaining_idx = || { + if path.segments().len() == 1 { + None + } else { + Some(1) + } + }; for scope in self.scopes() { match scope { @@ -314,7 +320,7 @@ impl Resolver { None, ), ResolvePathResultPrefixInfo::default(), - )) + )); } Path::LangItem(l, Some(_)) => { let type_ns = match *l { @@ -889,11 +895,10 @@ fn handle_macro_def_scope( // A macro is allowed to refer to variables from before its declaration. // Therefore, if we got to the rib of its declaration, give up its hygiene // and use its parent expansion. - let parent_ctx = db.lookup_intern_syntax_context(*parent_ctx); - *hygiene_id = HygieneId::new(parent_ctx.opaque_and_semitransparent); - *hygiene_info = parent_ctx.outer_expn.map(|expansion| { + *hygiene_id = HygieneId::new(parent_ctx.opaque_and_semitransparent(db)); + *hygiene_info = parent_ctx.outer_expn(db).map(|expansion| { let expansion = db.lookup_intern_macro_call(expansion); - (parent_ctx.parent, expansion.def) + (parent_ctx.parent(db), expansion.def) }); } } @@ -905,10 +910,10 @@ fn hygiene_info( hygiene_id: HygieneId, ) -> Option<(SyntaxContextId, MacroDefId)> { if !hygiene_id.is_root() { - let ctx = hygiene_id.lookup(db); - ctx.outer_expn.map(|expansion| { + let ctx = hygiene_id.lookup(); + ctx.outer_expn(db).map(|expansion| { let expansion = db.lookup_intern_macro_call(expansion); - (ctx.parent, expansion.def) + (ctx.parent(db), expansion.def) }) } else { None @@ -1438,7 +1443,7 @@ impl HasResolver for MacroRulesId { fn lookup_resolver<'db>( db: &(dyn DefDatabase + 'db), lookup: impl Lookup< - Database<'db> = dyn DefDatabase + 'db, + Database = dyn DefDatabase, Data = impl ItemTreeLoc, >, ) -> Resolver { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs index 54e6c1fd206d8..b6f08c0cafdbb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs @@ -3,10 +3,11 @@ use std::{fmt, panic, sync::Mutex}; use base_db::{ - ra_salsa::{self, Durability}, - AnchoredPath, CrateId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast, + CrateId, FileSourceRootInput, FileText, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId, + SourceRootInput, Upcast, }; use hir_expand::{db::ExpandDatabase, files::FilePosition, InFile}; +use salsa::{AsDynDatabase, Durability}; use span::{EditionedFileId, FileId}; use syntax::{algo, ast, AstNode}; use triomphe::Arc; @@ -18,43 +19,58 @@ use crate::{ LocalModuleId, Lookup, ModuleDefId, ModuleId, }; -#[ra_salsa::database( - base_db::SourceRootDatabaseStorage, - base_db::SourceDatabaseStorage, - hir_expand::db::ExpandDatabaseStorage, - crate::db::InternDatabaseStorage, - crate::db::DefDatabaseStorage -)] +#[salsa::db] +#[derive(Clone)] pub(crate) struct TestDB { - storage: ra_salsa::Storage, - events: Mutex>>, + storage: salsa::Storage, + files: Arc, + events: Arc>>>, } impl Default for TestDB { fn default() -> Self { - let mut this = Self { storage: Default::default(), events: Default::default() }; - this.setup_syntax_context_root(); + let mut this = Self { + storage: Default::default(), + events: Default::default(), + files: Default::default(), + }; this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); this } } impl Upcast for TestDB { + #[inline] fn upcast(&self) -> &(dyn ExpandDatabase + 'static) { self } } impl Upcast for TestDB { + #[inline] fn upcast(&self) -> &(dyn DefDatabase + 'static) { self } } -impl ra_salsa::Database for TestDB { - fn salsa_event(&self, event: ra_salsa::Event) { +impl Upcast for TestDB { + fn upcast(&self) -> &(dyn RootQueryDb + 'static) { + self + } +} + +impl Upcast for TestDB { + fn upcast(&self) -> &(dyn SourceDatabase + 'static) { + self + } +} + +#[salsa::db] +impl salsa::Database for TestDB { + fn salsa_event(&self, event: &dyn std::ops::Fn() -> salsa::Event) { let mut events = self.events.lock().unwrap(); if let Some(events) = &mut *events { + let event = event(); events.push(event); } } @@ -68,12 +84,54 @@ impl fmt::Debug for TestDB { impl panic::RefUnwindSafe for TestDB {} -impl FileLoader for TestDB { - fn resolve_path(&self, path: AnchoredPath<'_>) -> Option { - FileLoaderDelegate(self).resolve_path(path) +#[salsa::db] +impl SourceDatabase for TestDB { + fn file_text(&self, file_id: base_db::FileId) -> FileText { + self.files.file_text(file_id) } - fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { - FileLoaderDelegate(self).relevant_crates(file_id) + + fn set_file_text(&mut self, file_id: base_db::FileId, text: &str) { + let files = Arc::clone(&self.files); + files.set_file_text(self, file_id, text); + } + + fn set_file_text_with_durability( + &mut self, + file_id: base_db::FileId, + text: &str, + durability: Durability, + ) { + let files = Arc::clone(&self.files); + files.set_file_text_with_durability(self, file_id, text, durability); + } + + /// Source root of the file. + fn source_root(&self, source_root_id: SourceRootId) -> SourceRootInput { + self.files.source_root(source_root_id) + } + + fn set_source_root_with_durability( + &mut self, + source_root_id: SourceRootId, + source_root: Arc, + durability: Durability, + ) { + let files = Arc::clone(&self.files); + files.set_source_root_with_durability(self, source_root_id, source_root, durability); + } + + fn file_source_root(&self, id: base_db::FileId) -> FileSourceRootInput { + self.files.file_source_root(id) + } + + fn set_file_source_root_with_durability( + &mut self, + id: base_db::FileId, + source_root_id: SourceRootId, + durability: Durability, + ) { + let files = Arc::clone(&self.files); + files.set_file_source_root_with_durability(self, id, source_root_id, durability); } } @@ -92,8 +150,10 @@ impl TestDB { } pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { + let db = >::upcast(self); + for &krate in self.relevant_crates(file_id).iter() { - let crate_def_map = self.crate_def_map(krate); + let crate_def_map = db.crate_def_map(krate); for (local_id, data) in crate_def_map.modules() { if data.origin.file_id().map(EditionedFileId::file_id) == Some(file_id) { return crate_def_map.module_id(local_id); @@ -104,8 +164,10 @@ impl TestDB { } pub(crate) fn module_at_position(&self, position: FilePosition) -> ModuleId { + let db = >::upcast(self); + let file_module = self.module_for_file(position.file_id.file_id()); - let mut def_map = file_module.def_map(self); + let mut def_map = file_module.def_map(db); let module = self.mod_at_position(&def_map, position); def_map = match self.block_at_position(&def_map, position) { @@ -128,10 +190,11 @@ impl TestDB { /// Finds the smallest/innermost module in `def_map` containing `position`. fn mod_at_position(&self, def_map: &DefMap, position: FilePosition) -> LocalModuleId { + let db = >::upcast(self); let mut size = None; let mut res = DefMap::ROOT; for (module, data) in def_map.modules() { - let src = data.definition_source(self); + let src = data.definition_source(db); if src.file_id != position.file_id { continue; } @@ -167,17 +230,18 @@ impl TestDB { } fn block_at_position(&self, def_map: &DefMap, position: FilePosition) -> Option> { + let db = >::upcast(self); // Find the smallest (innermost) function in `def_map` containing the cursor. let mut size = None; let mut fn_def = None; for (_, module) in def_map.modules() { - let file_id = module.definition_source(self).file_id; + let file_id = module.definition_source(db).file_id; if file_id != position.file_id { continue; } for decl in module.scope.declarations() { if let ModuleDefId::FunctionId(it) = decl { - let range = it.lookup(self).source(self).value.syntax().text_range(); + let range = it.lookup(db).source(db).value.syntax().text_range(); if !range.contains(position.offset) { continue; @@ -203,10 +267,13 @@ impl TestDB { // Find the innermost block expression that has a `DefMap`. let def_with_body = fn_def?.into(); - let (_, source_map) = self.body_with_source_map(def_with_body); - let scopes = self.expr_scopes(def_with_body); - let root = self.parse(position.file_id); + let source_map = db.body_with_source_map(def_with_body).1; + let scopes = db.expr_scopes(def_with_body); + + let editioned_file_id_wrapper = + base_db::EditionedFileId::new(db.as_dyn_database(), position.file_id); + let root = db.parse(editioned_file_id_wrapper); let scope_iter = algo::ancestors_at_offset(&root.syntax_node(), position.offset) .filter_map(|node| { let block = ast::BlockExpr::cast(node)?; @@ -223,7 +290,7 @@ impl TestDB { let mut containing_blocks = scopes.scope_chain(Some(scope)).filter_map(|scope| scopes.block(scope)); - if let Some(block) = containing_blocks.next().map(|block| self.block_def_map(block)) { + if let Some(block) = containing_blocks.next().map(|block| db.block_def_map(block)) { return Some(block); } } @@ -231,7 +298,7 @@ impl TestDB { None } - pub(crate) fn log(&self, f: impl FnOnce()) -> Vec { + pub(crate) fn log(&self, f: impl FnOnce()) -> Vec { *self.events.lock().unwrap() = Some(Vec::new()); f(); self.events.lock().unwrap().take().unwrap() @@ -244,8 +311,11 @@ impl TestDB { .filter_map(|e| match e.kind { // This is pretty horrible, but `Debug` is the only way to inspect // QueryDescriptor at the moment. - ra_salsa::EventKind::WillExecute { database_key } => { - Some(format!("{:?}", database_key.debug(self))) + salsa::EventKind::WillExecute { database_key } => { + let ingredient = self + .as_dyn_database() + .ingredient_debug_name(database_key.ingredient_index()); + Some(ingredient.to_string()) } _ => None, }) diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml index 7d561e0527d91..607199a62443d 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml @@ -21,6 +21,8 @@ itertools.workspace = true hashbrown.workspace = true smallvec.workspace = true triomphe.workspace = true +query-group.workspace = true +salsa.workspace = true # local deps stdx.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs index 55242ab3e57d1..d8b3f40e8f413 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs @@ -3,9 +3,12 @@ use base_db::AnchoredPath; use cfg::CfgExpr; use either::Either; -use intern::{sym, Symbol}; +use intern::{ + sym::{self}, + Symbol, +}; use mbe::{expect_fragment, DelimiterKind}; -use span::{Edition, EditionedFileId, Span}; +use span::{Edition, EditionedFileId, FileId, Span}; use stdx::format_to; use syntax::{ format_smolstr, @@ -401,7 +404,7 @@ fn use_panic_2021(db: &dyn ExpandDatabase, span: Span) -> bool { // stack that does not have #[allow_internal_unstable(edition_panic)]. // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.) loop { - let Some(expn) = db.lookup_intern_syntax_context(span.ctx).outer_expn else { + let Some(expn) = span.ctx.outer_expn(db) else { break false; }; let expn = db.lookup_intern_macro_call(expn); @@ -656,10 +659,10 @@ fn relative_file( allow_recursion: bool, err_span: Span, ) -> Result { - let lookup = call_id.lookup(db); + let lookup = db.lookup_intern_macro_call(call_id); let call_site = lookup.kind.file_id().original_file_respecting_includes(db).file_id(); let path = AnchoredPath { anchor: call_site, path: path_str }; - let res = db + let res: FileId = db .resolve_path(path) .ok_or_else(|| ExpandError::other(err_span, format!("failed to load file `{path_str}`")))?; // Prevent include itself @@ -725,8 +728,10 @@ fn include_expand( tt: &tt::TopSubtree, span: Span, ) -> ExpandResult { - let file_id = match include_input_to_file_id(db, arg_id, tt) { - Ok(it) => it, + let (file_id_wrapper, editioned_file_id) = match include_input_to_file_id(db, arg_id, tt) { + Ok(editioned_file_id) => { + (base_db::EditionedFileId::new(db, editioned_file_id), editioned_file_id) + } Err(e) => { return ExpandResult::new( tt::TopSubtree::empty(DelimSpan { open: span, close: span }), @@ -734,10 +739,10 @@ fn include_expand( ) } }; - let span_map = db.real_span_map(file_id); + let span_map = db.real_span_map(editioned_file_id); // FIXME: Parse errors ExpandResult::ok(syntax_node_to_token_tree( - &db.parse(file_id).syntax_node(), + &db.parse(file_id_wrapper).syntax_node(), SpanMap::RealSpanMap(span_map), span, syntax_bridge::DocCommentDesugarMode::ProcMacro, @@ -800,7 +805,7 @@ fn include_str_expand( }; let text = db.file_text(file_id.file_id()); - let text = &*text; + let text = &*text.text(db); ExpandResult::ok(quote!(span =>#text)) } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs index 9b637fc768446..a961df181db23 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs @@ -277,8 +277,8 @@ mod tests { assert_eq!(quoted.to_string(), "hello"); let t = format!("{quoted:#?}"); expect![[r#" - SUBTREE $$ 937550:0@0..0#2 937550:0@0..0#2 - IDENT hello 937550:0@0..0#2"#]] + SUBTREE $$ 937550:0@0..0#4294967037 937550:0@0..0#4294967037 + IDENT hello 937550:0@0..0#4294967037"#]] .assert_eq(&t); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs index 1fdf251ba5210..7a42d6626010b 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs @@ -1,10 +1,8 @@ //! Defines a unit of change that can applied to the database to get the next //! state. Changes are transactional. -use base_db::{ - ra_salsa::Durability, CrateGraph, CrateId, CrateWorkspaceData, FileChange, SourceRoot, - SourceRootDatabase, -}; +use base_db::{CrateGraph, CrateId, CrateWorkspaceData, FileChange, SourceRoot}; use rustc_hash::FxHashMap; +use salsa::Durability; use span::FileId; use triomphe::Arc; @@ -21,7 +19,7 @@ impl ChangeWithProcMacros { Self::default() } - pub fn apply(self, db: &mut (impl ExpandDatabase + SourceRootDatabase)) { + pub fn apply(self, db: &mut impl ExpandDatabase) { self.source_change.apply(db); if let Some(proc_macros) = self.proc_macros { db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 8ca8bf1ba4a6e..2f97cceab554a 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -1,10 +1,14 @@ //! Defines database & queries for macro expansion. -use base_db::{ra_salsa, CrateId, SourceDatabase}; +use base_db::{CrateId, RootQueryDb}; use either::Either; use mbe::MatchedArmIndex; use rustc_hash::FxHashSet; -use span::{AstIdMap, Edition, EditionedFileId, Span, SyntaxContextData, SyntaxContextId}; +use salsa::plumbing::AsId; +use span::{ + AstIdMap, Edition, EditionedFileId, HirFileId, HirFileIdRepr, MacroCallId, MacroFileId, Span, + SyntaxContextId, +}; use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T}; use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode}; use triomphe::Arc; @@ -19,12 +23,11 @@ use crate::{ span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt, SyntaxContextExt as _, }, - proc_macro::ProcMacros, - span_map::{RealSpanMap, SpanMap, SpanMapRef}, - tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, - CustomProcMacroExpander, EagerCallInfo, EagerExpander, ExpandError, ExpandResult, ExpandTo, - ExpansionSpanMap, HirFileId, HirFileIdRepr, Lookup, MacroCallId, MacroCallKind, MacroCallLoc, - MacroDefId, MacroDefKind, MacroFileId, + proc_macro::{CustomProcMacroExpander, ProcMacros}, + span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef}, + tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, + EagerExpander, ExpandError, ExpandResult, ExpandTo, MacroCallKind, MacroCallLoc, MacroDefId, + MacroDefKind, }; /// This is just to ensure the types of smart_macro_arg and macro_arg are the same type MacroArgResult = (Arc, SyntaxFixupUndoInfo, Span); @@ -52,32 +55,32 @@ pub enum TokenExpander { ProcMacro(CustomProcMacroExpander), } -#[ra_salsa::query_group(ExpandDatabaseStorage)] -pub trait ExpandDatabase: SourceDatabase { +#[query_group::query_group] +pub trait ExpandDatabase: RootQueryDb { /// The proc macros. - #[ra_salsa::input] + #[salsa::input] fn proc_macros(&self) -> Arc; fn ast_id_map(&self, file_id: HirFileId) -> Arc; - /// Main public API -- parses a hir file, not caring whether it's a real - /// file or a macro expansion. - #[ra_salsa::transparent] + #[salsa::transparent] fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode; + /// Implementation for the macro case. - #[ra_salsa::lru] + #[salsa::lru(512)] fn parse_macro_expansion( &self, - macro_file: MacroFileId, + macro_file: span::MacroFileId, ) -> ExpandResult<(Parse, Arc)>; - #[ra_salsa::transparent] - #[ra_salsa::invoke(SpanMap::new)] + + #[salsa::transparent] + #[salsa::invoke(SpanMap::new)] fn span_map(&self, file_id: HirFileId) -> SpanMap; - #[ra_salsa::transparent] - #[ra_salsa::invoke(crate::span_map::expansion_span_map)] + #[salsa::transparent] + #[salsa::invoke(crate::span_map::expansion_span_map)] fn expansion_span_map(&self, file_id: MacroFileId) -> Arc; - #[ra_salsa::invoke(crate::span_map::real_span_map)] + #[salsa::invoke(crate::span_map::real_span_map)] fn real_span_map(&self, file_id: EditionedFileId) -> Arc; /// Macro ids. That's probably the tricksiest bit in rust-analyzer, and the @@ -85,43 +88,47 @@ pub trait ExpandDatabase: SourceDatabase { /// /// We encode macro definitions into ids of macro calls, this what allows us /// to be incremental. - #[ra_salsa::interned] + #[salsa::transparent] fn intern_macro_call(&self, macro_call: MacroCallLoc) -> MacroCallId; - #[ra_salsa::interned] - fn intern_syntax_context(&self, ctx: SyntaxContextData) -> SyntaxContextId; + #[salsa::transparent] + fn lookup_intern_macro_call(&self, macro_call: MacroCallId) -> MacroCallLoc; - #[ra_salsa::transparent] - fn setup_syntax_context_root(&self) -> (); - #[ra_salsa::transparent] - #[ra_salsa::invoke(crate::hygiene::dump_syntax_contexts)] + #[salsa::transparent] + #[salsa::invoke(crate::hygiene::dump_syntax_contexts)] fn dump_syntax_contexts(&self) -> String; /// Lowers syntactic macro call to a token tree representation. That's a firewall /// query, only typing in the macro call itself changes the returned /// subtree. #[deprecated = "calling this is incorrect, call `macro_arg_considering_derives` instead"] + #[salsa::invoke(macro_arg)] fn macro_arg(&self, id: MacroCallId) -> MacroArgResult; - #[ra_salsa::transparent] + + #[salsa::transparent] fn macro_arg_considering_derives( &self, id: MacroCallId, kind: &MacroCallKind, ) -> MacroArgResult; + /// Fetches the expander for this macro. - #[ra_salsa::transparent] - #[ra_salsa::invoke(TokenExpander::macro_expander)] + #[salsa::transparent] + #[salsa::invoke(TokenExpander::macro_expander)] fn macro_expander(&self, id: MacroDefId) -> TokenExpander; + /// Fetches (and compiles) the expander of this decl macro. - #[ra_salsa::invoke(DeclarativeMacroExpander::expander)] + #[salsa::invoke(DeclarativeMacroExpander::expander)] fn decl_macro_expander( &self, def_crate: CrateId, id: AstId, ) -> Arc; + /// Special case of the previous query for procedural macros. We can't LRU /// proc macros, since they are not deterministic in general, and /// non-determinism breaks salsa in a very, very, very bad way. /// @edwin0cheng heroically debugged this once! See #4315 for details + #[salsa::invoke(expand_proc_macro)] fn expand_proc_macro(&self, call: MacroCallId) -> ExpandResult>; /// Retrieves the span to be used for a proc-macro expansions spans. /// This is a firewall query as it requires parsing the file, which we don't want proc-macros to @@ -129,22 +136,42 @@ pub trait ExpandDatabase: SourceDatabase { /// parse queries being LRU cached. If they weren't the invalidations would only happen if the /// user wrote in the file that defines the proc-macro. fn proc_macro_span(&self, fun: AstId) -> Span; + /// Firewall query that returns the errors from the `parse_macro_expansion` query. + #[salsa::invoke(parse_macro_expansion_error)] fn parse_macro_expansion_error( &self, macro_call: MacroCallId, ) -> Option>>>; - #[ra_salsa::transparent] + + #[salsa::transparent] fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContextId; } +#[salsa::interned(no_lifetime, id = span::MacroCallId)] +pub struct MacroCallWrapper { + pub loc: MacroCallLoc, +} + +fn intern_macro_call(db: &dyn ExpandDatabase, macro_call: MacroCallLoc) -> MacroCallId { + MacroCallWrapper::new(db, macro_call).0 +} + +fn lookup_intern_macro_call(db: &dyn ExpandDatabase, macro_call: MacroCallId) -> MacroCallLoc { + MacroCallWrapper::ingredient(db).data(db.as_dyn_database(), macro_call.as_id()).0.clone() +} + +#[salsa::interned(no_lifetime, id = span::SyntaxContextId)] +pub struct SyntaxContextWrapper { + pub data: SyntaxContextId, +} + fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId, edition: Edition) -> SyntaxContextId { match file.repr() { HirFileIdRepr::FileId(_) => SyntaxContextId::root(edition), HirFileIdRepr::MacroFile(m) => { - db.macro_arg_considering_derives(m.macro_call_id, &m.macro_call_id.lookup(db).kind) - .2 - .ctx + let kind = db.lookup_intern_macro_call(m.macro_call_id).kind; + db.macro_arg_considering_derives(m.macro_call_id, &kind).2.ctx } } } @@ -322,9 +349,15 @@ fn ast_id_map(db: &dyn ExpandDatabase, file_id: span::HirFileId) -> triomphe::Ar triomphe::Arc::new(AstIdMap::from_source(&db.parse_or_expand(file_id))) } +/// Main public API -- parses a hir file, not caring whether it's a real +/// file or a macro expansion. fn parse_or_expand(db: &dyn ExpandDatabase, file_id: HirFileId) -> SyntaxNode { match file_id.repr() { - HirFileIdRepr::FileId(file_id) => db.parse(file_id).syntax_node(), + HirFileIdRepr::FileId(editioned_file_id) => { + let file_id = base_db::EditionedFileId::new(db, editioned_file_id); + db.parse(file_id).syntax_node() + } + HirFileIdRepr::MacroFile(macro_file) => { db.parse_macro_expansion(macro_file).value.0.syntax_node() } @@ -376,8 +409,13 @@ pub(crate) fn parse_with_map( file_id: HirFileId, ) -> (Parse, SpanMap) { match file_id.repr() { - HirFileIdRepr::FileId(file_id) => { - (db.parse(file_id).to_syntax(), SpanMap::RealSpanMap(db.real_span_map(file_id))) + HirFileIdRepr::FileId(editioned_file_id) => { + let file_id = base_db::EditionedFileId::new(db, editioned_file_id); + + ( + db.parse(file_id).to_syntax(), + SpanMap::RealSpanMap(db.real_span_map(editioned_file_id)), + ) } HirFileIdRepr::MacroFile(macro_file) => { let (parse, map) = db.parse_macro_expansion(macro_file).value; @@ -597,7 +635,7 @@ fn macro_expand( let (ExpandResult { value: (tt, matched_arm), err }, span) = match loc.def.kind { MacroDefKind::ProcMacro(..) => { - return db.expand_proc_macro(macro_call_id).map(CowArc::Arc).zip_val(None) + return db.expand_proc_macro(macro_call_id).map(CowArc::Arc).zip_val(None); } _ => { let (macro_arg, undo_info, span) = @@ -728,12 +766,7 @@ pub(crate) fn token_tree_to_syntax_node( ExpandTo::Type => syntax_bridge::TopEntryPoint::Type, ExpandTo::Expr => syntax_bridge::TopEntryPoint::Expr, }; - syntax_bridge::token_tree_to_syntax_node( - tt, - entry_point, - &mut |ctx| ctx.lookup(db).edition, - edition, - ) + syntax_bridge::token_tree_to_syntax_node(tt, entry_point, &mut |ctx| ctx.edition(db), edition) } fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> { @@ -754,9 +787,3 @@ fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> { }) } } - -fn setup_syntax_context_root(db: &dyn ExpandDatabase) { - for edition in Edition::iter() { - db.intern_syntax_context(SyntaxContextData::root(edition)); - } -} diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs index fef77acb7bbb7..91cbbc373649c 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs @@ -102,12 +102,13 @@ impl DeclarativeMacroExpander { }; let ctx_edition = |ctx: SyntaxContextId| { let crate_graph = db.crate_graph(); + if ctx.is_root() { crate_graph[def_crate].edition } else { - let data = db.lookup_intern_syntax_context(ctx); // UNWRAP-SAFETY: Only the root context has no outer expansion - crate_graph[data.outer_expn.unwrap().lookup(db).def.krate].edition + let krate = db.lookup_intern_macro_call(ctx.outer_expn(db).unwrap()).def.krate; + crate_graph[krate].edition } }; let (mac, transparency) = match id.to_ptr(db).to_node(&root) { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs index f476d1b564c4c..4a98b455cab83 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs @@ -28,7 +28,7 @@ use crate::{ ast::{self, AstNode}, db::ExpandDatabase, mod_path::ModPath, - AstId, EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, Intern, + AstId, EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, }; @@ -47,13 +47,13 @@ pub fn expand_eager_macro_input( // When `lazy_expand` is called, its *parent* file must already exist. // Here we store an eager macro id for the argument expanded subtree // for that purpose. - let arg_id = MacroCallLoc { + let loc = MacroCallLoc { def, krate, kind: MacroCallKind::FnLike { ast_id, expand_to: ExpandTo::Expr, eager: None }, ctxt: call_site, - } - .intern(db); + }; + let arg_id = db.intern_macro_call(loc); #[allow(deprecated)] // builtin eager macros are never derives let (_, _, span) = db.macro_arg(arg_id); let ExpandResult { value: (arg_exp, arg_exp_map), err: parse_err } = @@ -107,7 +107,7 @@ pub fn expand_eager_macro_input( ctxt: call_site, }; - ExpandResult { value: Some(loc.intern(db)), err } + ExpandResult { value: Some(db.intern_macro_call(loc)), err } } fn lazy_expand( diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs index f3bcc77268224..5810d11338cb9 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs @@ -159,7 +159,9 @@ trait FileIdToSyntax: Copy { impl FileIdToSyntax for EditionedFileId { fn file_syntax(self, db: &dyn db::ExpandDatabase) -> SyntaxNode { - db.parse(self).syntax_node() + let file_id = base_db::EditionedFileId::new(db, self); + + db.parse(file_id).syntax_node() } } impl FileIdToSyntax for MacroFileId { @@ -274,7 +276,7 @@ impl> InFile { // as we don't have node inputs otherwise and therefore can't find an `N` node in the input let file_id = match self.file_id.repr() { HirFileIdRepr::FileId(file_id) => { - return Some(InRealFile { file_id, value: self.value.borrow().clone() }) + return Some(InRealFile { file_id, value: self.value.borrow().clone() }); } HirFileIdRepr::MacroFile(m) if matches!(m.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn) => @@ -284,12 +286,14 @@ impl> InFile { _ => return None, }; - let FileRange { file_id, range } = map_node_range_up_rooted( + let FileRange { file_id: editioned_file_id, range } = map_node_range_up_rooted( db, &db.expansion_span_map(file_id), self.value.borrow().text_range(), )?; + let file_id = base_db::EditionedFileId::new(db, editioned_file_id); + let kind = self.kind(); let value = db .parse(file_id) @@ -298,7 +302,7 @@ impl> InFile { .ancestors() .take_while(|it| it.text_range() == range) .find(|it| it.kind() == kind)?; - Some(InRealFile::new(file_id, value)) + Some(InRealFile::new(editioned_file_id, value)) } } @@ -453,7 +457,7 @@ impl InFile { // as we don't have node inputs otherwise and therefore can't find an `N` node in the input let file_id = match self.file_id.repr() { HirFileIdRepr::FileId(file_id) => { - return Some(InRealFile { file_id, value: self.value }) + return Some(InRealFile { file_id, value: self.value }); } HirFileIdRepr::MacroFile(m) => m, }; @@ -461,16 +465,18 @@ impl InFile { return None; } - let FileRange { file_id, range } = map_node_range_up_rooted( + let FileRange { file_id: editioned_file_id, range } = map_node_range_up_rooted( db, &db.expansion_span_map(file_id), self.value.syntax().text_range(), )?; + let file_id = base_db::EditionedFileId::new(db, editioned_file_id); + // FIXME: This heuristic is brittle and with the right macro may select completely unrelated nodes? let anc = db.parse(file_id).syntax_node().covering_element(range); let value = anc.ancestors().find_map(N::cast)?; - Some(InRealFile::new(file_id, value)) + Some(InRealFile::new(editioned_file_id, value)) } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs index fe05af0ac9d31..b53468ccacdca 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs @@ -22,11 +22,11 @@ // FIXME: Move this into the span crate? Not quite possible today as that depends on `MacroCallLoc` // which contains a bunch of unrelated things -use std::iter; +use std::{convert::identity, iter}; -use span::{Edition, MacroCallId, Span, SyntaxContextData, SyntaxContextId}; +use span::{Edition, MacroCallId, Span, SyntaxContextId}; -use crate::db::{ExpandDatabase, InternSyntaxContextQuery}; +use crate::db::{ExpandDatabase, MacroCallWrapper}; pub use span::Transparency; @@ -72,8 +72,8 @@ fn span_with_ctxt_from_mark( pub(super) fn apply_mark( db: &dyn ExpandDatabase, - ctxt: SyntaxContextId, - call_id: MacroCallId, + ctxt: span::SyntaxContextId, + call_id: span::MacroCallId, transparency: Transparency, edition: Edition, ) -> SyntaxContextId { @@ -114,92 +114,75 @@ fn apply_mark_internal( transparency: Transparency, edition: Edition, ) -> SyntaxContextId { - use base_db::ra_salsa; - let call_id = Some(call_id); - let syntax_context_data = db.lookup_intern_syntax_context(ctxt); - let mut opaque = syntax_context_data.opaque; - let mut opaque_and_semitransparent = syntax_context_data.opaque_and_semitransparent; + let mut opaque = ctxt.opaque(db); + let mut opaque_and_semitransparent = ctxt.opaque_and_semitransparent(db); if transparency >= Transparency::Opaque { let parent = opaque; - opaque = ra_salsa::plumbing::get_query_table::(db).get_or_insert( - (parent, call_id, transparency, edition), - |new_opaque| SyntaxContextData { - outer_expn: call_id, - outer_transparency: transparency, - parent, - opaque: new_opaque, - opaque_and_semitransparent: new_opaque, - edition, - }, - ); + opaque = + SyntaxContextId::new(db, call_id, transparency, edition, parent, identity, identity); } if transparency >= Transparency::SemiTransparent { let parent = opaque_and_semitransparent; opaque_and_semitransparent = - ra_salsa::plumbing::get_query_table::(db).get_or_insert( - (parent, call_id, transparency, edition), - |new_opaque_and_semitransparent| SyntaxContextData { - outer_expn: call_id, - outer_transparency: transparency, - parent, - opaque, - opaque_and_semitransparent: new_opaque_and_semitransparent, - edition, - }, - ); + SyntaxContextId::new(db, call_id, transparency, edition, parent, |_| opaque, identity); } let parent = ctxt; - db.intern_syntax_context(SyntaxContextData { - outer_expn: call_id, - outer_transparency: transparency, - parent, - opaque, - opaque_and_semitransparent, + SyntaxContextId::new( + db, + call_id, + transparency, edition, - }) + parent, + |_| opaque, + |_| opaque_and_semitransparent, + ) } pub trait SyntaxContextExt { - fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> Self; - fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> Self; - fn parent_ctxt(self, db: &dyn ExpandDatabase) -> Self; - fn remove_mark(&mut self, db: &dyn ExpandDatabase) -> (Option, Transparency); - fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option, Transparency); - fn marks(self, db: &dyn ExpandDatabase) -> Vec<(MacroCallId, Transparency)>; + fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId; + fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId; + fn parent_ctxt(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId; + fn remove_mark(&mut self, db: &dyn ExpandDatabase) + -> (Option, Transparency); + fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option, Transparency); + fn marks(self, db: &dyn ExpandDatabase) -> Vec<(span::MacroCallId, Transparency)>; fn is_opaque(self, db: &dyn ExpandDatabase) -> bool; } impl SyntaxContextExt for SyntaxContextId { - fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> Self { - db.lookup_intern_syntax_context(self).opaque_and_semitransparent + fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId { + self.opaque_and_semitransparent(db) } - fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> Self { - db.lookup_intern_syntax_context(self).opaque + fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId { + self.opaque(db) } - fn parent_ctxt(self, db: &dyn ExpandDatabase) -> Self { - db.lookup_intern_syntax_context(self).parent + fn parent_ctxt(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId { + self.parent(db) } - fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option, Transparency) { - let data = db.lookup_intern_syntax_context(self); - (data.outer_expn, data.outer_transparency) + fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option, Transparency) { + let data = self; + (data.outer_expn(db), data.outer_transparency(db)) } - fn remove_mark(&mut self, db: &dyn ExpandDatabase) -> (Option, Transparency) { - let data = db.lookup_intern_syntax_context(*self); - *self = data.parent; - (data.outer_expn, data.outer_transparency) + fn remove_mark( + &mut self, + db: &dyn ExpandDatabase, + ) -> (Option, Transparency) { + let data = *self; + *self = data.parent(db); + (data.outer_expn(db), data.outer_transparency(db)) } - fn marks(self, db: &dyn ExpandDatabase) -> Vec<(MacroCallId, Transparency)> { + fn marks(self, db: &dyn ExpandDatabase) -> Vec<(span::MacroCallId, Transparency)> { let mut marks = marks_rev(self, db).collect::>(); marks.reverse(); marks } fn is_opaque(self, db: &dyn ExpandDatabase) -> bool { - !self.is_root() && db.lookup_intern_syntax_context(self).outer_transparency.is_opaque() + !self.is_root() && self.outer_transparency(db).is_opaque() } } @@ -207,7 +190,7 @@ impl SyntaxContextExt for SyntaxContextId { pub fn marks_rev( ctxt: SyntaxContextId, db: &dyn ExpandDatabase, -) -> impl Iterator + '_ { +) -> impl Iterator + '_ { iter::successors(Some(ctxt), move |&mark| Some(mark.parent_ctxt(db))) .take_while(|&it| !it.is_root()) .map(|ctx| { @@ -219,18 +202,14 @@ pub fn marks_rev( } pub(crate) fn dump_syntax_contexts(db: &dyn ExpandDatabase) -> String { - use crate::db::{InternMacroCallLookupQuery, InternSyntaxContextLookupQuery}; - use base_db::ra_salsa::debug::DebugQueryTable; - let mut s = String::from("Expansions:"); - let mut entries = InternMacroCallLookupQuery.in_db(db).entries::>(); - entries.sort_by_key(|e| e.key); - for e in entries { - let id = e.key; - let expn_data = e.value.as_ref().unwrap(); + let entries = + MacroCallWrapper::ingredient(db).entries(db.as_dyn_database()).collect::>(); + for loc in entries { + let expn_data = &loc.fields().0; + s.push_str(&format!( - "\n{:?}: parent: {:?}, call_site_ctxt: {:?}, kind: {:?}", - id, + "parent: {:?}, call_site_ctxt: {:?}, kind: {:?}", expn_data.kind.file_id(), expn_data.ctxt, expn_data.kind.descr(), @@ -238,28 +217,25 @@ pub(crate) fn dump_syntax_contexts(db: &dyn ExpandDatabase) -> String { } s.push_str("\n\nSyntaxContexts:\n"); - let mut entries = InternSyntaxContextLookupQuery.in_db(db).entries::>(); - entries.sort_by_key(|e| e.key); + let entries = SyntaxContextId::ingredient(db).entries(db.as_dyn_database()).collect::>(); for e in entries { struct SyntaxContextDebug<'a>( &'a dyn ExpandDatabase, - SyntaxContextId, - &'a SyntaxContextData, + &'a span::SyntaxContextUnderlyingData, ); impl std::fmt::Debug for SyntaxContextDebug<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - fancy_debug(self.2, self.1, self.0, f) + fancy_debug(self.1, self.0, f) } } fn fancy_debug( - this: &SyntaxContextData, - self_id: SyntaxContextId, + this: &span::SyntaxContextUnderlyingData, db: &dyn ExpandDatabase, f: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { - write!(f, "#{self_id} parent: #{}, outer_mark: (", this.parent)?; + write!(f, "parent: #{}, outer_mark: (", this.parent)?; match this.outer_expn { Some(id) => { write!(f, "{:?}::{{{{expn{:?}}}}}", db.lookup_intern_macro_call(id).krate, id)? @@ -269,7 +245,8 @@ pub(crate) fn dump_syntax_contexts(db: &dyn ExpandDatabase) -> String { write!(f, ", {:?})", this.outer_transparency) } - stdx::format_to!(s, "{:?}\n", SyntaxContextDebug(db, e.key, &e.value.unwrap())); + let dbg = SyntaxContextDebug(db, e.fields()); + stdx::format_to!(s, "{:?}\n", dbg); } s } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index c1d808cbf2c5a..f8c83dce55ac6 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -33,11 +33,11 @@ use triomphe::Arc; use core::fmt; use std::hash::Hash; -use base_db::{ra_salsa::InternValueTrivial, CrateId}; +use base_db::CrateId; use either::Either; use span::{ Edition, EditionedFileId, ErasedFileAstId, FileAstId, HirFileIdRepr, Span, SpanAnchor, - SyntaxContextData, SyntaxContextId, + SyntaxContextId, }; use syntax::{ ast::{self, AstNode}, @@ -89,17 +89,17 @@ pub mod tt { macro_rules! impl_intern_lookup { ($db:ident, $id:ident, $loc:ident, $intern:ident, $lookup:ident) => { impl $crate::Intern for $loc { - type Database<'db> = dyn $db + 'db; + type Database = dyn $db; type ID = $id; - fn intern(self, db: &Self::Database<'_>) -> $id { + fn intern(self, db: &Self::Database) -> Self::ID { db.$intern(self) } } impl $crate::Lookup for $id { - type Database<'db> = dyn $db + 'db; + type Database = dyn $db; type Data = $loc; - fn lookup(&self, db: &Self::Database<'_>) -> $loc { + fn lookup(&self, db: &Self::Database) -> Self::Data { db.$lookup(*self) } } @@ -108,15 +108,15 @@ macro_rules! impl_intern_lookup { // ideally these would be defined in base-db, but the orphan rule doesn't let us pub trait Intern { - type Database<'db>: ?Sized; + type Database: ?Sized; type ID; - fn intern(self, db: &Self::Database<'_>) -> Self::ID; + fn intern(self, db: &Self::Database) -> Self::ID; } pub trait Lookup { - type Database<'db>: ?Sized; + type Database: ?Sized; type Data; - fn lookup(&self, db: &Self::Database<'_>) -> Self::Data; + fn lookup(&self, db: &Self::Database) -> Self::Data; } impl_intern_lookup!( @@ -127,14 +127,6 @@ impl_intern_lookup!( lookup_intern_macro_call ); -impl_intern_lookup!( - ExpandDatabase, - SyntaxContextId, - SyntaxContextData, - intern_syntax_context, - lookup_intern_syntax_context -); - pub type ExpandResult = ValueResult; #[derive(Debug, PartialEq, Eq, Clone, Hash)] @@ -262,7 +254,6 @@ pub struct MacroCallLoc { pub kind: MacroCallKind, pub ctxt: SyntaxContextId, } -impl InternValueTrivial for MacroCallLoc {} #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroDefId { @@ -357,7 +348,7 @@ impl HirFileIdExt for HirFileId { fn edition(self, db: &dyn ExpandDatabase) -> Edition { match self.repr() { HirFileIdRepr::FileId(file_id) => file_id.edition(), - HirFileIdRepr::MacroFile(m) => m.macro_call_id.lookup(db).def.edition, + HirFileIdRepr::MacroFile(m) => db.lookup_intern_macro_call(m.macro_call_id).def.edition, } } fn original_file(self, db: &dyn ExpandDatabase) -> EditionedFileId { @@ -366,7 +357,7 @@ impl HirFileIdExt for HirFileId { match file_id.repr() { HirFileIdRepr::FileId(id) => break id, HirFileIdRepr::MacroFile(MacroFileId { macro_call_id }) => { - file_id = macro_call_id.lookup(db).kind.file_id(); + file_id = db.lookup_intern_macro_call(macro_call_id).kind.file_id() } } } @@ -409,7 +400,7 @@ impl HirFileIdExt for HirFileId { fn as_builtin_derive_attr_node(&self, db: &dyn ExpandDatabase) -> Option> { let macro_file = self.macro_file()?; - let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id); + let loc = db.lookup_intern_macro_call(macro_file.macro_call_id); let attr = match loc.def.kind { MacroDefKind::BuiltInDerive(..) => loc.to_node(db), _ => return None, @@ -467,7 +458,7 @@ impl MacroFileIdExt for MacroFileId { let mut level = 0; let mut macro_file = self; loop { - let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id); + let loc = db.lookup_intern_macro_call(macro_file.macro_call_id); level += 1; macro_file = match loc.kind.file_id().repr() { @@ -477,7 +468,7 @@ impl MacroFileIdExt for MacroFileId { } } fn parent(self, db: &dyn ExpandDatabase) -> HirFileId { - self.macro_call_id.lookup(db).kind.file_id() + db.lookup_intern_macro_call(self.macro_call_id).kind.file_id() } /// Return expansion information if it is a macro-expansion file @@ -538,7 +529,7 @@ impl MacroDefId { kind: MacroCallKind, ctxt: SyntaxContextId, ) -> MacroCallId { - MacroCallLoc { def: self, krate, kind, ctxt }.intern(db) + db.intern_macro_call(MacroCallLoc { def: self, krate, kind, ctxt }) } pub fn definition_range(&self, db: &dyn ExpandDatabase) -> InFile { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs index 75b5861454056..6f6f41f322abf 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs @@ -277,7 +277,7 @@ fn convert_path( if mod_path.segments.len() == 1 && mod_path.kind == PathKind::Plain { if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { let syn_ctx = span_for_range(segment.syntax().text_range()); - if let Some(macro_call_id) = db.lookup_intern_syntax_context(syn_ctx).outer_expn { + if let Some(macro_call_id) = syn_ctx.outer_expn(db) { if db.lookup_intern_macro_call(macro_call_id).def.local_inner { mod_path.kind = match resolve_crate_root(db, syn_ctx) { Some(crate_root) => PathKind::DollarCrate(crate_root), @@ -336,7 +336,7 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: tt::TokenTreesView<'_>) -> Optio pub fn resolve_crate_root(db: &dyn ExpandDatabase, mut ctxt: SyntaxContextId) -> Option { // When resolving `$crate` from a `macro_rules!` invoked in a `macro`, // we don't want to pretend that the `macro_rules!` definition is in the `macro` - // as described in `SyntaxContext::apply_mark`, so we ignore prepended opaque marks. + // as described in `SyntaxContextId::apply_mark`, so we ignore prepended opaque marks. // FIXME: This is only a guess and it doesn't work correctly for `macro_rules!` // definitions actually produced by `macro` and `macro` definitions produced by // `macro_rules!`, but at least such configurations are not stable yet. diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs index c744fbce77b7c..944341ec3f2cd 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs @@ -25,9 +25,8 @@ pub fn prettify_macro_expansion( let ctx = span_map.span_at(dollar_crate.text_range().start() + span_offset).ctx; let replacement = syntax_ctx_id_to_dollar_crate_replacement.entry(ctx).or_insert_with(|| { - let ctx_data = db.lookup_intern_syntax_context(ctx); let macro_call_id = - ctx_data.outer_expn.expect("`$crate` cannot come from `SyntaxContextId::ROOT`"); + ctx.outer_expn(db).expect("`$crate` cannot come from `SyntaxContextId::ROOT`"); let macro_call = db.lookup_intern_macro_call(macro_call_id); let macro_def_crate = macro_call.def.krate; // First, if this is the same crate as the macro, nothing will work but `crate`. diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs b/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs index 740c27b89cea1..ab99cb14f9562 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs @@ -79,10 +79,16 @@ impl SpanMapRef<'_> { } } -pub(crate) fn real_span_map(db: &dyn ExpandDatabase, file_id: EditionedFileId) -> Arc { +pub(crate) fn real_span_map( + db: &dyn ExpandDatabase, + editioned_file_id: EditionedFileId, +) -> Arc { use syntax::ast::HasModuleItem; let mut pairs = vec![(syntax::TextSize::new(0), span::ROOT_ERASED_FILE_AST_ID)]; - let ast_id_map = db.ast_id_map(file_id.into()); + let ast_id_map = db.ast_id_map(editioned_file_id.into()); + + let file_id = base_db::EditionedFileId::new(db, editioned_file_id); + let tree = db.parse(file_id).tree(); // This is an incrementality layer. Basically we can't use absolute ranges for our spans as that // would mean we'd invalidate everything whenever we type. So instead we make the text ranges @@ -134,7 +140,7 @@ pub(crate) fn real_span_map(db: &dyn ExpandDatabase, file_id: EditionedFileId) - }); Arc::new(RealSpanMap::from_file( - file_id, + editioned_file_id, pairs.into_boxed_slice(), tree.syntax().text_range().end(), )) diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml index 1d12bee646c4f..30074105331c5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml @@ -31,8 +31,11 @@ la-arena.workspace = true triomphe.workspace = true nohash-hasher.workspace = true typed-arena = "2.0.1" +dashmap.workspace = true indexmap.workspace = true rustc_apfloat = "0.2.0" +query-group.workspace = true +salsa.workspace = true ra-ap-rustc_abi.workspace = true ra-ap-rustc_index.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 67fb73696f766..2be321733075b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -451,10 +451,10 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { self.db.type_alias_data(id).name.display(self.db.upcast(), self.edition()).to_string() } fn opaque_type_name(&self, opaque_ty_id: chalk_ir::OpaqueTyId) -> String { - format!("Opaque_{}", opaque_ty_id.0) + format!("Opaque_{:?}", opaque_ty_id.0) } fn fn_def_name(&self, fn_def_id: chalk_ir::FnDefId) -> String { - format!("fn_{}", fn_def_id.0) + format!("fn_{:?}", fn_def_id.0) } fn coroutine_datum( &self, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index fb604569f439d..b3c604015a0c1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -1,6 +1,6 @@ //! Constant evaluation details -use base_db::{ra_salsa::Cycle, CrateId}; +use base_db::CrateId; use chalk_ir::{cast::Cast, BoundVar, DebruijnIndex}; use hir_def::{ expr_store::{Body, HygieneId}, @@ -11,14 +11,19 @@ use hir_def::{ ConstBlockLoc, EnumVariantId, GeneralConstId, HasModule as _, StaticId, }; use hir_expand::Lookup; +use salsa::Cycle; use stdx::never; use triomphe::Arc; use crate::{ - db::HirDatabase, display::DisplayTarget, generics::Generics, infer::InferenceContext, - lower::ParamLoweringMode, mir::monomorphize_mir_body_bad, to_placeholder_idx, Const, ConstData, - ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty, - TyBuilder, + db::{HirDatabase, HirDatabaseData}, + display::DisplayTarget, + generics::Generics, + infer::InferenceContext, + lower::ParamLoweringMode, + mir::monomorphize_mir_body_bad, + to_placeholder_idx, Const, ConstData, ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, + Substitution, TraitEnvironment, Ty, TyBuilder, }; use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError}; @@ -224,9 +229,10 @@ pub fn try_const_isize(db: &dyn HirDatabase, c: &Const) -> Option { pub(crate) fn const_eval_recover( _: &dyn HirDatabase, _: &Cycle, - _: &GeneralConstId, - _: &Substitution, - _: &Option>, + _: HirDatabaseData, + _: GeneralConstId, + _: Substitution, + _: Option>, ) -> Result { Err(ConstEvalError::MirLowerError(MirLowerError::Loop)) } @@ -234,7 +240,7 @@ pub(crate) fn const_eval_recover( pub(crate) fn const_eval_static_recover( _: &dyn HirDatabase, _: &Cycle, - _: &StaticId, + _: StaticId, ) -> Result { Err(ConstEvalError::MirLowerError(MirLowerError::Loop)) } @@ -242,7 +248,7 @@ pub(crate) fn const_eval_static_recover( pub(crate) fn const_eval_discriminant_recover( _: &dyn HirDatabase, _: &Cycle, - _: &EnumVariantId, + _: EnumVariantId, ) -> Result { Err(ConstEvalError::MirLowerError(MirLowerError::Loop)) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 26a3b7022976f..f2673dc58fa41 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -1,4 +1,4 @@ -use base_db::SourceDatabase; +use base_db::RootQueryDb; use chalk_ir::Substitution; use hir_def::db::DefDatabase; use rustc_apfloat::{ diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index 76031491d9a07..5817ed2ef20cd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -3,11 +3,7 @@ use std::sync; -use base_db::{ - impl_intern_key, - ra_salsa::{self, InternValueTrivial}, - CrateId, Upcast, -}; +use base_db::{impl_intern_key, CrateId, Upcast}; use hir_def::{ db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId, @@ -15,6 +11,7 @@ use hir_def::{ }; use hir_expand::name::Name; use la_arena::ArenaMap; +use salsa::plumbing::AsId; use smallvec::SmallVec; use triomphe::Arc; @@ -31,22 +28,22 @@ use crate::{ PolyFnSig, Substitution, TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId, }; -#[ra_salsa::query_group(HirDatabaseStorage)] -pub trait HirDatabase: DefDatabase + Upcast { - #[ra_salsa::invoke(crate::infer::infer_query)] +#[query_group::query_group] +pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { + #[salsa::invoke_actual(crate::infer::infer_query)] fn infer(&self, def: DefWithBodyId) -> Arc; // region:mir - #[ra_salsa::invoke(crate::mir::mir_body_query)] - #[ra_salsa::cycle(crate::mir::mir_body_recover)] + #[salsa::invoke_actual(crate::mir::mir_body_query)] + #[salsa::cycle(crate::mir::mir_body_recover)] fn mir_body(&self, def: DefWithBodyId) -> Result, MirLowerError>; - #[ra_salsa::invoke(crate::mir::mir_body_for_closure_query)] + #[salsa::invoke(crate::mir::mir_body_for_closure_query)] fn mir_body_for_closure(&self, def: ClosureId) -> Result, MirLowerError>; - #[ra_salsa::invoke(crate::mir::monomorphized_mir_body_query)] - #[ra_salsa::cycle(crate::mir::monomorphized_mir_body_recover)] + #[salsa::invoke(crate::mir::monomorphized_mir_body_query)] + #[salsa::cycle(crate::mir::monomorphized_mir_body_recover)] fn monomorphized_mir_body( &self, def: DefWithBodyId, @@ -54,7 +51,7 @@ pub trait HirDatabase: DefDatabase + Upcast { env: Arc, ) -> Result, MirLowerError>; - #[ra_salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)] + #[salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)] fn monomorphized_mir_body_for_closure( &self, def: ClosureId, @@ -62,12 +59,12 @@ pub trait HirDatabase: DefDatabase + Upcast { env: Arc, ) -> Result, MirLowerError>; - #[ra_salsa::invoke(crate::mir::borrowck_query)] - #[ra_salsa::lru] + #[salsa::invoke(crate::mir::borrowck_query)] + #[salsa::lru(2024)] fn borrowck(&self, def: DefWithBodyId) -> Result, MirLowerError>; - #[ra_salsa::invoke(crate::consteval::const_eval_query)] - #[ra_salsa::cycle(crate::consteval::const_eval_recover)] + #[salsa::invoke(crate::consteval::const_eval_query)] + #[salsa::cycle(crate::consteval::const_eval_recover)] fn const_eval( &self, def: GeneralConstId, @@ -75,15 +72,15 @@ pub trait HirDatabase: DefDatabase + Upcast { trait_env: Option>, ) -> Result; - #[ra_salsa::invoke(crate::consteval::const_eval_static_query)] - #[ra_salsa::cycle(crate::consteval::const_eval_static_recover)] + #[salsa::invoke_actual(crate::consteval::const_eval_static_query)] + #[salsa::cycle(crate::consteval::const_eval_static_recover)] fn const_eval_static(&self, def: StaticId) -> Result; - #[ra_salsa::invoke(crate::consteval::const_eval_discriminant_variant)] - #[ra_salsa::cycle(crate::consteval::const_eval_discriminant_recover)] + #[salsa::invoke_actual(crate::consteval::const_eval_discriminant_variant)] + #[salsa::cycle(crate::consteval::const_eval_discriminant_recover)] fn const_eval_discriminant(&self, def: EnumVariantId) -> Result; - #[ra_salsa::invoke(crate::method_resolution::lookup_impl_method_query)] + #[salsa::invoke(crate::method_resolution::lookup_impl_method_query)] fn lookup_impl_method( &self, env: Arc, @@ -93,8 +90,8 @@ pub trait HirDatabase: DefDatabase + Upcast { // endregion:mir - #[ra_salsa::invoke(crate::layout::layout_of_adt_query)] - #[ra_salsa::cycle(crate::layout::layout_of_adt_recover)] + #[salsa::invoke(crate::layout::layout_of_adt_query)] + #[salsa::cycle(crate::layout::layout_of_adt_recover)] fn layout_of_adt( &self, def: AdtId, @@ -102,63 +99,67 @@ pub trait HirDatabase: DefDatabase + Upcast { env: Arc, ) -> Result, LayoutError>; - #[ra_salsa::invoke(crate::layout::layout_of_ty_query)] - #[ra_salsa::cycle(crate::layout::layout_of_ty_recover)] + #[salsa::invoke(crate::layout::layout_of_ty_query)] + #[salsa::cycle(crate::layout::layout_of_ty_recover)] fn layout_of_ty(&self, ty: Ty, env: Arc) -> Result, LayoutError>; - #[ra_salsa::invoke(crate::layout::target_data_layout_query)] + #[salsa::invoke(crate::layout::target_data_layout_query)] fn target_data_layout(&self, krate: CrateId) -> Result, Arc>; - #[ra_salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)] + #[salsa::invoke_actual(crate::dyn_compatibility::dyn_compatibility_of_trait_query)] fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option; - #[ra_salsa::invoke(crate::lower::ty_query)] - #[ra_salsa::cycle(crate::lower::ty_recover)] + #[salsa::invoke(crate::lower::ty_query)] + #[salsa::cycle(crate::lower::ty_recover)] fn ty(&self, def: TyDefId) -> Binders; - #[ra_salsa::invoke(crate::lower::type_for_type_alias_with_diagnostics_query)] + #[salsa::invoke_actual(crate::lower::type_for_type_alias_with_diagnostics_query)] fn type_for_type_alias_with_diagnostics(&self, def: TypeAliasId) -> (Binders, Diagnostics); /// Returns the type of the value of the given constant, or `None` if the `ValueTyDefId` is /// a `StructId` or `EnumVariantId` with a record constructor. - #[ra_salsa::invoke(crate::lower::value_ty_query)] + #[salsa::invoke_actual(crate::lower::value_ty_query)] fn value_ty(&self, def: ValueTyDefId) -> Option>; - #[ra_salsa::invoke(crate::lower::impl_self_ty_with_diagnostics_query)] - #[ra_salsa::cycle(crate::lower::impl_self_ty_with_diagnostics_recover)] + #[salsa::invoke_actual(crate::lower::impl_self_ty_with_diagnostics_query)] + #[salsa::cycle(crate::lower::impl_self_ty_with_diagnostics_recover)] fn impl_self_ty_with_diagnostics(&self, def: ImplId) -> (Binders, Diagnostics); - #[ra_salsa::invoke(crate::lower::impl_self_ty_query)] + + #[salsa::invoke_actual(crate::lower::impl_self_ty_query)] fn impl_self_ty(&self, def: ImplId) -> Binders; - #[ra_salsa::invoke(crate::lower::const_param_ty_with_diagnostics_query)] + #[salsa::invoke(crate::lower::const_param_ty_with_diagnostics_query)] fn const_param_ty_with_diagnostics(&self, def: ConstParamId) -> (Ty, Diagnostics); - #[ra_salsa::invoke(crate::lower::const_param_ty_query)] + + #[salsa::invoke(crate::lower::const_param_ty_query)] fn const_param_ty(&self, def: ConstParamId) -> Ty; - #[ra_salsa::invoke(crate::lower::impl_trait_with_diagnostics_query)] + #[salsa::invoke_actual(crate::lower::impl_trait_with_diagnostics_query)] fn impl_trait_with_diagnostics(&self, def: ImplId) -> Option<(Binders, Diagnostics)>; - #[ra_salsa::invoke(crate::lower::impl_trait_query)] + + #[salsa::invoke_actual(crate::lower::impl_trait_query)] fn impl_trait(&self, def: ImplId) -> Option>; - #[ra_salsa::invoke(crate::lower::field_types_with_diagnostics_query)] + #[salsa::invoke_actual(crate::lower::field_types_with_diagnostics_query)] fn field_types_with_diagnostics( &self, var: VariantId, ) -> (Arc>>, Diagnostics); - #[ra_salsa::invoke(crate::lower::field_types_query)] + + #[salsa::invoke_actual(crate::lower::field_types_query)] fn field_types(&self, var: VariantId) -> Arc>>; - #[ra_salsa::invoke(crate::lower::callable_item_sig)] + #[salsa::invoke_actual(crate::lower::callable_item_sig)] fn callable_item_signature(&self, def: CallableDefId) -> PolyFnSig; - #[ra_salsa::invoke(crate::lower::return_type_impl_traits)] + #[salsa::invoke_actual(crate::lower::return_type_impl_traits)] fn return_type_impl_traits(&self, def: FunctionId) -> Option>>; - #[ra_salsa::invoke(crate::lower::type_alias_impl_traits)] + #[salsa::invoke_actual(crate::lower::type_alias_impl_traits)] fn type_alias_impl_traits(&self, def: TypeAliasId) -> Option>>; - #[ra_salsa::invoke(crate::lower::generic_predicates_for_param_query)] - #[ra_salsa::cycle(crate::lower::generic_predicates_for_param_recover)] + #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] + #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] fn generic_predicates_for_param( &self, def: GenericDefId, @@ -166,132 +167,139 @@ pub trait HirDatabase: DefDatabase + Upcast { assoc_name: Option, ) -> GenericPredicates; - #[ra_salsa::invoke(crate::lower::generic_predicates_query)] + #[salsa::invoke_actual(crate::lower::generic_predicates_query)] fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates; - #[ra_salsa::invoke(crate::lower::generic_predicates_without_parent_with_diagnostics_query)] + #[salsa::invoke_actual(crate::lower::generic_predicates_without_parent_with_diagnostics_query)] fn generic_predicates_without_parent_with_diagnostics( &self, def: GenericDefId, ) -> (GenericPredicates, Diagnostics); - #[ra_salsa::invoke(crate::lower::generic_predicates_without_parent_query)] + + #[salsa::invoke_actual(crate::lower::generic_predicates_without_parent_query)] fn generic_predicates_without_parent(&self, def: GenericDefId) -> GenericPredicates; - #[ra_salsa::invoke(crate::lower::trait_environment_for_body_query)] - #[ra_salsa::transparent] + #[salsa::invoke_actual(crate::lower::trait_environment_for_body_query)] + #[salsa::transparent] fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc; - #[ra_salsa::invoke(crate::lower::trait_environment_query)] + #[salsa::invoke_actual(crate::lower::trait_environment_query)] fn trait_environment(&self, def: GenericDefId) -> Arc; - #[ra_salsa::invoke(crate::lower::generic_defaults_with_diagnostics_query)] - #[ra_salsa::cycle(crate::lower::generic_defaults_with_diagnostics_recover)] + #[salsa::invoke_actual(crate::lower::generic_defaults_with_diagnostics_query)] + #[salsa::cycle(crate::lower::generic_defaults_with_diagnostics_recover)] fn generic_defaults_with_diagnostics( &self, def: GenericDefId, ) -> (GenericDefaults, Diagnostics); - #[ra_salsa::invoke(crate::lower::generic_defaults_query)] + + #[salsa::invoke_actual(crate::lower::generic_defaults_query)] fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults; - #[ra_salsa::invoke(InherentImpls::inherent_impls_in_crate_query)] + #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)] fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc; - #[ra_salsa::invoke(InherentImpls::inherent_impls_in_block_query)] + #[salsa::invoke_actual(InherentImpls::inherent_impls_in_block_query)] fn inherent_impls_in_block(&self, block: BlockId) -> Option>; /// Collects all crates in the dependency graph that have impls for the /// given fingerprint. This is only used for primitive types and types /// annotated with `rustc_has_incoherent_inherent_impls`; for other types /// we just look at the crate where the type is defined. - #[ra_salsa::invoke(crate::method_resolution::incoherent_inherent_impl_crates)] + #[salsa::invoke(crate::method_resolution::incoherent_inherent_impl_crates)] fn incoherent_inherent_impl_crates( &self, krate: CrateId, fp: TyFingerprint, ) -> SmallVec<[CrateId; 2]>; - #[ra_salsa::invoke(TraitImpls::trait_impls_in_crate_query)] + #[salsa::invoke(TraitImpls::trait_impls_in_crate_query)] fn trait_impls_in_crate(&self, krate: CrateId) -> Arc; - #[ra_salsa::invoke(TraitImpls::trait_impls_in_block_query)] + #[salsa::invoke_actual(TraitImpls::trait_impls_in_block_query)] fn trait_impls_in_block(&self, block: BlockId) -> Option>; - #[ra_salsa::invoke(TraitImpls::trait_impls_in_deps_query)] + #[salsa::invoke(TraitImpls::trait_impls_in_deps_query)] fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<[Arc]>; // Interned IDs for Chalk integration - #[ra_salsa::interned] + #[salsa::interned] fn intern_callable_def(&self, callable_def: CallableDefId) -> InternedCallableDefId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_type_or_const_param_id( &self, param_id: TypeOrConstParamId, ) -> InternedTypeOrConstParamId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_closure(&self, id: InternedClosure) -> InternedClosureId; - #[ra_salsa::interned] + + #[salsa::interned] fn intern_coroutine(&self, id: InternedCoroutine) -> InternedCoroutineId; - #[ra_salsa::invoke(chalk_db::associated_ty_data_query)] + #[salsa::invoke(chalk_db::associated_ty_data_query)] fn associated_ty_data( &self, id: chalk_db::AssocTypeId, ) -> sync::Arc; - #[ra_salsa::invoke(chalk_db::trait_datum_query)] + #[salsa::invoke(chalk_db::trait_datum_query)] fn trait_datum( &self, krate: CrateId, trait_id: chalk_db::TraitId, ) -> sync::Arc; - #[ra_salsa::invoke(chalk_db::adt_datum_query)] + #[salsa::invoke(chalk_db::adt_datum_query)] fn adt_datum( &self, krate: CrateId, struct_id: chalk_db::AdtId, ) -> sync::Arc; - #[ra_salsa::invoke(chalk_db::impl_datum_query)] + #[salsa::invoke(chalk_db::impl_datum_query)] fn impl_datum( &self, krate: CrateId, impl_id: chalk_db::ImplId, ) -> sync::Arc; - #[ra_salsa::invoke(chalk_db::fn_def_datum_query)] + #[salsa::invoke(chalk_db::fn_def_datum_query)] fn fn_def_datum(&self, fn_def_id: FnDefId) -> sync::Arc; - #[ra_salsa::invoke(chalk_db::fn_def_variance_query)] + #[salsa::invoke(chalk_db::fn_def_variance_query)] fn fn_def_variance(&self, fn_def_id: FnDefId) -> chalk_db::Variances; - #[ra_salsa::invoke(chalk_db::adt_variance_query)] + #[salsa::invoke(chalk_db::adt_variance_query)] fn adt_variance(&self, adt_id: chalk_db::AdtId) -> chalk_db::Variances; - #[ra_salsa::invoke(crate::variance::variances_of)] - #[ra_salsa::cycle(crate::variance::variances_of_cycle)] + #[salsa::invoke_actual(crate::variance::variances_of)] + #[salsa::cycle(crate::variance::variances_of_cycle)] fn variances_of(&self, def: GenericDefId) -> Option>; - #[ra_salsa::invoke(chalk_db::associated_ty_value_query)] + #[salsa::invoke(chalk_db::associated_ty_value_query)] fn associated_ty_value( &self, krate: CrateId, id: chalk_db::AssociatedTyValueId, ) -> sync::Arc; - #[ra_salsa::invoke(crate::traits::normalize_projection_query)] - #[ra_salsa::transparent] + #[salsa::invoke(crate::traits::normalize_projection_query)] + #[salsa::transparent] fn normalize_projection( &self, projection: crate::ProjectionTy, env: Arc, ) -> Ty; - #[ra_salsa::invoke(crate::traits::trait_solve_query)] + #[salsa::invoke(crate::traits::trait_solve_query)] fn trait_solve( &self, krate: CrateId, @@ -299,7 +307,7 @@ pub trait HirDatabase: DefDatabase + Upcast { goal: crate::Canonical>, ) -> Option; - #[ra_salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)] + #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)] fn program_clauses_for_chalk_env( &self, krate: CrateId, @@ -307,9 +315,9 @@ pub trait HirDatabase: DefDatabase + Upcast { env: chalk_ir::Environment, ) -> chalk_ir::ProgramClauses; - #[ra_salsa::invoke(crate::drop::has_drop_glue)] - #[ra_salsa::cycle(crate::drop::has_drop_glue_recover)] - fn has_drop_glue(&self, ty: Ty, env: Arc) -> DropGlue {} + #[salsa::invoke(crate::drop::has_drop_glue)] + #[salsa::cycle(crate::drop::has_drop_glue_recover)] + fn has_drop_glue(&self, ty: Ty, env: Arc) -> DropGlue; } #[test] @@ -317,41 +325,22 @@ fn hir_database_is_dyn_compatible() { fn _assert_dyn_compatible(_: &dyn HirDatabase) {} } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct InternedTypeOrConstParamId(ra_salsa::InternId); -impl_intern_key!(InternedTypeOrConstParamId); +impl_intern_key!(InternedTypeOrConstParamId, TypeOrConstParamId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct InternedLifetimeParamId(ra_salsa::InternId); -impl_intern_key!(InternedLifetimeParamId); +impl_intern_key!(InternedLifetimeParamId, LifetimeParamId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct InternedConstParamId(ra_salsa::InternId); -impl_intern_key!(InternedConstParamId); +impl_intern_key!(InternedConstParamId, ConstParamId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct InternedOpaqueTyId(ra_salsa::InternId); -impl_intern_key!(InternedOpaqueTyId); +impl_intern_key!(InternedOpaqueTyId, ImplTraitId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct InternedClosureId(ra_salsa::InternId); -impl_intern_key!(InternedClosureId); - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct InternedClosure(pub DefWithBodyId, pub ExprId); +impl_intern_key!(InternedClosureId, InternedClosure); -impl InternValueTrivial for InternedClosure {} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct InternedCoroutineId(ra_salsa::InternId); -impl_intern_key!(InternedCoroutineId); - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct InternedCoroutine(pub DefWithBodyId, pub ExprId); -impl InternValueTrivial for InternedCoroutine {} +impl_intern_key!(InternedCoroutineId, InternedCoroutine); -/// This exists just for Chalk, because Chalk just has a single `FnDefId` where -/// we have different IDs for struct and enum variant constructors. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] -pub struct InternedCallableDefId(ra_salsa::InternId); -impl_intern_key!(InternedCallableDefId); +// This exists just for Chalk, because Chalk just has a single `FnDefId` where +// we have different IDs for struct and enum variant constructors. +impl_intern_key!(InternedCallableDefId, CallableDefId); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index 774991560e9ca..eed74e1eee358 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -251,7 +251,7 @@ impl<'a> DeclValidator<'a> { return; } - let (_, source_map) = self.db.body_with_source_map(func.into()); + let source_map = self.db.body_with_source_map(func.into()).1; for (id, replacement) in pats_replacements { let Ok(source_ptr) = source_map.pat_syntax(id) else { continue; @@ -597,7 +597,7 @@ impl<'a> DeclValidator<'a> { ) where N: AstNode + HasName + fmt::Debug, S: HasSource, - L: Lookup = dyn DefDatabase + 'a> + HasModule + Copy, + L: Lookup + HasModule + Copy, { let to_expected_case_type = match expected_case { CaseType::LowerSnakeCase => to_lower_snake_case, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index cc6f4d9e52eb8..975143b29f2f9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -434,7 +434,7 @@ impl ExprValidator { let last_then_expr_ty = &self.infer[last_then_expr]; if last_then_expr_ty.is_never() { // Only look at sources if the then branch diverges and we have an else branch. - let (_, source_map) = db.body_with_source_map(self.owner); + let source_map = db.body_with_source_map(self.owner).1; let Ok(source_ptr) = source_map.expr_syntax(id) else { return; }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs index 351926c86c473..4ad16cf8bcf7e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs @@ -1,6 +1,5 @@ //! Utilities for computing drop info about types. -use base_db::ra_salsa; use chalk_ir::cast::Cast; use hir_def::data::adt::StructFlags; use hir_def::lang_item::LangItem; @@ -8,6 +7,7 @@ use hir_def::AdtId; use stdx::never; use triomphe::Arc; +use crate::db::HirDatabaseData; use crate::{ db::HirDatabase, method_resolution::TyFingerprint, AliasTy, Canonical, CanonicalVarKinds, InEnvironment, Interner, ProjectionTy, TraitEnvironment, Ty, TyBuilder, TyKind, @@ -201,9 +201,10 @@ fn is_copy(db: &dyn HirDatabase, ty: Ty, env: Arc) -> bool { pub(crate) fn has_drop_glue_recover( _db: &dyn HirDatabase, - _cycle: &ra_salsa::Cycle, - _ty: &Ty, - _env: &Arc, + _cycle: &salsa::Cycle, + _: HirDatabaseData, + _ty: Ty, + _env: Arc, ) -> DropGlue { DropGlue::None } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 80e3ca1fa282e..131e98d729651 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -289,7 +289,7 @@ impl InferenceContext<'_> { expected: &Expectation, is_read: ExprIsRead, ) -> Ty { - self.db.unwind_if_cancelled(); + self.db.unwind_if_revision_cancelled(); let ty = match &self.body[tgt_expr] { Expr::Missing => self.err_ty(), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs index 804c3aea3a5c9..832a00e1e5e7b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs @@ -8,7 +8,6 @@ use crate::{ ProgramClauseData, ProgramClauses, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution, Ty, TyData, TyKind, VariableKind, VariableKinds, }; -use base_db::ra_salsa::InternId; use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variance}; use hir_def::TypeAliasId; use intern::{impl_internable, Interned}; @@ -68,7 +67,7 @@ impl chalk_ir::interner::Interner for Interner { type InternedCanonicalVarKinds = Interned>>; type InternedConstraints = Vec>; type InternedVariances = SmallVec<[Variance; 16]>; - type DefId = InternId; + type DefId = salsa::Id; type InternedAdtId = hir_def::AdtId; type Identifier = TypeAliasId; type FnAbi = FnAbi; @@ -98,7 +97,7 @@ impl chalk_ir::interner::Interner for Interner { opaque_ty_id: OpaqueTyId, fmt: &mut fmt::Formatter<'_>, ) -> Option { - Some(write!(fmt, "OpaqueTy#{}", opaque_ty_id.0)) + Some(write!(fmt, "OpaqueTy#{:?}", opaque_ty_id.0)) } fn debug_fn_def_id(fn_def_id: FnDefId, fmt: &mut fmt::Formatter<'_>) -> Option { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index bbd419d9659bf..167dcec3bb3f8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -2,7 +2,6 @@ use std::fmt; -use base_db::ra_salsa::Cycle; use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy}; use hir_def::{ layout::{ @@ -14,21 +13,20 @@ use hir_def::{ use la_arena::{Idx, RawIdx}; use rustc_abi::AddressSpace; use rustc_index::IndexVec; +use salsa::Cycle; use triomphe::Arc; use crate::{ consteval::try_const_usize, - db::{HirDatabase, InternedClosure}, + db::{HirDatabase, HirDatabaseData, InternedClosure}, infer::normalize, utils::ClosureSubst, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, }; -pub use self::{ - adt::{layout_of_adt_query, layout_of_adt_recover}, - target::target_data_layout_query, -}; +pub(crate) use self::adt::layout_of_adt_recover; +pub use self::{adt::layout_of_adt_query, target::target_data_layout_query}; mod adt; mod target; @@ -367,11 +365,12 @@ pub fn layout_of_ty_query( Ok(Arc::new(result)) } -pub fn layout_of_ty_recover( +pub(crate) fn layout_of_ty_recover( _: &dyn HirDatabase, _: &Cycle, - _: &Ty, - _: &Arc, + _: HirDatabaseData, + _: Ty, + _: Arc, ) -> Result, LayoutError> { Err(LayoutError::RecursiveTypeWithoutIndirection) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs index eb4729fab8426..ab9c07779c07a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs @@ -2,7 +2,6 @@ use std::{cmp, ops::Bound}; -use base_db::ra_salsa::Cycle; use hir_def::{ data::adt::VariantData, layout::{Integer, ReprOptions, TargetDataLayout}, @@ -10,6 +9,7 @@ use hir_def::{ }; use intern::sym; use rustc_index::IndexVec; +use salsa::Cycle; use smallvec::SmallVec; use triomphe::Arc; @@ -20,7 +20,7 @@ use crate::{ Substitution, TraitEnvironment, }; -use super::LayoutCx; +use super::{HirDatabaseData, LayoutCx}; pub fn layout_of_adt_query( db: &dyn HirDatabase, @@ -131,12 +131,13 @@ fn layout_scalar_valid_range(db: &dyn HirDatabase, def: AdtId) -> (Bound, ) } -pub fn layout_of_adt_recover( +pub(crate) fn layout_of_adt_recover( _: &dyn HirDatabase, _: &Cycle, - _: &AdtId, - _: &Substitution, - _: &Arc, + _: HirDatabaseData, + _: AdtId, + _: Substitution, + _: Arc, ) -> Result, LayoutError> { Err(LayoutError::RecursiveTypeWithoutIndirection) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 624767cedf822..f35298846a858 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -56,7 +56,6 @@ mod variance; use std::hash::Hash; -use base_db::ra_salsa::InternValueTrivial; use chalk_ir::{ fold::{Shift, TypeFoldable}, interner::HasInterner, @@ -610,7 +609,6 @@ pub enum ImplTraitId { TypeAliasImplTrait(hir_def::TypeAliasId, ImplTraitIdx), AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId), } -impl InternValueTrivial for ImplTraitId {} #[derive(PartialEq, Eq, Debug, Hash)] pub struct ImplTraits { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index af73b5ed9a7b4..ff7f0349638cd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -14,7 +14,7 @@ use std::{ ops::{self, Not as _}, }; -use base_db::{ra_salsa::Cycle, CrateId}; +use base_db::CrateId; use chalk_ir::{ cast::Cast, fold::{Shift, TypeFoldable}, @@ -47,6 +47,7 @@ use hir_expand::{name::Name, ExpandResult}; use la_arena::{Arena, ArenaMap}; use rustc_hash::FxHashSet; use rustc_pattern_analysis::Captures; +use salsa::Cycle; use stdx::{impl_from, never}; use syntax::ast; use triomphe::{Arc, ThinArc}; @@ -57,7 +58,7 @@ use crate::{ intern_const_ref, intern_const_scalar, path_to_const, unknown_const, unknown_const_as_generic, }, - db::HirDatabase, + db::{HirDatabase, HirDatabaseData}, error_lifetime, generics::{generics, trait_self_param_idx, Generics}, lower::{ @@ -1111,10 +1112,11 @@ pub(crate) fn generic_predicates_for_param_query( pub(crate) fn generic_predicates_for_param_recover( _db: &dyn HirDatabase, - _cycle: &Cycle, - _def: &GenericDefId, - _param_id: &TypeOrConstParamId, - _assoc_name: &Option, + _cycle: &salsa::Cycle, + _: HirDatabaseData, + _def: GenericDefId, + _param_id: TypeOrConstParamId, + _assoc_name: Option, ) -> GenericPredicates { GenericPredicates(None) } @@ -1271,6 +1273,7 @@ where ); }; } + ( GenericPredicates(predicates.is_empty().not().then(|| predicates.into())), create_diagnostics(ctx.diagnostics), @@ -1414,9 +1417,9 @@ pub(crate) fn generic_defaults_with_diagnostics_query( pub(crate) fn generic_defaults_with_diagnostics_recover( db: &dyn HirDatabase, _cycle: &Cycle, - def: &GenericDefId, + def: GenericDefId, ) -> (GenericDefaults, Diagnostics) { - let generic_params = generics(db.upcast(), *def); + let generic_params = generics(db.upcast(), def); if generic_params.len() == 0 { return (GenericDefaults(None), None); } @@ -1591,6 +1594,7 @@ pub(crate) fn type_for_type_alias_with_diagnostics_query( .map(|type_ref| ctx.lower_ty(type_ref)) .unwrap_or_else(|| TyKind::Error.intern(Interner)) }; + (make_binders(db, &generics, inner), create_diagnostics(ctx.diagnostics)) } @@ -1602,7 +1606,7 @@ pub enum TyDefId { } impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] pub enum ValueTyDefId { FunctionId(FunctionId), StructId(StructId), @@ -1638,8 +1642,13 @@ pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders { } } -pub(crate) fn ty_recover(db: &dyn HirDatabase, _cycle: &Cycle, def: &TyDefId) -> Binders { - let generics = match *def { +pub(crate) fn ty_recover( + db: &dyn HirDatabase, + _cycle: &salsa::Cycle, + _: HirDatabaseData, + def: TyDefId, +) -> Binders { + let generics = match def { TyDefId::BuiltinType(_) => return Binders::empty(Interner, TyKind::Error.intern(Interner)), TyDefId::AdtId(it) => generics(db.upcast(), it.into()), TyDefId::TypeAliasId(it) => generics(db.upcast(), it.into()), @@ -1703,10 +1712,10 @@ pub(crate) fn const_param_ty_with_diagnostics_query( pub(crate) fn impl_self_ty_with_diagnostics_recover( db: &dyn HirDatabase, - _cycle: &Cycle, - impl_id: &ImplId, + _cycle: &salsa::Cycle, + impl_id: ImplId, ) -> (Binders, Diagnostics) { - let generics = generics(db.upcast(), (*impl_id).into()); + let generics = generics(db.upcast(), (impl_id).into()); (make_binders(db, &generics, TyKind::Error.intern(Interner)), None) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs index 2f38e8fa14c0b..cfa2a49b79c53 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs @@ -5,8 +5,11 @@ use chalk_solve::rust_ir; -use base_db::ra_salsa::{self, InternKey}; use hir_def::{LifetimeParamId, TraitId, TypeAliasId, TypeOrConstParamId}; +use salsa::{ + plumbing::{AsId, FromId}, + Id, +}; use crate::{ chalk_db, db::HirDatabase, AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, @@ -30,11 +33,11 @@ impl ToChalk for hir_def::ImplId { type Chalk = chalk_db::ImplId; fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::ImplId { - chalk_ir::ImplId(self.as_intern_id()) + chalk_ir::ImplId(self.as_id()) } fn from_chalk(_db: &dyn HirDatabase, impl_id: chalk_db::ImplId) -> hir_def::ImplId { - InternKey::from_intern_id(impl_id.0) + FromId::from_id(impl_id.0.as_id()) } } @@ -56,84 +59,84 @@ impl ToChalk for TypeAliasAsValue { type Chalk = chalk_db::AssociatedTyValueId; fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::AssociatedTyValueId { - rust_ir::AssociatedTyValueId(self.0.as_intern_id()) + rust_ir::AssociatedTyValueId(self.0.as_id()) } fn from_chalk( _db: &dyn HirDatabase, assoc_ty_value_id: chalk_db::AssociatedTyValueId, ) -> TypeAliasAsValue { - TypeAliasAsValue(TypeAliasId::from_intern_id(assoc_ty_value_id.0)) + TypeAliasAsValue(TypeAliasId::from_id(assoc_ty_value_id.0)) } } impl From for crate::db::InternedCallableDefId { fn from(fn_def_id: FnDefId) -> Self { - InternKey::from_intern_id(fn_def_id.0) + Self::from_id(fn_def_id.0) } } impl From for FnDefId { fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self { - chalk_ir::FnDefId(callable_def_id.as_intern_id()) + chalk_ir::FnDefId(callable_def_id.as_id()) } } impl From for crate::db::InternedOpaqueTyId { fn from(id: OpaqueTyId) -> Self { - InternKey::from_intern_id(id.0) + FromId::from_id(id.0) } } impl From for OpaqueTyId { fn from(id: crate::db::InternedOpaqueTyId) -> Self { - chalk_ir::OpaqueTyId(id.as_intern_id()) + chalk_ir::OpaqueTyId(id.as_id()) } } impl From> for crate::db::InternedClosureId { fn from(id: chalk_ir::ClosureId) -> Self { - Self::from_intern_id(id.0) + FromId::from_id(id.0) } } impl From for chalk_ir::ClosureId { fn from(id: crate::db::InternedClosureId) -> Self { - chalk_ir::ClosureId(id.as_intern_id()) + chalk_ir::ClosureId(id.as_id()) } } impl From> for crate::db::InternedCoroutineId { fn from(id: chalk_ir::CoroutineId) -> Self { - Self::from_intern_id(id.0) + Self::from_id(id.0) } } impl From for chalk_ir::CoroutineId { fn from(id: crate::db::InternedCoroutineId) -> Self { - chalk_ir::CoroutineId(id.as_intern_id()) + chalk_ir::CoroutineId(id.as_id()) } } pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { - chalk_ir::ForeignDefId(ra_salsa::InternKey::as_intern_id(&id)) + chalk_ir::ForeignDefId(id.as_id()) } pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId { - ra_salsa::InternKey::from_intern_id(id.0) + FromId::from_id(id.0) } pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId { - chalk_ir::AssocTypeId(ra_salsa::InternKey::as_intern_id(&id)) + chalk_ir::AssocTypeId(id.as_id()) } pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId { - ra_salsa::InternKey::from_intern_id(id.0) + FromId::from_id(id.0) } pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeOrConstParamId { assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); - let interned_id = ra_salsa::InternKey::from_intern_id(ra_salsa::InternId::from(idx.idx)); + let interned_id = FromId::from_id(Id::from_u32(idx.idx.try_into().unwrap())); db.lookup_intern_type_or_const_param_id(interned_id) } @@ -141,13 +144,13 @@ pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Place let interned_id = db.intern_type_or_const_param_id(id); PlaceholderIndex { ui: chalk_ir::UniverseIndex::ROOT, - idx: ra_salsa::InternKey::as_intern_id(&interned_id).as_usize(), + idx: interned_id.as_id().as_u32() as usize, } } pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId { assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); - let interned_id = ra_salsa::InternKey::from_intern_id(ra_salsa::InternId::from(idx.idx)); + let interned_id = FromId::from_id(Id::from_u32(idx.idx.try_into().unwrap())); db.lookup_intern_lifetime_param_id(interned_id) } @@ -155,14 +158,14 @@ pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> Place let interned_id = db.intern_lifetime_param_id(id); PlaceholderIndex { ui: chalk_ir::UniverseIndex::ROOT, - idx: ra_salsa::InternKey::as_intern_id(&interned_id).as_usize(), + idx: interned_id.as_id().as_u32() as usize, } } pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { - chalk_ir::TraitId(ra_salsa::InternKey::as_intern_id(&id)) + chalk_ir::TraitId(id.as_id()) } pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId { - ra_salsa::InternKey::from_intern_id(id.0) + FromId::from_id(id.0) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index db94351dcc995..c5ad808accdf4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -714,6 +714,7 @@ pub(crate) fn lookup_impl_method_query( else { return (func, fn_subst); }; + ( impl_fn, Substitution::from_iter( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index 56c431ef8dab6..ae454fbe528a5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -32,17 +32,18 @@ pub use borrowck::{borrowck_query, BorrowckResult, MutabilityReason}; pub use eval::{ interpret_mir, pad16, render_const_using_debug_impl, Evaluator, MirEvalError, VTableMap, }; -pub use lower::{ - lower_to_mir, mir_body_for_closure_query, mir_body_query, mir_body_recover, MirLowerError, -}; +pub use lower::{lower_to_mir, mir_body_for_closure_query, mir_body_query, MirLowerError}; pub use monomorphization::{ monomorphize_mir_body_bad, monomorphized_mir_body_for_closure_query, - monomorphized_mir_body_query, monomorphized_mir_body_recover, + monomorphized_mir_body_query, }; use rustc_hash::FxHashMap; use smallvec::{smallvec, SmallVec}; use stdx::{impl_from, never}; +pub(crate) use lower::mir_body_recover; +pub(crate) use monomorphization::monomorphized_mir_body_recover; + use super::consteval::{intern_const_scalar, try_const_usize}; pub type BasicBlockId = Idx; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs index fbcca388e781d..fd1e724ee88ec 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs @@ -145,7 +145,7 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec Operand::Constant(_) | Operand::Static(_) => (), }; for (_, block) in body.basic_blocks.iter() { - db.unwind_if_cancelled(); + db.unwind_if_revision_cancelled(); for statement in &block.statements { match &statement.kind { StatementKind::Assign(_, r) => match r { @@ -235,7 +235,7 @@ fn partially_moved(db: &dyn HirDatabase, body: &MirBody) -> Vec Operand::Constant(_) | Operand::Static(_) => (), }; for (_, block) in body.basic_blocks.iter() { - db.unwind_if_cancelled(); + db.unwind_if_revision_cancelled(); for statement in &block.statements { match &statement.kind { StatementKind::Assign(_, r) => match r { @@ -306,7 +306,7 @@ fn partially_moved(db: &dyn HirDatabase, body: &MirBody) -> Vec fn borrow_regions(db: &dyn HirDatabase, body: &MirBody) -> Vec { let mut borrows = FxHashMap::default(); for (_, block) in body.basic_blocks.iter() { - db.unwind_if_cancelled(); + db.unwind_if_revision_cancelled(); for statement in &block.statements { if let StatementKind::Assign(_, Rvalue::Ref(kind, p)) = &statement.kind { borrows @@ -477,7 +477,7 @@ fn ever_initialized_map( dfs(db, body, l, &mut stack, &mut result); } for l in body.locals.iter().map(|it| it.0) { - db.unwind_if_cancelled(); + db.unwind_if_revision_cancelled(); if !result[body.start_block].contains_idx(l) { result[body.start_block].insert(l, false); stack.clear(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 74a34e2981710..c9d62f566c1a6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -2558,6 +2558,7 @@ impl Evaluator<'_> { } else { let (imp, generic_args) = self.db.lookup_impl_method(self.trait_env.clone(), def, generic_args.clone()); + let mir_body = self .db .monomorphized_mir_body(imp.into(), generic_args, self.trait_env.clone()) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 520717e799521..17f1da0c9f378 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -2,7 +2,7 @@ use std::{fmt::Write, iter, mem}; -use base_db::{ra_salsa::Cycle, CrateId}; +use base_db::{salsa::Cycle, CrateId}; use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind}; use hir_def::{ data::adt::{StructKind, VariantData}, @@ -2149,10 +2149,10 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result Result> { Err(MirLowerError::Loop) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs index 92132fa047362..6d1e9a1ea1972 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs @@ -9,7 +9,6 @@ use std::mem; -use base_db::ra_salsa::Cycle; use chalk_ir::{ fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}, ConstData, DebruijnIndex, @@ -19,7 +18,7 @@ use triomphe::Arc; use crate::{ consteval::{intern_const_scalar, unknown_const}, - db::{HirDatabase, InternedClosure}, + db::{HirDatabase, HirDatabaseData, InternedClosure}, from_placeholder_idx, generics::{generics, Generics}, infer::normalize, @@ -314,12 +313,13 @@ pub fn monomorphized_mir_body_query( Ok(Arc::new(body)) } -pub fn monomorphized_mir_body_recover( +pub(crate) fn monomorphized_mir_body_recover( _: &dyn HirDatabase, - _: &Cycle, - _: &DefWithBodyId, - _: &Substitution, - _: &Arc, + _: &salsa::Cycle, + _: HirDatabaseData, + _: DefWithBodyId, + _: Substitution, + _: Arc, ) -> Result, MirLowerError> { Err(MirLowerError::Loop) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs index f37dd91d8e90f..b18a057ba0b9d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs @@ -3,34 +3,34 @@ use std::{fmt, panic, sync::Mutex}; use base_db::{ - ra_salsa::{self, Durability}, - AnchoredPath, CrateId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast, + FileSourceRootInput, FileText, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId, + SourceRootInput, Upcast, }; + use hir_def::{db::DefDatabase, ModuleId}; use hir_expand::db::ExpandDatabase; use rustc_hash::FxHashMap; +use salsa::{AsDynDatabase, Durability}; use span::{EditionedFileId, FileId}; use syntax::TextRange; use test_utils::extract_annotations; use triomphe::Arc; -#[ra_salsa::database( - base_db::SourceRootDatabaseStorage, - base_db::SourceDatabaseStorage, - hir_expand::db::ExpandDatabaseStorage, - hir_def::db::InternDatabaseStorage, - hir_def::db::DefDatabaseStorage, - crate::db::HirDatabaseStorage -)] +#[salsa::db] +#[derive(Clone)] pub(crate) struct TestDB { - storage: ra_salsa::Storage, - events: Mutex>>, + storage: salsa::Storage, + files: Arc, + events: Arc>>>, } impl Default for TestDB { fn default() -> Self { - let mut this = Self { storage: Default::default(), events: Default::default() }; - this.setup_syntax_context_root(); + let mut this = Self { + storage: Default::default(), + events: Default::default(), + files: Default::default(), + }; this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); this } @@ -54,35 +54,81 @@ impl Upcast for TestDB { } } -impl ra_salsa::Database for TestDB { - fn salsa_event(&self, event: ra_salsa::Event) { - let mut events = self.events.lock().unwrap(); - if let Some(events) = &mut *events { - events.push(event); - } +impl Upcast for TestDB { + fn upcast(&self) -> &(dyn RootQueryDb + 'static) { + self } } -impl ra_salsa::ParallelDatabase for TestDB { - fn snapshot(&self) -> ra_salsa::Snapshot { - ra_salsa::Snapshot::new(TestDB { - storage: self.storage.snapshot(), - events: Default::default(), - }) +impl Upcast for TestDB { + fn upcast(&self) -> &(dyn SourceDatabase + 'static) { + self } } -impl panic::RefUnwindSafe for TestDB {} +#[salsa::db] +impl SourceDatabase for TestDB { + fn file_text(&self, file_id: base_db::FileId) -> FileText { + self.files.file_text(file_id) + } -impl FileLoader for TestDB { - fn resolve_path(&self, path: AnchoredPath<'_>) -> Option { - FileLoaderDelegate(self).resolve_path(path) + fn set_file_text(&mut self, file_id: base_db::FileId, text: &str) { + let files = Arc::clone(&self.files); + files.set_file_text(self, file_id, text); } - fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { - FileLoaderDelegate(self).relevant_crates(file_id) + + fn set_file_text_with_durability( + &mut self, + file_id: base_db::FileId, + text: &str, + durability: Durability, + ) { + let files = Arc::clone(&self.files); + files.set_file_text_with_durability(self, file_id, text, durability); + } + + /// Source root of the file. + fn source_root(&self, source_root_id: SourceRootId) -> SourceRootInput { + self.files.source_root(source_root_id) + } + + fn set_source_root_with_durability( + &mut self, + source_root_id: SourceRootId, + source_root: Arc, + durability: Durability, + ) { + let files = Arc::clone(&self.files); + files.set_source_root_with_durability(self, source_root_id, source_root, durability); + } + + fn file_source_root(&self, id: base_db::FileId) -> FileSourceRootInput { + self.files.file_source_root(id) + } + + fn set_file_source_root_with_durability( + &mut self, + id: base_db::FileId, + source_root_id: SourceRootId, + durability: Durability, + ) { + let files = Arc::clone(&self.files); + files.set_file_source_root_with_durability(self, id, source_root_id, durability); } } +#[salsa::db] +impl salsa::Database for TestDB { + fn salsa_event(&self, event: &dyn std::ops::Fn() -> salsa::Event) { + let mut events = self.events.lock().unwrap(); + if let Some(events) = &mut *events { + events.push(event()); + } + } +} + +impl panic::RefUnwindSafe for TestDB {} + impl TestDB { pub(crate) fn module_for_file_opt(&self, file_id: impl Into) -> Option { let file_id = file_id.into(); @@ -117,7 +163,7 @@ impl TestDB { .into_iter() .filter_map(|file_id| { let text = self.file_text(file_id.file_id()); - let annotations = extract_annotations(&text); + let annotations = extract_annotations(&text.text(self)); if annotations.is_empty() { return None; } @@ -128,7 +174,7 @@ impl TestDB { } impl TestDB { - pub(crate) fn log(&self, f: impl FnOnce()) -> Vec { + pub(crate) fn log(&self, f: impl FnOnce()) -> Vec { *self.events.lock().unwrap() = Some(Vec::new()); f(); self.events.lock().unwrap().take().unwrap() @@ -141,8 +187,11 @@ impl TestDB { .filter_map(|e| match e.kind { // This is pretty horrible, but `Debug` is the only way to inspect // QueryDescriptor at the moment. - ra_salsa::EventKind::WillExecute { database_key } => { - Some(format!("{:?}", database_key.debug(self))) + salsa::EventKind::WillExecute { database_key } => { + let ingredient = self + .as_dyn_database() + .ingredient_debug_name(database_key.ingredient_index()); + Some(ingredient.to_string()) } _ => None, }) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index 81e38be2285ab..26229040582b8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -15,7 +15,7 @@ mod type_alias_impl_traits; use std::env; use std::sync::LazyLock; -use base_db::{CrateId, SourceDatabaseFileInputExt as _}; +use base_db::{CrateId, SourceDatabase}; use expect_test::Expect; use hir_def::{ db::DefDatabase, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs index 6f7bfc4ea7a00..efb1728d0561d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs @@ -1,8 +1,8 @@ -use base_db::ra_salsa::InternKey; use expect_test::{expect, Expect}; use hir_def::db::DefDatabase; use hir_expand::files::InFileWrapper; use itertools::Itertools; +use salsa::plumbing::FromId; use span::{HirFileId, TextRange}; use syntax::{AstNode, AstPtr}; use test_fixture::WithFixture; @@ -34,8 +34,8 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec let infer = db.infer(def); let db = &db; captures_info.extend(infer.closure_info.iter().flat_map(|(closure_id, (captures, _))| { - let closure = db.lookup_intern_closure(InternedClosureId::from_intern_id(closure_id.0)); - let (_, source_map) = db.body_with_source_map(closure.0); + let closure = db.lookup_intern_closure(InternedClosureId::from_id(closure_id.0)); + let source_map = db.body_with_source_map(closure.0).1; let closure_text_range = source_map .expr_syntax(closure.1) .expect("failed to map closure to SyntaxNode") diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs index 3757d722ac83b..d54c6937bc393 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs @@ -1,4 +1,4 @@ -use base_db::SourceDatabaseFileInputExt as _; +use base_db::SourceDatabase; use hir_def::ModuleDefId; use test_fixture::WithFixture; @@ -25,7 +25,7 @@ fn foo() -> i32 { } }); }); - assert!(format!("{events:?}").contains("infer")) + assert!(format!("{events:?}").contains("infer_shim")) } let new_text = " @@ -47,7 +47,7 @@ fn foo() -> i32 { } }); }); - assert!(!format!("{events:?}").contains("infer"), "{events:#?}") + assert!(!format!("{events:?}").contains("infer_shim"), "{events:#?}") } } @@ -76,7 +76,7 @@ fn baz() -> i32 { } }); }); - assert!(format!("{events:?}").contains("infer")) + assert!(format!("{events:?}").contains("infer_shim")) } let new_text = " @@ -103,6 +103,6 @@ fn baz() -> i32 { } }); }); - assert!(format!("{events:?}").matches("infer").count() == 1, "{events:#?}") + assert!(format!("{events:?}").matches("infer_shim").count() == 1, "{events:#?}") } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index 8cb7dbf60f37b..0135e0a409bbe 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -160,7 +160,7 @@ fn solve( let fuel = std::cell::Cell::new(CHALK_SOLVER_FUEL); let should_continue = || { - db.unwind_if_cancelled(); + db.unwind_if_revision_cancelled(); let remaining = fuel.get(); fuel.set(remaining - 1); if remaining == 0 { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index 3a22158ce6f1d..425196d92f79a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -19,7 +19,7 @@ use crate::{ AliasTy, Const, ConstScalar, DynTyExt, GenericArg, GenericArgData, Interner, Lifetime, LifetimeData, Ty, TyKind, }; -use base_db::ra_salsa::Cycle; +use base_db::salsa::Cycle; use chalk_ir::Mutability; use hir_def::data::adt::StructFlags; use hir_def::{AdtId, GenericDefId, GenericParamId, VariantId}; @@ -58,9 +58,9 @@ pub(crate) fn variances_of(db: &dyn HirDatabase, def: GenericDefId) -> Option Option> { - let generics = generics(db.upcast(), *def); + let generics = generics(db.upcast(), def); let count = generics.len(); if count == 0 { diff --git a/src/tools/rust-analyzer/crates/hir/src/db.rs b/src/tools/rust-analyzer/crates/hir/src/db.rs index 22760c41aaecf..9e8e87ecff001 100644 --- a/src/tools/rust-analyzer/crates/hir/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir/src/db.rs @@ -3,44 +3,43 @@ //! we didn't do that. //! //! But we need this for at least LRU caching at the query level. -pub use hir_def::db::{ - AttrsQuery, BlockDefMapQuery, BlockItemTreeQuery, BlockItemTreeWithSourceMapQuery, BodyQuery, - BodyWithSourceMapQuery, ConstDataQuery, ConstVisibilityQuery, CrateDefMapQuery, - CrateLangItemsQuery, CrateNotableTraitsQuery, CrateSupportsNoStdQuery, DefDatabase, - DefDatabaseStorage, EnumDataQuery, EnumVariantDataWithDiagnosticsQuery, - ExpandProcAttrMacrosQuery, ExprScopesQuery, ExternCrateDeclDataQuery, FieldVisibilitiesQuery, - FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery, FileItemTreeWithSourceMapQuery, - FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery, - GenericParamsWithSourceMapQuery, ImplDataWithDiagnosticsQuery, ImportMapQuery, - IncludeMacroInvocQuery, InternAnonymousConstQuery, InternBlockQuery, InternConstQuery, - InternDatabase, InternDatabaseStorage, InternEnumQuery, InternExternBlockQuery, - InternExternCrateQuery, InternFunctionQuery, InternImplQuery, InternInTypeConstQuery, - InternMacro2Query, InternMacroRulesQuery, InternProcMacroQuery, InternStaticQuery, - InternStructQuery, InternTraitAliasQuery, InternTraitQuery, InternTypeAliasQuery, - InternUnionQuery, InternUseQuery, LangItemQuery, Macro2DataQuery, MacroDefQuery, - MacroRulesDataQuery, NotableTraitsInDepsQuery, ProcMacroDataQuery, StaticDataQuery, - StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitDataWithDiagnosticsQuery, - TypeAliasDataQuery, UnionDataWithDiagnosticsQuery, -}; -pub use hir_expand::db::{ - AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage, - ExpandProcMacroQuery, InternMacroCallQuery, InternSyntaxContextQuery, MacroArgQuery, - ParseMacroExpansionErrorQuery, ParseMacroExpansionQuery, ProcMacroSpanQuery, ProcMacrosQuery, - RealSpanMapQuery, -}; -pub use hir_ty::db::{ - AdtDatumQuery, AdtVarianceQuery, AssociatedTyDataQuery, AssociatedTyValueQuery, BorrowckQuery, - CallableItemSignatureQuery, ConstEvalDiscriminantQuery, ConstEvalQuery, ConstEvalStaticQuery, - ConstParamTyQuery, DynCompatibilityOfTraitQuery, FieldTypesQuery, FnDefDatumQuery, - FnDefVarianceQuery, GenericDefaultsQuery, GenericPredicatesForParamQuery, - GenericPredicatesQuery, GenericPredicatesWithoutParentQuery, HirDatabase, HirDatabaseStorage, - ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, IncoherentInherentImplCratesQuery, InferQuery, - InherentImplsInBlockQuery, InherentImplsInCrateQuery, InternCallableDefQuery, - InternClosureQuery, InternCoroutineQuery, InternImplTraitIdQuery, InternLifetimeParamIdQuery, - InternTypeOrConstParamIdQuery, LayoutOfAdtQuery, LayoutOfTyQuery, LookupImplMethodQuery, - MirBodyForClosureQuery, MirBodyQuery, MonomorphizedMirBodyForClosureQuery, - MonomorphizedMirBodyQuery, ProgramClausesForChalkEnvQuery, ReturnTypeImplTraitsQuery, - TargetDataLayoutQuery, TraitDatumQuery, TraitEnvironmentQuery, TraitImplsInBlockQuery, - TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery, - TypeAliasImplTraitsQuery, ValueTyQuery, -}; +pub use hir_def::db::DefDatabase; +// AttrsQuery, BlockDefMapQuery, BlockItemTreeQuery, BlockItemTreeWithSourceMapQuery, BodyQuery, +// BodyWithSourceMapQuery, ConstDataQuery, ConstVisibilityQuery, CrateDefMapQuery, +// CrateLangItemsQuery, CrateNotableTraitsQuery, CrateSupportsNoStdQuery, DefDatabase, +// DefDatabaseStorage, EnumDataQuery, EnumVariantDataWithDiagnosticsQuery, +// ExpandProcAttrMacrosQuery, ExprScopesQuery, ExternCrateDeclDataQuery, FieldVisibilitiesQuery, +// FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery, FileItemTreeWithSourceMapQuery, +// FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery, +// GenericParamsWithSourceMapQuery, ImplDataWithDiagnosticsQuery, ImportMapQuery, +// IncludeMacroInvocQuery, InternAnonymousConstQuery, InternBlockQuery, InternConstQuery, +// InternDatabase, InternDatabaseStorage, InternEnumQuery, InternExternBlockQuery, +// InternExternCrateQuery, InternFunctionQuery, InternImplQuery, InternInTypeConstQuery, +// InternMacro2Query, InternMacroRulesQuery, InternProcMacroQuery, InternStaticQuery, +// InternStructQuery, InternTraitAliasQuery, InternTraitQuery, InternTypeAliasQuery, +// InternUnionQuery, InternUseQuery, LangItemQuery, Macro2DataQuery, MacroDefQuery, +// MacroRulesDataQuery, NotableTraitsInDepsQuery, ProcMacroDataQuery, StaticDataQuery, +// StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitDataWithDiagnosticsQuery, +// TypeAliasDataQuery, UnionDataWithDiagnosticsQuery, +// }; +pub use hir_expand::db::ExpandDatabase; +// AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage, +// ExpandProcMacroQuery, InternMacroCallQuery, InternSyntaxContextQuery, MacroArgQuery, +// ParseMacroExpansionErrorQuery, ParseMacroExpansionQuery, ProcMacroSpanQuery, ProcMacrosQuery, +// RealSpanMapQuery, +pub use hir_ty::db::HirDatabase; +// AdtDatumQuery, AdtVarianceQuery, AssociatedTyDataQuery, AssociatedTyValueQuery, BorrowckQuery, +// CallableItemSignatureQuery, ConstEvalDiscriminantQuery, ConstEvalQuery, ConstEvalStaticQuery, +// ConstParamTyQuery, DynCompatibilityOfTraitQuery, FieldTypesQuery, FnDefDatumQuery, +// FnDefVarianceQuery, GenericDefaultsQuery, GenericPredicatesForParamQuery, +// GenericPredicatesQuery, GenericPredicatesWithoutParentQuery, HirDatabase, HirDatabaseStorage, +// ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, IncoherentInherentImplCratesQuery, InferQuery, +// InherentImplsInBlockQuery, InherentImplsInCrateQuery, InternCallableDefQuery, +// InternClosureQuery, InternCoroutineQuery, InternImplTraitIdQuery, InternLifetimeParamIdQuery, +// InternTypeOrConstParamIdQuery, LayoutOfAdtQuery, LayoutOfTyQuery, LookupImplMethodQuery, +// MirBodyForClosureQuery, MirBodyQuery, MonomorphizedMirBodyForClosureQuery, +// MonomorphizedMirBodyQuery, ProgramClausesForChalkEnvQuery, ReturnTypeImplTraitsQuery, +// TargetDataLayoutQuery, TraitDatumQuery, TraitEnvironmentQuery, TraitImplsInBlockQuery, +// TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery, +// TypeAliasImplTraitsQuery, ValueTyQuery, +// }; diff --git a/src/tools/rust-analyzer/crates/hir/src/has_source.rs b/src/tools/rust-analyzer/crates/hir/src/has_source.rs index 372c725293441..b4468178fbede 100644 --- a/src/tools/rust-analyzer/crates/hir/src/has_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/has_source.rs @@ -306,7 +306,7 @@ impl HasSource for ExternCrateDecl { impl HasSource for InlineAsmOperand { type Ast = ast::AsmOperandNamed; fn source(self, db: &dyn HirDatabase) -> Option> { - let (_body, source_map) = db.body_with_source_map(self.owner); + let source_map = db.body_with_source_map(self.owner).1; if let Ok(src) = source_map.expr_syntax(self.expr) { let root = src.file_syntax(db.upcast()); return src diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index a8075509474ab..dbe743e7e2f85 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -662,6 +662,7 @@ impl Module { db.field_types_with_diagnostics(s.id.into()).1, tree_source_maps.strukt(tree_id.value).item(), ); + for diag in db.struct_data_with_diagnostics(s.id).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } @@ -675,6 +676,7 @@ impl Module { db.field_types_with_diagnostics(u.id.into()).1, tree_source_maps.union(tree_id.value).item(), ); + for diag in db.union_data_with_diagnostics(u.id).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } @@ -1906,6 +1908,7 @@ impl DefWithBody { let krate = self.module(db).id.krate(); let (body, source_map) = db.body_with_source_map(self.into()); + let item_tree_source_maps; let outer_types_source_map = match self { DefWithBody::Function(function) => { @@ -1955,7 +1958,7 @@ impl DefWithBody { None }; MacroError { - node: (*node).map(|it| it.into()), + node: (node).map(|it| it.into()), precise_location, message, error, @@ -3346,7 +3349,7 @@ fn as_assoc_item<'db, ID, DEF, LOC>( id: ID, ) -> Option where - ID: Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, + ID: Lookup>, DEF: From, LOC: ItemTreeNode, { @@ -3362,7 +3365,7 @@ fn as_extern_assoc_item<'db, ID, DEF, LOC>( id: ID, ) -> Option where - ID: Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, + ID: Lookup>, DEF: From, LOC: ItemTreeNode, { @@ -4656,6 +4659,7 @@ pub struct CaptureUsages { impl CaptureUsages { pub fn sources(&self, db: &dyn HirDatabase) -> Vec { let (body, source_map) = db.body_with_source_map(self.parent); + let mut result = Vec::with_capacity(self.spans.len()); for &span in self.spans.iter() { let is_ref = span.is_ref_span(&body); diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 5e2eebcd13c69..aeeb3f9790986 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -307,9 +307,10 @@ impl<'db> SemanticsImpl<'db> { SemanticsImpl { db, s2d_cache: Default::default(), macro_call_cache: Default::default() } } - pub fn parse(&self, file_id: EditionedFileId) -> ast::SourceFile { + pub fn parse(&self, file_id: base_db::EditionedFileId) -> ast::SourceFile { + let hir_file_id = file_id.editioned_file_id(self.db).into(); let tree = self.db.parse(file_id).tree(); - self.cache(tree.syntax().clone(), file_id.into()); + self.cache(tree.syntax().clone(), hir_file_id); tree } @@ -329,11 +330,14 @@ impl<'db> SemanticsImpl<'db> { } pub fn parse_guess_edition(&self, file_id: FileId) -> ast::SourceFile { - let file_id = self + let editioned_file_id = self .attach_first_edition(file_id) .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); + + let file_id = base_db::EditionedFileId::new(self.db, editioned_file_id); + let tree = self.db.parse(file_id).tree(); - self.cache(tree.syntax().clone(), file_id.into()); + self.cache(tree.syntax().clone(), editioned_file_id.into()); tree } @@ -1903,7 +1907,9 @@ fn macro_call_to_macro_id( match loc.def.ast_id() { Either::Left(it) => { let node = match it.file_id.repr() { - HirFileIdRepr::FileId(file_id) => { + HirFileIdRepr::FileId(editioned_file_id) => { + let file_id = base_db::EditionedFileId::new(db, editioned_file_id); + it.to_ptr(db).to_node(&db.parse(file_id).syntax_node()) } HirFileIdRepr::MacroFile(macro_file) => { @@ -1915,7 +1921,9 @@ fn macro_call_to_macro_id( } Either::Right(it) => { let node = match it.file_id.repr() { - HirFileIdRepr::FileId(file_id) => { + HirFileIdRepr::FileId(editioned_file_id) => { + let file_id = base_db::EditionedFileId::new(db, editioned_file_id); + it.to_ptr(db).to_node(&db.parse(file_id).syntax_node()) } HirFileIdRepr::MacroFile(macro_file) => { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index d0fdf5cbdf7a3..da9bb8b15c8c0 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -254,7 +254,7 @@ fn insert_item_loc( id: ID, key: Key, ) where - ID: for<'db> Lookup = dyn DefDatabase + 'db, Data = Data> + 'static, + ID: Lookup + 'static, Data: ItemTreeLoc, N: ItemTreeNode, N::Source: 'static, diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 18cbaa15aeaed..4ec0739656076 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -85,6 +85,7 @@ //! active crate for a given position, and then provide an API to resolve all //! syntax nodes against this specific crate. +use base_db::{RootQueryDb, Upcast}; use either::Either; use hir_def::{ dyn_map::{ @@ -99,11 +100,11 @@ use hir_def::{ }; use hir_expand::{ attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, InMacroFile, MacroCallId, - MacroFileIdExt, + MacroFileId, MacroFileIdExt, }; use rustc_hash::FxHashMap; use smallvec::SmallVec; -use span::{EditionedFileId, FileId, MacroFileId}; +use span::{EditionedFileId, FileId}; use stdx::impl_from; use syntax::{ ast::{self, HasName}, @@ -142,7 +143,7 @@ impl SourceToDefCache { return m; } self.included_file_cache.insert(file, None); - for &crate_id in db.relevant_crates(file.into()).iter() { + for &crate_id in Upcast::::upcast(db).relevant_crates(file.into()).iter() { db.include_macro_invoc(crate_id).iter().for_each(|&(macro_call_id, file_id)| { self.included_file_cache.insert(file_id, Some(MacroFileId { macro_call_id })); }); @@ -176,7 +177,9 @@ impl SourceToDefCtx<'_, '_> { let _p = tracing::info_span!("SourceToDefCtx::file_to_def").entered(); self.cache.file_to_def_cache.entry(file).or_insert_with(|| { let mut mods = SmallVec::new(); - for &crate_id in self.db.relevant_crates(file).iter() { + + for &crate_id in Upcast::::upcast(self.db).relevant_crates(file).iter() + { // Note: `mod` declarations in block modules cannot be supported here let crate_def_map = self.db.crate_def_map(crate_id); let n_mods = mods.len(); @@ -344,7 +347,7 @@ impl SourceToDefCtx<'_, '_> { }) .position(|it| it == *src.value)?; let container = self.find_pat_or_label_container(src.syntax_ref())?; - let (_, source_map) = self.db.body_with_source_map(container); + let source_map = self.db.body_with_source_map(container).1; let expr = source_map.node_expr(src.with_value(&ast::Expr::AsmExpr(asm)))?.as_expr()?; Some(InlineAsmOperand { owner: container, expr, index }) } @@ -377,7 +380,8 @@ impl SourceToDefCtx<'_, '_> { src: InFile<&ast::Label>, ) -> Option<(DefWithBodyId, LabelId)> { let container = self.find_pat_or_label_container(src.syntax_ref())?; - let (_body, source_map) = self.db.body_with_source_map(container); + let source_map = self.db.body_with_source_map(container).1; + let label_id = source_map.node_label(src)?; Some((container, label_id)) } diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index d1245f5f7d681..aa0eac9478a22 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -1635,8 +1635,7 @@ pub(crate) fn name_hygiene(db: &dyn HirDatabase, name: InFile<&SyntaxNode>) -> H }; let span_map = db.expansion_span_map(macro_file); let ctx = span_map.span_at(name.value.text_range().start()).ctx; - let ctx = db.lookup_intern_syntax_context(ctx); - HygieneId::new(ctx.opaque_and_semitransparent) + HygieneId::new(ctx.opaque_and_semitransparent(db)) } fn type_of_expr_including_adjust(infer: &InferenceResult, id: ExprId) -> Option<&Ty> { diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index 81eb6a70ad73e..fa8153ad2162d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -111,7 +111,7 @@ impl<'a> SymbolCollector<'a> { fn do_work(&mut self, work: SymbolCollectorWork) { let _p = tracing::info_span!("SymbolCollector::do_work", ?work).entered(); tracing::info!(?work, "SymbolCollector::do_work"); - self.db.unwind_if_cancelled(); + self.db.unwind_if_revision_cancelled(); let parent_name = work.parent.map(|name| name.as_str().to_smolstr()); self.with_container_name(parent_name, |s| s.collect_from_module(work.module_id)); @@ -346,9 +346,9 @@ impl<'a> SymbolCollector<'a> { } } - fn push_decl<'db, L>(&mut self, id: L, name: &Name, is_assoc: bool) + fn push_decl(&mut self, id: L, name: &Name, is_assoc: bool) where - L: Lookup = dyn DefDatabase + 'db> + Into, + L: Lookup + Into, ::Data: HasSource, <::Data as HasSource>::Value: HasName, { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs index b1189f0d0b06e..c4e98c0742358 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs @@ -1,6 +1,7 @@ //! See [`AssistContext`]. use hir::{FileRange, Semantics}; +use ide_db::base_db::salsa::AsDynDatabase; use ide_db::EditionedFileId; use ide_db::{label::Label, FileId, RootDatabase}; use syntax::Edition; @@ -64,7 +65,10 @@ impl<'a> AssistContext<'a> { config: &'a AssistConfig, frange: FileRange, ) -> AssistContext<'a> { - let source_file = sema.parse(frange.file_id); + let editioned_file_id = + ide_db::base_db::EditionedFileId::new(sema.db.as_dyn_database(), frange.file_id); + + let source_file = sema.parse(editioned_file_id); let start = frange.range.start(); let end = frange.range.end(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 37f5f44dfa020..fee7662a78494 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -2,6 +2,7 @@ use std::iter::{self, Peekable}; use either::Either; use hir::{sym, Adt, Crate, HasAttrs, ImportPathConfig, ModuleDef, Semantics}; +use ide_db::base_db::salsa::AsDynDatabase; use ide_db::syntax_helpers::suggest_name; use ide_db::RootDatabase; use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast}; @@ -256,7 +257,12 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) // Just replace the element that the original range came from let old_place = { // Find the original element - let file = ctx.sema.parse(arm_list_range.file_id); + let editioned_file_id = ide_db::base_db::EditionedFileId::new( + ctx.sema.db.as_dyn_database(), + arm_list_range.file_id, + ); + + let file = ctx.sema.parse(editioned_file_id); let old_place = file.syntax().covering_element(arm_list_range.range); match old_place { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs index 7716e99e604b3..9cb14e8d9a007 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs @@ -1136,7 +1136,7 @@ fn foo() { } //- /main.rs -use foo::Foo; +use foo::{Bool, Foo}; mod foo; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs index d34cf895cd90a..54826f03884f3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs @@ -590,7 +590,7 @@ fn handle_call( let indent = if insert_newlines { first_arg_indent.unwrap().to_string() } else { String::new() }; // FIXME: This text manipulation seems risky. - let text = ctx.db().file_text(file_id.file_id()); + let text = ctx.db().file_text(file_id.file_id()).text(ctx.db()); let mut text = text[..u32::from(range.end()).try_into().unwrap()].trim_end(); if !text.ends_with(')') { return None; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs index 6e3be0ce69279..b94422b13c1bc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs @@ -2,6 +2,7 @@ use std::iter; use either::Either; use hir::{HasSource, HirFileIdExt, ModuleSource}; +use ide_db::base_db::salsa::AsDynDatabase; use ide_db::{ assists::{AssistId, AssistKind}, defs::{Definition, NameClass, NameRefClass}, @@ -331,7 +332,10 @@ impl Module { let mut use_stmts_set = FxHashSet::default(); for (file_id, refs) in node_def.usages(&ctx.sema).all() { - let source_file = ctx.sema.parse(file_id); + let editioned_file_id = + ide_db::base_db::EditionedFileId::new(ctx.sema.db.as_dyn_database(), file_id); + + let source_file = ctx.sema.parse(editioned_file_id); let usages = refs.into_iter().filter_map(|FileReference { range, .. }| { // handle normal usages let name_ref = find_node_at_range::(source_file.syntax(), range)?; @@ -457,7 +461,11 @@ impl Module { let selection_range = ctx.selection_trimmed(); let file_id = ctx.file_id(); let usage_res = def.usages(&ctx.sema).in_scope(&SearchScope::single_file(file_id)).all(); - let file = ctx.sema.parse(file_id); + + let editioned_file_id = + ide_db::base_db::EditionedFileId::new(ctx.sema.db.as_dyn_database(), file_id); + + let file = ctx.sema.parse(editioned_file_id); // track uses which does not exists in `Use` let mut uses_exist_in_sel = false; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs index 7af2a2e1e6a33..29bd8cf0d1a65 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs @@ -2,6 +2,7 @@ use hir::{ Adt, AsAssocItem, HasSource, HirDisplay, HirFileIdExt, Module, PathResolution, Semantics, StructKind, Type, TypeInfo, }; +use ide_db::base_db::salsa::AsDynDatabase; use ide_db::{ defs::{Definition, NameRefClass}, famous_defs::FamousDefs, @@ -205,7 +206,11 @@ fn get_adt_source( fn_name: &str, ) -> Option<(Option, FileId)> { let range = adt.source(ctx.sema.db)?.syntax().original_file_range_rooted(ctx.sema.db); - let file = ctx.sema.parse(range.file_id); + + let editioned_file_id = + ide_db::base_db::EditionedFileId::new(ctx.sema.db.as_dyn_database(), range.file_id); + + let file = ctx.sema.parse(editioned_file_id); let adt_source = ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?; find_struct_impl(ctx, &adt_source, &[fn_name.to_owned()]) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs index 5ddb17b20729a..2d7722a654e8e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs @@ -1,4 +1,6 @@ -use ide_db::{defs::Definition, search::FileReference, EditionedFileId}; +use ide_db::{ + base_db::salsa::AsDynDatabase, defs::Definition, search::FileReference, EditionedFileId, +}; use syntax::{ algo::{find_node_at_range, least_common_ancestor_element}, ast::{self, HasArgList}, @@ -102,7 +104,11 @@ fn process_usages( arg_to_remove: usize, is_self_present: bool, ) { - let source_file = ctx.sema.parse(file_id); + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(ctx.sema.db.as_dyn_database(), file_id); + + let source_file = ctx.sema.parse(editioned_file_id_wrapper); + builder.edit_file(file_id); let possible_ranges = references .into_iter() .filter_map(|usage| process_usage(&source_file, usage, arg_to_remove, is_self_present)); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs index b4042abf5d649..4f751b68e7f0b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -3,7 +3,7 @@ mod generated; use expect_test::expect; use hir::{FileRange, Semantics}; use ide_db::{ - base_db::{SourceDatabase, SourceRootDatabase}, + base_db::SourceDatabase, imports::insert_use::{ImportGranularity, InsertUseConfig}, source_change::FileSystemEdit, EditionedFileId, RootDatabase, SnippetCap, @@ -222,7 +222,7 @@ pub(crate) fn check_assist_unresolved( fn check_doc_test(assist_id: &str, before: &str, after: &str) { let after = trim_indent(after); let (db, file_id, selection) = RootDatabase::with_range_or_offset(before); - let before = db.file_text(file_id.file_id()).to_string(); + let before = db.file_text(file_id.file_id()).text(&db).to_string(); let frange = FileRange { file_id, range: selection.into() }; let assist = assists(&db, &TEST_CONFIG, AssistResolveStrategy::All, frange.into()) @@ -281,7 +281,7 @@ fn check_with_config( ) { let (mut db, file_with_caret_id, range_or_offset) = RootDatabase::with_range_or_offset(before); db.enable_proc_attr_macros(); - let text_without_caret = db.file_text(file_with_caret_id.into()).to_string(); + let text_without_caret = db.file_text(file_with_caret_id.into()).text(&db).to_string(); let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() }; @@ -311,14 +311,14 @@ fn check_with_config( let mut buf = String::new(); for (file_id, (edit, snippet_edit)) in source_change.source_file_edits { - let mut text = db.file_text(file_id).as_ref().to_owned(); + let mut text = db.file_text(file_id).text(&db).as_ref().to_owned(); edit.apply(&mut text); if let Some(snippet_edit) = snippet_edit { snippet_edit.apply(&mut text); } if !skip_header { - let sr = db.file_source_root(file_id); - let sr = db.source_root(sr); + let source_root_id = db.file_source_root(file_id).source_root_id(&db); + let sr = db.source_root(source_root_id).source_root(&db); let path = sr.path_for_file(&file_id).unwrap(); format_to!(buf, "//- {}\n", path) } @@ -329,15 +329,16 @@ fn check_with_config( let (dst, contents) = match file_system_edit { FileSystemEdit::CreateFile { dst, initial_contents } => (dst, initial_contents), FileSystemEdit::MoveFile { src, dst } => { - (dst, db.file_text(src).as_ref().to_owned()) + (dst, db.file_text(src).text(&db).as_ref().to_owned()) } FileSystemEdit::MoveDir { src, src_id, dst } => { // temporary placeholder for MoveDir since we are not using MoveDir in ide assists yet. (dst, format!("{src_id:?}\n{src:?}")) } }; - let sr = db.file_source_root(dst.anchor); - let sr = db.source_root(sr); + + let source_root_id = db.file_source_root(dst.anchor).source_root_id(&db); + let sr = db.source_root(source_root_id).source_root(&db); let mut base = sr.path_for_file(&dst.anchor).unwrap().clone(); base.pop(); let created_file_path = base.join(&dst.path).unwrap(); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs index cca6a22f290d2..fad7c92d8aecb 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs @@ -4,7 +4,7 @@ use std::iter; use hir::{HirFileIdExt, Module}; use ide_db::{ - base_db::{SourceRootDatabase, VfsPath}, + base_db::{SourceDatabase, VfsPath}, FxHashSet, RootDatabase, SymbolKind, }; use syntax::{ast, AstNode, SyntaxKind}; @@ -43,7 +43,10 @@ pub(crate) fn complete_mod( let module_definition_file = current_module.definition_source_file_id(ctx.db).original_file(ctx.db); - let source_root = ctx.db.source_root(ctx.db.file_source_root(module_definition_file.file_id())); + let source_root_id = + ctx.db.file_source_root(module_definition_file.file_id()).source_root_id(ctx.db); + let source_root = ctx.db.source_root(source_root_id).source_root(ctx.db); + let directory_to_look_for_submodules = directory_to_look_for_submodules( current_module, ctx.db, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs index 28e2853096e0e..611f8a2873d7b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs @@ -277,7 +277,7 @@ fn get_receiver_text( range.range = TextRange::at(range.range.start(), range.range.len() - TextSize::of('.')) } let file_text = sema.db.file_text(range.file_id.file_id()); - let mut text = file_text[range.range].to_owned(); + let mut text = file_text.text(sema.db)[range.range].to_owned(); // The receiver texts should be interpreted as-is, as they are expected to be // normal Rust expressions. diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index e686a29309461..54620bbad1bce 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -6,13 +6,14 @@ mod tests; use std::{iter, ops::ControlFlow}; +use base_db::{salsa::AsDynDatabase, RootQueryDb as _}; use hir::{ DisplayTarget, HasAttrs, Local, ModPath, ModuleDef, ModuleSource, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Symbol, Type, TypeInfo, }; use ide_db::{ - base_db::SourceDatabase, famous_defs::FamousDefs, helpers::is_editable_crate, FilePosition, - FxHashMap, FxHashSet, RootDatabase, + famous_defs::FamousDefs, helpers::is_editable_crate, FilePosition, FxHashMap, FxHashSet, + RootDatabase, }; use syntax::{ ast::{self, AttrKind, NameOrNameRef}, @@ -706,15 +707,19 @@ impl<'a> CompletionContext<'a> { let _p = tracing::info_span!("CompletionContext::new").entered(); let sema = Semantics::new(db); - let file_id = sema.attach_first_edition(file_id)?; - let original_file = sema.parse(file_id); + let editioned_file_id = sema.attach_first_edition(file_id)?; + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(sema.db.as_dyn_database(), editioned_file_id); + + let original_file = sema.parse(editioned_file_id_wrapper); // Insert a fake ident to get a valid parse tree. We will use this file // to determine context, though the original_file will be used for // actual completion. let file_with_fake_ident = { - let parse = db.parse(file_id); - parse.reparse(TextRange::empty(offset), COMPLETION_MARKER, file_id.edition()).tree() + let (_, edition) = editioned_file_id.unpack(); + let parse = db.parse(editioned_file_id_wrapper); + parse.reparse(TextRange::empty(offset), COMPLETION_MARKER, edition).tree() }; // always pick the token to the immediate left of the cursor, as that is what we are actually diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs index a990b39481a19..c9fc5ae152400 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs @@ -11,6 +11,7 @@ mod snippet; mod tests; use ide_db::{ + base_db::salsa::AsDynDatabase, imports::insert_use::{self, ImportScope}, syntax_helpers::tree_diff::diff, text_edit::TextEdit, @@ -275,7 +276,11 @@ pub fn resolve_completion_edits( let _p = tracing::info_span!("resolve_completion_edits").entered(); let sema = hir::Semantics::new(db); - let original_file = sema.parse(sema.attach_first_edition(file_id)?); + let editioned_file_id = sema.attach_first_edition(file_id)?; + let editioned_file_id = + ide_db::base_db::EditionedFileId::new(db.as_dyn_database(), editioned_file_id); + + let original_file = sema.parse(editioned_file_id); let original_token = syntax::AstNode::syntax(&original_file).token_at_offset(offset).left_biased()?; let position_for_import = &original_token.parent()?; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 0735be38cd9c8..0f0fa115af0b3 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -2042,8 +2042,8 @@ fn f() { A { bar: b$0 }; } expect![[r#" fn bar() fn() -> u8 [type+name] fn baz() fn() -> u8 [type] - ex bar() [type] ex baz() [type] + ex bar() [type] st A A [] fn f() fn() [] "#]], diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs index 9d91f95eb65b8..2984348a3278d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs @@ -246,7 +246,7 @@ pub(crate) fn check_edit_with_config( .filter(|it| it.lookup() == what) .collect_tuple() .unwrap_or_else(|| panic!("can't find {what:?} completion in {completions:#?}")); - let mut actual = db.file_text(position.file_id).to_string(); + let mut actual = db.file_text(position.file_id).text(&db).to_string(); let mut combined_edit = completion.text_edit.clone(); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs index 9ab66243b5c8c..823cc8c3d8c55 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs @@ -7,7 +7,7 @@ use crate::tests::{completion_list_with_config_raw, position, TEST_CONFIG}; fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let completions = completion_list_with_config_raw(TEST_CONFIG, ra_fixture, true, None); let (db, position) = position(ra_fixture); - let mut actual = db.file_text(position.file_id).to_string(); + let mut actual = db.file_text(position.file_id).text(&db).to_string(); completions .into_iter() .exactly_one() diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml index 641998c3dacaf..848556523387e 100644 --- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml @@ -15,6 +15,7 @@ rust-version.workspace = true cov-mark = "2.0.0-pre.1" crossbeam-channel.workspace = true tracing.workspace = true +dashmap.workspace = true rayon.workspace = true fst = { version = "0.4.7", default-features = false } rustc-hash.workspace = true @@ -23,6 +24,8 @@ itertools.workspace = true arrayvec.workspace = true indexmap.workspace = true memchr = "2.6.4" +salsa.workspace = true +query-group.workspace = true triomphe.workspace = true nohash-hasher.workspace = true bitflags.workspace = true @@ -34,6 +37,7 @@ profile.workspace = true stdx.workspace = true syntax.workspace = true span.workspace = true +vfs.workspace = true # ide should depend only on the top-level `hir` package. if you need # something from some `hir-xxx` subpackage, reexport the API via `hir`. hir.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs index 46ff4fbf9e904..d8b265678278b 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs @@ -1,14 +1,9 @@ //! Applies changes to the IDE state transactionally. -use base_db::{ - ra_salsa::{ - debug::{DebugQueryTable, TableEntry}, - Database, Durability, Query, QueryTable, - }, - SourceRootId, -}; -use profile::{memory_usage, Bytes}; +use base_db::SourceRootId; +use profile::Bytes; use rustc_hash::FxHashSet; +use salsa::{Database as _, Durability}; use triomphe::Arc; use crate::{symbol_index::SymbolsDatabase, ChangeWithProcMacros, RootDatabase}; @@ -52,23 +47,23 @@ impl RootDatabase { pub fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes, usize)> { let mut acc: Vec<(String, Bytes, usize)> = vec![]; - fn collect_query_count<'q, Q>(table: &QueryTable<'q, Q>) -> usize - where - QueryTable<'q, Q>: DebugQueryTable, - Q: Query, - ::Storage: 'q, - { - struct EntryCounter(usize); - impl FromIterator> for EntryCounter { - fn from_iter(iter: T) -> EntryCounter - where - T: IntoIterator>, - { - EntryCounter(iter.into_iter().count()) - } - } - table.entries::().0 - } + // fn collect_query_count<'q, Q>(table: &QueryTable<'q, Q>) -> usize + // where + // QueryTable<'q, Q>: DebugQueryTable, + // Q: Query, + // ::Storage: 'q, + // { + // struct EntryCounter(usize); + // impl FromIterator> for EntryCounter { + // fn from_iter(iter: T) -> EntryCounter + // where + // T: IntoIterator>, + // { + // EntryCounter(iter.into_iter().count()) + // } + // } + // table.entries::().0 + // } macro_rules! purge_each_query { ($($q:path)*) => {$( @@ -83,170 +78,170 @@ impl RootDatabase { )*} } purge_each_query![ - // SymbolsDatabase - crate::symbol_index::ModuleSymbolsQuery - crate::symbol_index::LibrarySymbolsQuery - crate::symbol_index::LocalRootsQuery - crate::symbol_index::LibraryRootsQuery - // HirDatabase - hir::db::AdtDatumQuery - hir::db::AdtVarianceQuery - hir::db::AssociatedTyDataQuery - hir::db::AssociatedTyValueQuery - hir::db::BorrowckQuery - hir::db::CallableItemSignatureQuery - hir::db::ConstEvalDiscriminantQuery - hir::db::ConstEvalQuery - hir::db::ConstEvalStaticQuery - hir::db::ConstParamTyQuery - hir::db::DynCompatibilityOfTraitQuery - hir::db::FieldTypesQuery - hir::db::FnDefDatumQuery - hir::db::FnDefVarianceQuery - hir::db::GenericDefaultsQuery - hir::db::GenericPredicatesForParamQuery - hir::db::GenericPredicatesQuery - hir::db::GenericPredicatesWithoutParentQuery - hir::db::ImplDatumQuery - hir::db::ImplSelfTyQuery - hir::db::ImplTraitQuery - hir::db::IncoherentInherentImplCratesQuery - hir::db::InferQuery - hir::db::InherentImplsInBlockQuery - hir::db::InherentImplsInCrateQuery - hir::db::InternCallableDefQuery - hir::db::InternClosureQuery - hir::db::InternCoroutineQuery - hir::db::InternImplTraitIdQuery - hir::db::InternLifetimeParamIdQuery - hir::db::InternTypeOrConstParamIdQuery - hir::db::LayoutOfAdtQuery - hir::db::LayoutOfTyQuery - hir::db::LookupImplMethodQuery - hir::db::MirBodyForClosureQuery - hir::db::MirBodyQuery - hir::db::MonomorphizedMirBodyForClosureQuery - hir::db::MonomorphizedMirBodyQuery - hir::db::ProgramClausesForChalkEnvQuery - hir::db::ReturnTypeImplTraitsQuery - hir::db::TargetDataLayoutQuery - hir::db::TraitDatumQuery - hir::db::TraitEnvironmentQuery - hir::db::TraitImplsInBlockQuery - hir::db::TraitImplsInCrateQuery - hir::db::TraitImplsInDepsQuery - hir::db::TraitSolveQuery - hir::db::TyQuery - hir::db::TypeAliasImplTraitsQuery - hir::db::ValueTyQuery + // // SymbolsDatabase + // crate::symbol_index::ModuleSymbolsQuery + // crate::symbol_index::LibrarySymbolsQuery + // crate::symbol_index::LocalRootsQuery + // crate::symbol_index::LibraryRootsQuery + // // HirDatabase + // hir::db::AdtDatumQuery + // hir::db::AdtVarianceQuery + // hir::db::AssociatedTyDataQuery + // hir::db::AssociatedTyValueQuery + // hir::db::BorrowckQuery + // hir::db::CallableItemSignatureQuery + // hir::db::ConstEvalDiscriminantQuery + // hir::db::ConstEvalQuery + // hir::db::ConstEvalStaticQuery + // hir::db::ConstParamTyQuery + // hir::db::DynCompatibilityOfTraitQuery + // hir::db::FieldTypesQuery + // hir::db::FnDefDatumQuery + // hir::db::FnDefVarianceQuery + // hir::db::GenericDefaultsQuery + // hir::db::GenericPredicatesForParamQuery + // hir::db::GenericPredicatesQuery + // hir::db::GenericPredicatesWithoutParentQuery + // hir::db::ImplDatumQuery + // hir::db::ImplSelfTyQuery + // hir::db::ImplTraitQuery + // hir::db::IncoherentInherentImplCratesQuery + // hir::db::InferQuery + // hir::db::InherentImplsInBlockQuery + // hir::db::InherentImplsInCrateQuery + // hir::db::InternCallableDefQuery + // hir::db::InternClosureQuery + // hir::db::InternCoroutineQuery + // hir::db::InternImplTraitIdQuery + // hir::db::InternLifetimeParamIdQuery + // hir::db::InternTypeOrConstParamIdQuery + // hir::db::LayoutOfAdtQuery + // hir::db::LayoutOfTyQuery + // hir::db::LookupImplMethodQuery + // hir::db::MirBodyForClosureQuery + // hir::db::MirBodyQuery + // hir::db::MonomorphizedMirBodyForClosureQuery + // hir::db::MonomorphizedMirBodyQuery + // hir::db::ProgramClausesForChalkEnvQuery + // hir::db::ReturnTypeImplTraitsQuery + // hir::db::TargetDataLayoutQuery + // hir::db::TraitDatumQuery + // hir::db::TraitEnvironmentQuery + // hir::db::TraitImplsInBlockQuery + // hir::db::TraitImplsInCrateQuery + // hir::db::TraitImplsInDepsQuery + // hir::db::TraitSolveQuery + // hir::db::TyQuery + // hir::db::TypeAliasImplTraitsQuery + // hir::db::ValueTyQuery - // DefDatabase - hir::db::AttrsQuery - hir::db::BlockDefMapQuery - hir::db::BlockItemTreeQuery - hir::db::BlockItemTreeWithSourceMapQuery - hir::db::BodyQuery - hir::db::BodyWithSourceMapQuery - hir::db::ConstDataQuery - hir::db::ConstVisibilityQuery - hir::db::CrateDefMapQuery - hir::db::CrateLangItemsQuery - hir::db::CrateNotableTraitsQuery - hir::db::CrateSupportsNoStdQuery - hir::db::EnumDataQuery - hir::db::EnumVariantDataWithDiagnosticsQuery - hir::db::ExpandProcAttrMacrosQuery - hir::db::ExprScopesQuery - hir::db::ExternCrateDeclDataQuery - hir::db::FieldVisibilitiesQuery - hir::db::FieldsAttrsQuery - hir::db::FieldsAttrsSourceMapQuery - hir::db::FileItemTreeQuery - hir::db::FileItemTreeWithSourceMapQuery - hir::db::FunctionDataQuery - hir::db::FunctionVisibilityQuery - hir::db::GenericParamsQuery - hir::db::GenericParamsWithSourceMapQuery - hir::db::ImplDataWithDiagnosticsQuery - hir::db::ImportMapQuery - hir::db::IncludeMacroInvocQuery - hir::db::InternAnonymousConstQuery - hir::db::InternBlockQuery - hir::db::InternConstQuery - hir::db::InternEnumQuery - hir::db::InternExternBlockQuery - hir::db::InternExternCrateQuery - hir::db::InternFunctionQuery - hir::db::InternImplQuery - hir::db::InternInTypeConstQuery - hir::db::InternMacro2Query - hir::db::InternMacroRulesQuery - hir::db::InternProcMacroQuery - hir::db::InternStaticQuery - hir::db::InternStructQuery - hir::db::InternTraitAliasQuery - hir::db::InternTraitQuery - hir::db::InternTypeAliasQuery - hir::db::InternUnionQuery - hir::db::InternUseQuery - hir::db::LangItemQuery - hir::db::Macro2DataQuery - hir::db::MacroDefQuery - hir::db::MacroRulesDataQuery - hir::db::NotableTraitsInDepsQuery - hir::db::ProcMacroDataQuery - hir::db::StaticDataQuery - hir::db::StructDataWithDiagnosticsQuery - hir::db::TraitAliasDataQuery - hir::db::TraitDataWithDiagnosticsQuery - hir::db::TypeAliasDataQuery - hir::db::UnionDataWithDiagnosticsQuery + // // DefDatabase + // hir::db::AttrsQuery + // hir::db::BlockDefMapQuery + // hir::db::BlockItemTreeQuery + // hir::db::BlockItemTreeWithSourceMapQuery + // hir::db::BodyQuery + // hir::db::BodyWithSourceMapQuery + // hir::db::ConstDataQuery + // hir::db::ConstVisibilityQuery + // hir::db::CrateDefMapQuery + // hir::db::CrateLangItemsQuery + // hir::db::CrateNotableTraitsQuery + // hir::db::CrateSupportsNoStdQuery + // hir::db::EnumDataQuery + // hir::db::EnumVariantDataWithDiagnosticsQuery + // hir::db::ExpandProcAttrMacrosQuery + // hir::db::ExprScopesQuery + // hir::db::ExternCrateDeclDataQuery + // hir::db::FieldVisibilitiesQuery + // hir::db::FieldsAttrsQuery + // hir::db::FieldsAttrsSourceMapQuery + // hir::db::FileItemTreeQuery + // hir::db::FileItemTreeWithSourceMapQuery + // hir::db::FunctionDataQuery + // hir::db::FunctionVisibilityQuery + // hir::db::GenericParamsQuery + // hir::db::GenericParamsWithSourceMapQuery + // hir::db::ImplDataWithDiagnosticsQuery + // hir::db::ImportMapQuery + // hir::db::IncludeMacroInvocQuery + // hir::db::InternAnonymousConstQuery + // hir::db::InternBlockQuery + // hir::db::InternConstQuery + // hir::db::InternEnumQuery + // hir::db::InternExternBlockQuery + // hir::db::InternExternCrateQuery + // hir::db::InternFunctionQuery + // hir::db::InternImplQuery + // hir::db::InternInTypeConstQuery + // hir::db::InternMacro2Query + // hir::db::InternMacroRulesQuery + // hir::db::InternProcMacroQuery + // hir::db::InternStaticQuery + // hir::db::InternStructQuery + // hir::db::InternTraitAliasQuery + // hir::db::InternTraitQuery + // hir::db::InternTypeAliasQuery + // hir::db::InternUnionQuery + // hir::db::InternUseQuery + // hir::db::LangItemQuery + // hir::db::Macro2DataQuery + // hir::db::MacroDefQuery + // hir::db::MacroRulesDataQuery + // hir::db::NotableTraitsInDepsQuery + // hir::db::ProcMacroDataQuery + // hir::db::StaticDataQuery + // hir::db::StructDataWithDiagnosticsQuery + // hir::db::TraitAliasDataQuery + // hir::db::TraitDataWithDiagnosticsQuery + // hir::db::TypeAliasDataQuery + // hir::db::UnionDataWithDiagnosticsQuery - // InternDatabase - hir::db::InternFunctionQuery - hir::db::InternStructQuery - hir::db::InternUnionQuery - hir::db::InternEnumQuery - hir::db::InternConstQuery - hir::db::InternStaticQuery - hir::db::InternTraitQuery - hir::db::InternTraitAliasQuery - hir::db::InternTypeAliasQuery - hir::db::InternImplQuery - hir::db::InternExternBlockQuery - hir::db::InternBlockQuery - hir::db::InternMacro2Query - hir::db::InternProcMacroQuery - hir::db::InternMacroRulesQuery + // // InternDatabase + // hir::db::InternFunctionQuery + // hir::db::InternStructQuery + // hir::db::InternUnionQuery + // hir::db::InternEnumQuery + // hir::db::InternConstQuery + // hir::db::InternStaticQuery + // hir::db::InternTraitQuery + // hir::db::InternTraitAliasQuery + // hir::db::InternTypeAliasQuery + // hir::db::InternImplQuery + // hir::db::InternExternBlockQuery + // hir::db::InternBlockQuery + // hir::db::InternMacro2Query + // hir::db::InternProcMacroQuery + // hir::db::InternMacroRulesQuery - // ExpandDatabase - hir::db::AstIdMapQuery - hir::db::DeclMacroExpanderQuery - hir::db::ExpandProcMacroQuery - hir::db::InternMacroCallQuery - hir::db::InternSyntaxContextQuery - hir::db::MacroArgQuery - hir::db::ParseMacroExpansionErrorQuery - hir::db::ParseMacroExpansionQuery - hir::db::ProcMacroSpanQuery - hir::db::ProcMacrosQuery - hir::db::RealSpanMapQuery + // // ExpandDatabase + // hir::db::AstIdMapQuery + // hir::db::DeclMacroExpanderQuery + // hir::db::ExpandProcMacroQuery + // hir::db::InternMacroCallQuery + // hir::db::InternSyntaxContextQuery + // hir::db::MacroArgQuery + // hir::db::ParseMacroExpansionErrorQuery + // hir::db::ParseMacroExpansionQuery + // hir::db::ProcMacroSpanQuery + // hir::db::ProcMacrosQuery + // hir::db::RealSpanMapQuery - // LineIndexDatabase - crate::LineIndexQuery + // // LineIndexDatabase + // crate::LineIndexQuery - // SourceDatabase - base_db::ParseQuery - base_db::ParseErrorsQuery - base_db::CrateGraphQuery - base_db::CrateWorkspaceDataQuery + // // SourceDatabase + // base_db::ParseQuery + // base_db::ParseErrorsQuery + // base_db::CrateGraphQuery + // base_db::CrateWorkspaceDataQuery - // SourceDatabaseExt - base_db::FileTextQuery - base_db::CompressedFileTextQuery - base_db::FileSourceRootQuery - base_db::SourceRootQuery - base_db::SourceRootCratesQuery + // // SourceDatabaseExt + // base_db::FileTextQuery + // base_db::CompressedFileTextQuery + // base_db::FileSourceRootQuery + // base_db::SourceRootQuery + // base_db::SourceRootCratesQuery ]; acc.sort_by_key(|it| std::cmp::Reverse(it.1)); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs index 2f4d07446f2c1..af4c10f8ea6b5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs @@ -1,6 +1,6 @@ //! See [`FamousDefs`]. -use base_db::{CrateOrigin, LangCrateOrigin, SourceDatabase}; +use base_db::{CrateOrigin, LangCrateOrigin, RootQueryDb as _}; use hir::{Crate, Enum, Function, Macro, Module, ScopeDef, Semantics, Trait}; use crate::RootDatabase; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs b/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs index 84fa58d743bbc..ebafc8876f249 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs @@ -2,7 +2,7 @@ use std::collections::VecDeque; -use base_db::SourceRootDatabase; +use base_db::SourceDatabase; use hir::{Crate, ItemInNs, ModuleDef, Name, Semantics}; use span::{Edition, FileId}; use syntax::{ @@ -108,8 +108,8 @@ pub fn lint_eq_or_in_group(lint: &str, lint_is: &str) -> bool { pub fn is_editable_crate(krate: Crate, db: &RootDatabase) -> bool { let root_file = krate.root_file(db); - let source_root_id = db.file_source_root(root_file); - !db.source_root(source_root_id).is_library + let source_root_id = db.file_source_root(root_file).source_root_id(db); + !db.source_root(source_root_id).source_root(db).is_library } // FIXME: This is a weird function diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs index decb0ea9d8a8a..39810c615bb77 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs @@ -1,3 +1,4 @@ +use salsa::AsDynDatabase; use stdx::trim_indent; use test_fixture::WithFixture; use test_utils::{assert_eq_text, CURSOR_MARKER}; @@ -1250,9 +1251,15 @@ fn check_with_config( ) { let (db, file_id, pos) = if ra_fixture_before.contains(CURSOR_MARKER) { let (db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture_before); + + let file_id = crate::base_db::EditionedFileId::new(db.as_dyn_database(), file_id); + (db, file_id, Some(range_or_offset)) } else { let (db, file_id) = RootDatabase::with_single_file(ra_fixture_before); + + let file_id = crate::base_db::EditionedFileId::new(db.as_dyn_database(), file_id); + (db, file_id, None) }; let sema = &Semantics::new(&db); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs index 96115eee6dc2a..2516a9d0aa388 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -46,13 +46,14 @@ pub mod syntax_helpers { } pub use hir::ChangeWithProcMacros; +use salsa::Durability; use std::{fmt, mem::ManuallyDrop}; use base_db::{ - ra_salsa::{self, Durability}, - AnchoredPath, CrateId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast, - DEFAULT_FILE_TEXT_LRU_CAP, + query_group::{self}, + FileSourceRootInput, FileText, Files, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId, + SourceRootInput, Upcast, }; use hir::{ db::{DefDatabase, ExpandDatabase, HirDatabase}, @@ -76,22 +77,21 @@ pub type FxIndexMap = pub type FilePosition = FilePositionWrapper; pub type FileRange = FileRangeWrapper; -#[ra_salsa::database( - base_db::SourceRootDatabaseStorage, - base_db::SourceDatabaseStorage, - hir::db::ExpandDatabaseStorage, - hir::db::DefDatabaseStorage, - hir::db::HirDatabaseStorage, - hir::db::InternDatabaseStorage, - LineIndexDatabaseStorage, - symbol_index::SymbolsDatabaseStorage -)] +#[salsa::db] pub struct RootDatabase { // We use `ManuallyDrop` here because every codegen unit that contains a // `&RootDatabase -> &dyn OtherDatabase` cast will instantiate its drop glue in the vtable, // which duplicates `Weak::drop` and `Arc::drop` tens of thousands of times, which makes // compile times of all `ide_*` and downstream crates suffer greatly. - storage: ManuallyDrop>, + storage: ManuallyDrop>, + files: Arc, +} + +impl std::panic::RefUnwindSafe for RootDatabase {} + +#[salsa::db] +impl salsa::Database for RootDatabase { + fn salsa_event(&self, _event: &dyn Fn() -> salsa::Event) {} } impl Drop for RootDatabase { @@ -100,6 +100,12 @@ impl Drop for RootDatabase { } } +impl Clone for RootDatabase { + fn clone(&self) -> Self { + Self { storage: self.storage.clone(), files: self.files.clone() } + } +} + impl fmt::Debug for RootDatabase { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RootDatabase").finish() @@ -127,16 +133,68 @@ impl Upcast for RootDatabase { } } -impl FileLoader for RootDatabase { - fn resolve_path(&self, path: AnchoredPath<'_>) -> Option { - FileLoaderDelegate(self).resolve_path(path) +impl Upcast for RootDatabase { + fn upcast(&self) -> &(dyn RootQueryDb + 'static) { + self } - fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { - FileLoaderDelegate(self).relevant_crates(file_id) +} + +impl Upcast for RootDatabase { + fn upcast(&self) -> &(dyn SourceDatabase + 'static) { + self } } -impl ra_salsa::Database for RootDatabase {} +#[salsa::db] +impl SourceDatabase for RootDatabase { + fn file_text(&self, file_id: vfs::FileId) -> FileText { + self.files.file_text(file_id) + } + + fn set_file_text(&mut self, file_id: vfs::FileId, text: &str) { + let files = Arc::clone(&self.files); + files.set_file_text(self, file_id, text); + } + + fn set_file_text_with_durability( + &mut self, + file_id: vfs::FileId, + text: &str, + durability: Durability, + ) { + let files = Arc::clone(&self.files); + files.set_file_text_with_durability(self, file_id, text, durability); + } + + /// Source root of the file. + fn source_root(&self, source_root_id: SourceRootId) -> SourceRootInput { + self.files.source_root(source_root_id) + } + + fn set_source_root_with_durability( + &mut self, + source_root_id: SourceRootId, + source_root: Arc, + durability: Durability, + ) { + let files = Arc::clone(&self.files); + files.set_source_root_with_durability(self, source_root_id, source_root, durability); + } + + fn file_source_root(&self, id: vfs::FileId) -> FileSourceRootInput { + self.files.file_source_root(id) + } + + fn set_file_source_root_with_durability( + &mut self, + id: vfs::FileId, + source_root_id: SourceRootId, + durability: Durability, + ) { + let files = Arc::clone(&self.files); + files.set_file_source_root_with_durability(self, id, source_root_id, durability); + } +} impl Default for RootDatabase { fn default() -> RootDatabase { @@ -146,14 +204,16 @@ impl Default for RootDatabase { impl RootDatabase { pub fn new(lru_capacity: Option) -> RootDatabase { - let mut db = RootDatabase { storage: ManuallyDrop::new(ra_salsa::Storage::default()) }; + let mut db = RootDatabase { + storage: ManuallyDrop::new(salsa::Storage::default()), + files: Default::default(), + }; db.set_crate_graph_with_durability(Default::default(), Durability::HIGH); db.set_proc_macros_with_durability(Default::default(), Durability::HIGH); db.set_local_roots_with_durability(Default::default(), Durability::HIGH); db.set_library_roots_with_durability(Default::default(), Durability::HIGH); db.set_expand_proc_attr_macros_with_durability(false, Durability::HIGH); db.update_base_query_lru_capacities(lru_capacity); - db.setup_syntax_context_root(); db } @@ -161,57 +221,54 @@ impl RootDatabase { self.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); } - pub fn update_base_query_lru_capacities(&mut self, lru_capacity: Option) { - let lru_capacity = lru_capacity.unwrap_or(base_db::DEFAULT_PARSE_LRU_CAP); - base_db::FileTextQuery.in_db_mut(self).set_lru_capacity(DEFAULT_FILE_TEXT_LRU_CAP); - base_db::ParseQuery.in_db_mut(self).set_lru_capacity(lru_capacity); - // macro expansions are usually rather small, so we can afford to keep more of them alive - hir::db::ParseMacroExpansionQuery.in_db_mut(self).set_lru_capacity(4 * lru_capacity); - hir::db::BorrowckQuery.in_db_mut(self).set_lru_capacity(base_db::DEFAULT_BORROWCK_LRU_CAP); - hir::db::BodyWithSourceMapQuery.in_db_mut(self).set_lru_capacity(2048); + pub fn update_base_query_lru_capacities(&mut self, _lru_capacity: Option) { + // let lru_capacity = lru_capacity.unwrap_or(base_db::DEFAULT_PARSE_LRU_CAP); + // base_db::FileTextQuery.in_db_mut(self).set_lru_capacity(DEFAULT_FILE_TEXT_LRU_CAP); + // base_db::ParseQuery.in_db_mut(self).set_lru_capacity(lru_capacity); + // // macro expansions are usually rather small, so we can afford to keep more of them alive + // hir::db::ParseMacroExpansionQuery.in_db_mut(self).set_lru_capacity(4 * lru_capacity); + // hir::db::BorrowckQuery.in_db_mut(self).set_lru_capacity(base_db::DEFAULT_BORROWCK_LRU_CAP); + // hir::db::BodyWithSourceMapQuery.in_db_mut(self).set_lru_capacity(2048); } - pub fn update_lru_capacities(&mut self, lru_capacities: &FxHashMap, u16>) { - use hir::db as hir_db; - - base_db::FileTextQuery.in_db_mut(self).set_lru_capacity(DEFAULT_FILE_TEXT_LRU_CAP); - base_db::ParseQuery.in_db_mut(self).set_lru_capacity( - lru_capacities - .get(stringify!(ParseQuery)) - .copied() - .unwrap_or(base_db::DEFAULT_PARSE_LRU_CAP), - ); - hir_db::ParseMacroExpansionQuery.in_db_mut(self).set_lru_capacity( - lru_capacities - .get(stringify!(ParseMacroExpansionQuery)) - .copied() - .unwrap_or(4 * base_db::DEFAULT_PARSE_LRU_CAP), - ); - hir_db::BorrowckQuery.in_db_mut(self).set_lru_capacity( - lru_capacities - .get(stringify!(BorrowckQuery)) - .copied() - .unwrap_or(base_db::DEFAULT_BORROWCK_LRU_CAP), - ); - hir::db::BodyWithSourceMapQuery.in_db_mut(self).set_lru_capacity(2048); + pub fn update_lru_capacities(&mut self, _lru_capacities: &FxHashMap, u16>) { + // FIXME(salsa-transition): bring this back; allow changing LRU settings at runtime. + // use hir::db as hir_db; + + // base_db::FileTextQuery.in_db_mut(self).set_lru_capacity(DEFAULT_FILE_TEXT_LRU_CAP); + // base_db::ParseQuery.in_db_mut(self).set_lru_capacity( + // lru_capacities + // .get(stringify!(ParseQuery)) + // .copied() + // .unwrap_or(base_db::DEFAULT_PARSE_LRU_CAP), + // ); + // hir_db::ParseMacroExpansionQuery.in_db_mut(self).set_lru_capacity( + // lru_capacities + // .get(stringify!(ParseMacroExpansionQuery)) + // .copied() + // .unwrap_or(4 * base_db::DEFAULT_PARSE_LRU_CAP), + // ); + // hir_db::BorrowckQuery.in_db_mut(self).set_lru_capacity( + // lru_capacities + // .get(stringify!(BorrowckQuery)) + // .copied() + // .unwrap_or(base_db::DEFAULT_BORROWCK_LRU_CAP), + // ); + // hir::db::BodyWithSourceMapQuery.in_db_mut(self).set_lru_capacity(2048); } -} -impl ra_salsa::ParallelDatabase for RootDatabase { - fn snapshot(&self) -> ra_salsa::Snapshot { - ra_salsa::Snapshot::new(RootDatabase { - storage: ManuallyDrop::new(self.storage.snapshot()), - }) + pub fn snapshot(&self) -> Self { + Self { storage: self.storage.clone(), files: self.files.clone() } } } -#[ra_salsa::query_group(LineIndexDatabaseStorage)] -pub trait LineIndexDatabase: base_db::SourceDatabase { +#[query_group::query_group] +pub trait LineIndexDatabase: base_db::RootQueryDb { fn line_index(&self, file_id: FileId) -> Arc; } fn line_index(db: &dyn LineIndexDatabase, file_id: FileId) -> Arc { - let text = db.file_text(file_id); + let text = db.file_text(file_id).text(db); Arc::new(LineIndex::new(&text)) } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs index 22dc3d9e29d65..74d79cd69557f 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs @@ -8,12 +8,10 @@ use std::time::Duration; use hir::{db::DefDatabase, Symbol}; use itertools::Itertools; +use salsa::{Cancelled, Database}; use crate::{ - base_db::{ - ra_salsa::{Database, ParallelDatabase, Snapshot}, - Cancelled, CrateId, SourceDatabase, - }, + base_db::{CrateId, RootQueryDb}, symbol_index::SymbolsDatabase, FxIndexMap, RootDatabase, }; @@ -66,7 +64,7 @@ pub fn parallel_prime_caches( let (work_sender, progress_receiver) = { let (progress_sender, progress_receiver) = crossbeam_channel::unbounded(); let (work_sender, work_receiver) = crossbeam_channel::unbounded(); - let prime_caches_worker = move |db: Snapshot| { + let prime_caches_worker = move |db: RootDatabase| { while let Ok((crate_id, crate_name, kind)) = work_receiver.recv() { progress_sender .send(ParallelPrimeCacheWorkerProgress::BeginCrate { crate_id, crate_name })?; @@ -90,7 +88,7 @@ pub fn parallel_prime_caches( stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) .allow_leak(true) .name(format!("PrimeCaches#{id}")) - .spawn(move || Cancelled::catch(|| worker(db))) + .spawn(move || Cancelled::catch(|| worker(db.snapshot()))) .expect("failed to spawn thread"); } @@ -108,7 +106,7 @@ pub fn parallel_prime_caches( let mut additional_phases = vec![]; while crates_done < crates_total { - db.unwind_if_cancelled(); + db.unwind_if_revision_cancelled(); for crate_id in &mut crates_to_prime { let krate = &graph[crate_id]; @@ -145,7 +143,7 @@ pub fn parallel_prime_caches( } Err(crossbeam_channel::RecvTimeoutError::Disconnected) => { // our workers may have died from a cancelled task, so we'll check and re-raise here. - db.unwind_if_cancelled(); + db.unwind_if_revision_cancelled(); break; } }; @@ -177,7 +175,7 @@ pub fn parallel_prime_caches( } while crates_done < crates_total { - db.unwind_if_cancelled(); + db.unwind_if_revision_cancelled(); // recv_timeout is somewhat a hack, we need a way to from this thread check to see if the current salsa revision // is cancelled on a regular basis. workers will only exit if they are processing a task that is cancelled, or @@ -189,7 +187,7 @@ pub fn parallel_prime_caches( } Err(crossbeam_channel::RecvTimeoutError::Disconnected) => { // our workers may have died from a cancelled task, so we'll check and re-raise here. - db.unwind_if_cancelled(); + db.unwind_if_revision_cancelled(); break; } }; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index 02cd8b8bdf510..81df0c0f0f88b 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -7,7 +7,7 @@ use std::mem; use std::{cell::LazyCell, cmp::Reverse}; -use base_db::{ra_salsa::Database, SourceDatabase, SourceRootDatabase}; +use base_db::{RootQueryDb, SourceDatabase}; use either::Either; use hir::{ sym, Adt, AsAssocItem, DefWithBody, FileRange, FileRangeWrapper, HasAttrs, HasContainer, @@ -17,6 +17,7 @@ use hir::{ use memchr::memmem::Finder; use parser::SyntaxKind; use rustc_hash::{FxHashMap, FxHashSet}; +use salsa::Database; use span::EditionedFileId; use syntax::{ ast::{self, HasName, Rename}, @@ -164,8 +165,8 @@ impl SearchScope { let graph = db.crate_graph(); for krate in graph.iter() { let root_file = graph[krate].root_file_id; - let source_root_id = db.file_source_root(root_file); - let source_root = db.source_root(source_root_id); + let source_root = db.file_source_root(root_file).source_root_id(db); + let source_root = db.source_root(source_root).source_root(db); entries.extend( source_root.iter().map(|id| (EditionedFileId::new(id, graph[krate].edition), None)), ); @@ -178,8 +179,9 @@ impl SearchScope { let mut entries = FxHashMap::default(); for rev_dep in of.transitive_reverse_dependencies(db) { let root_file = rev_dep.root_file(db); - let source_root_id = db.file_source_root(root_file); - let source_root = db.source_root(source_root_id); + + let source_root = db.file_source_root(root_file).source_root_id(db); + let source_root = db.source_root(source_root).source_root(db); entries.extend( source_root.iter().map(|id| (EditionedFileId::new(id, rev_dep.edition(db)), None)), ); @@ -190,8 +192,9 @@ impl SearchScope { /// Build a search scope spanning the given crate. fn krate(db: &RootDatabase, of: hir::Crate) -> SearchScope { let root_file = of.root_file(db); - let source_root_id = db.file_source_root(root_file); - let source_root = db.source_root(source_root_id); + + let source_root_id = db.file_source_root(root_file).source_root_id(db); + let source_root = db.source_root(source_root_id).source_root(db); SearchScope { entries: source_root .iter() @@ -483,7 +486,7 @@ impl<'a> FindUsages<'a> { scope: &'b SearchScope, ) -> impl Iterator, EditionedFileId, TextRange)> + 'b { scope.entries.iter().map(|(&file_id, &search_range)| { - let text = db.file_text(file_id.file_id()); + let text = db.file_text(file_id.file_id()).text(db); let search_range = search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(&*text))); @@ -649,6 +652,8 @@ impl<'a> FindUsages<'a> { for (file_text, file_id, search_range) in FindUsages::scope_files(db, ¤t_to_process_search_scope) { + let file_id = crate::base_db::EditionedFileId::new(db, file_id); + let tree = LazyCell::new(move || sema.parse(file_id).syntax().clone()); for offset in FindUsages::match_indices(&file_text, &finder, search_range) { @@ -808,7 +813,9 @@ impl<'a> FindUsages<'a> { sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool, ) { for (file_text, file_id, search_range) in files { - let tree = LazyCell::new(move || this.sema.parse(file_id).syntax().clone()); + let file_id_wrapper = crate::base_db::EditionedFileId::new(this.sema.db, file_id); + + let tree = LazyCell::new(move || this.sema.parse(file_id_wrapper).syntax().clone()); for offset in FindUsages::match_indices(&file_text, finder, search_range) { let usages = FindUsages::find_nodes(this.sema, name, &tree, offset) @@ -853,7 +860,7 @@ impl<'a> FindUsages<'a> { name, is_possibly_self.into_iter().map(|position| { ( - self.sema.db.file_text(position.file_id.file_id()), + self.sema.db.file_text(position.file_id.file_id()).text(self.sema.db), position.file_id, position.range, ) @@ -947,8 +954,9 @@ impl<'a> FindUsages<'a> { let include_self_kw_refs = self.include_self_kw_refs.as_ref().map(|ty| (ty, Finder::new("Self"))); for (text, file_id, search_range) in Self::scope_files(sema.db, &search_scope) { - self.sema.db.unwind_if_cancelled(); - let tree = LazyCell::new(move || sema.parse(file_id).syntax().clone()); + let file_id_wrapper = crate::base_db::EditionedFileId::new(sema.db, file_id); + + let tree = LazyCell::new(move || sema.parse(file_id_wrapper).syntax().clone()); // Search for occurrences of the items name for offset in Self::match_indices(&text, finder, search_range) { @@ -1001,8 +1009,10 @@ impl<'a> FindUsages<'a> { let finder = &Finder::new("super"); for (text, file_id, search_range) in Self::scope_files(sema.db, &scope) { - self.sema.db.unwind_if_cancelled(); - let tree = LazyCell::new(move || sema.parse(file_id).syntax().clone()); + self.sema.db.unwind_if_revision_cancelled(); + + let file_id_wrapper = crate::base_db::EditionedFileId::new(sema.db, file_id); + let tree = LazyCell::new(move || sema.parse(file_id_wrapper).syntax().clone()); for offset in Self::match_indices(&text, finder, search_range) { for name_ref in Self::find_nodes(sema, "super", &tree, offset) @@ -1050,10 +1060,13 @@ impl<'a> FindUsages<'a> { return; }; - let text = sema.db.file_text(file_id.file_id()); + let file_text = sema.db.file_text(file_id.file_id()); + let text = file_text.text(sema.db); let search_range = search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(&*text))); + let file_id = crate::base_db::EditionedFileId::new(sema.db, file_id); + let tree = LazyCell::new(|| sema.parse(file_id).syntax().clone()); let finder = &Finder::new("self"); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs index 2737436993deb..5fea97b32dbde 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs @@ -27,10 +27,7 @@ use std::{ ops::ControlFlow, }; -use base_db::{ - ra_salsa::{self, ParallelDatabase}, - SourceRootDatabase, SourceRootId, Upcast, -}; +use base_db::{RootQueryDb, SourceDatabase, SourceRootId, Upcast}; use fst::{raw::IndexedValue, Automaton, Streamer}; use hir::{ db::HirDatabase, @@ -99,8 +96,8 @@ impl Query { } } -#[ra_salsa::query_group(SymbolsDatabaseStorage)] -pub trait SymbolsDatabase: HirDatabase + SourceRootDatabase + Upcast { +#[query_group::query_group] +pub trait SymbolsDatabase: HirDatabase + SourceDatabase + Upcast { /// The symbol index for a given module. These modules should only be in source roots that /// are inside local_roots. fn module_symbols(&self, module: Module) -> Arc; @@ -108,18 +105,18 @@ pub trait SymbolsDatabase: HirDatabase + SourceRootDatabase + Upcast Arc; - #[ra_salsa::transparent] + #[salsa::transparent] /// The symbol indices of modules that make up a given crate. fn crate_symbols(&self, krate: Crate) -> Box<[Arc]>; /// The set of "local" (that is, from the current workspace) roots. /// Files in local roots are assumed to change frequently. - #[ra_salsa::input] + #[salsa::input] fn local_roots(&self) -> Arc>; /// The set of roots for crates.io libraries. /// Files in libraries are assumed to never change. - #[ra_salsa::input] + #[salsa::input] fn library_roots(&self) -> Arc>; } @@ -150,26 +147,6 @@ pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc(DB); -impl Snap> { - fn new(db: &DB) -> Self { - Self(db.snapshot()) - } -} -impl Clone for Snap> { - fn clone(&self) -> Snap> { - Snap(self.0.snapshot()) - } -} -impl std::ops::Deref for Snap { - type Target = DB; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - // Feature: Workspace Symbol // // Uses fuzzy-search to find types, modules and functions by name across your @@ -201,7 +178,7 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec { let indices: Vec<_> = if query.libs { db.library_roots() .par_iter() - .map_with(Snap::new(db), |snap, &root| snap.library_symbols(root)) + .map_with(db.clone(), |snap, &root| snap.library_symbols(root)) .collect() } else { let mut crates = Vec::new(); @@ -211,7 +188,7 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec { } let indices: Vec<_> = crates .into_par_iter() - .map_with(Snap::new(db), |snap, krate| snap.crate_symbols(krate.into())) + .map_with(db.clone(), |snap, krate| snap.crate_symbols(krate.into())) .collect(); indices.iter().flat_map(|indices| indices.iter().cloned()).collect() }; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs index e085bf15cb92d..21dd098781a85 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs @@ -457,9 +457,11 @@ mod tests { fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected: &str) { let (db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture); let frange = FileRange { file_id, range: range_or_offset.into() }; - let sema = Semantics::new(&db); - let source_file = sema.parse(frange.file_id); + + let file_id = crate::base_db::EditionedFileId::new(sema.db, frange.file_id); + let source_file = sema.parse(file_id); + let element = source_file.syntax().covering_element(frange.range); let expr = element.ancestors().find_map(ast::Expr::cast).expect("selection is not an expression"); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt index efcf53ded64f0..0cae7f367c205 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt @@ -14,7 +14,7 @@ Struct( Struct { id: StructId( - 1, + 4401, ), }, ), @@ -47,7 +47,7 @@ Struct( Struct { id: StructId( - 0, + 4400, ), }, ), @@ -80,7 +80,7 @@ Struct( Struct { id: StructId( - 0, + 4400, ), }, ), @@ -113,7 +113,7 @@ Struct( Struct { id: StructId( - 0, + 4400, ), }, ), @@ -146,7 +146,7 @@ Struct( Struct { id: StructId( - 0, + 4400, ), }, ), @@ -179,7 +179,7 @@ Struct( Struct { id: StructId( - 1, + 4401, ), }, ), @@ -212,7 +212,7 @@ Struct( Struct { id: StructId( - 0, + 4400, ), }, ), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt index 7dce95592b819..48de1fb837a20 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt @@ -13,7 +13,7 @@ def: TypeAlias( TypeAlias { id: TypeAliasId( - 0, + 8400, ), }, ), @@ -44,7 +44,7 @@ def: Const( Const { id: ConstId( - 0, + 7c00, ), }, ), @@ -75,7 +75,7 @@ def: Const( Const { id: ConstId( - 2, + 7c02, ), }, ), @@ -107,7 +107,7 @@ Enum( Enum { id: EnumId( - 0, + 6400, ), }, ), @@ -140,7 +140,7 @@ Macro { id: Macro2Id( Macro2Id( - 0, + 6000, ), ), }, @@ -173,7 +173,7 @@ Macro { id: Macro2Id( Macro2Id( - 0, + 6000, ), ), }, @@ -205,7 +205,7 @@ def: Static( Static { id: StaticId( - 0, + 8000, ), }, ), @@ -237,7 +237,7 @@ Struct( Struct { id: StructId( - 1, + 5c01, ), }, ), @@ -270,14 +270,14 @@ Struct( Struct { id: StructId( - 0, + 5c00, ), }, ), ), loc: DeclarationLocation { hir_file_id: MacroFile( - 0, + Id(4800), ), ptr: SyntaxNodePtr { kind: STRUCT, @@ -300,7 +300,7 @@ Struct( Struct { id: StructId( - 5, + 5c05, ), }, ), @@ -335,7 +335,7 @@ Struct( Struct { id: StructId( - 6, + 5c06, ), }, ), @@ -370,7 +370,7 @@ Struct( Struct { id: StructId( - 7, + 5c07, ), }, ), @@ -403,7 +403,7 @@ Struct( Struct { id: StructId( - 2, + 5c02, ), }, ), @@ -435,7 +435,7 @@ def: Trait( Trait { id: TraitId( - 0, + 7400, ), }, ), @@ -467,7 +467,7 @@ Macro { id: Macro2Id( Macro2Id( - 0, + 6000, ), ), }, @@ -500,7 +500,7 @@ Union( Union { id: UnionId( - 0, + 6c00, ), }, ), @@ -599,7 +599,7 @@ Macro { id: MacroRulesId( MacroRulesId( - 1, + 4401, ), ), }, @@ -631,7 +631,7 @@ def: Function( Function { id: FunctionId( - 2, + 7802, ), }, ), @@ -664,7 +664,7 @@ def: Function( Function { id: FunctionId( - 1, + 7801, ), }, ), @@ -698,7 +698,7 @@ Macro { id: MacroRulesId( MacroRulesId( - 0, + 4400, ), ), }, @@ -730,7 +730,7 @@ def: Function( Function { id: FunctionId( - 0, + 7800, ), }, ), @@ -762,7 +762,7 @@ Macro { id: MacroRulesId( MacroRulesId( - 1, + 4401, ), ), }, @@ -794,7 +794,7 @@ def: Function( Function { id: FunctionId( - 3, + 7803, ), }, ), @@ -839,7 +839,7 @@ Struct( Struct { id: StructId( - 3, + 5c03, ), }, ), @@ -882,7 +882,7 @@ def: Trait( Trait { id: TraitId( - 0, + 7400, ), }, ), @@ -914,7 +914,7 @@ Macro { id: Macro2Id( Macro2Id( - 0, + 6000, ), ), }, @@ -947,7 +947,7 @@ Struct( Struct { id: StructId( - 4, + 5c04, ), }, ), @@ -980,7 +980,7 @@ Macro { id: Macro2Id( Macro2Id( - 0, + 6000, ), ), }, @@ -1013,7 +1013,7 @@ Struct( Struct { id: StructId( - 4, + 5c04, ), }, ), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/traits.rs b/src/tools/rust-analyzer/crates/ide-db/src/traits.rs index 0f67496d0989e..fb231393a473d 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/traits.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/traits.rs @@ -116,6 +116,7 @@ mod tests { use expect_test::{expect, Expect}; use hir::FilePosition; use hir::Semantics; + use salsa::AsDynDatabase; use span::Edition; use syntax::ast::{self, AstNode}; use test_fixture::ChangeFixture; @@ -138,7 +139,11 @@ mod tests { fn check_trait(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (db, position) = position(ra_fixture); let sema = Semantics::new(&db); - let file = sema.parse(position.file_id); + + let editioned_file_id = + crate::base_db::EditionedFileId::new(sema.db.as_dyn_database(), position.file_id); + + let file = sema.parse(editioned_file_id); let impl_block: ast::Impl = sema.find_node_at_offset_with_descend(file.syntax(), position.offset).unwrap(); let trait_ = crate::traits::resolve_target_trait(&sema, &impl_block); @@ -152,7 +157,11 @@ mod tests { fn check_missing_assoc(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (db, position) = position(ra_fixture); let sema = Semantics::new(&db); - let file = sema.parse(position.file_id); + + let editioned_file_id = + crate::base_db::EditionedFileId::new(sema.db.as_dyn_database(), position.file_id); + + let file = sema.parse(editioned_file_id); let impl_block: ast::Impl = sema.find_node_at_offset_with_descend(file.syntax(), position.offset).unwrap(); let items = crate::traits::get_missing_assoc_items(&sema, &impl_block); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index c726a3bcd3cad..f17e9e64ab74e 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -1053,7 +1053,7 @@ fn test() -> String { fn f() { let mut x = (|| 1, 2); x = (|| 3, 4); - //^^^^ error: expected {closure#0}, found {closure#1} + //^^^^ error: expected {closure#23552}, found {closure#23553} } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs index f3109b9bb73a2..550751b6c01c4 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs @@ -3,9 +3,10 @@ use std::iter; use hir::{db::DefDatabase, DefMap, InFile, ModuleSource}; +use ide_db::base_db::RootQueryDb; use ide_db::text_edit::TextEdit; use ide_db::{ - base_db::{FileLoader, SourceDatabase, SourceRootDatabase}, + base_db::{SourceDatabase, Upcast}, source_change::SourceChange, FileId, FileRange, LineIndexDatabase, }; @@ -48,6 +49,7 @@ pub(crate) fn unlinked_file( // Only show this diagnostic on the first three characters of // the file, to avoid overwhelming the user during startup. range = SourceDatabase::file_text(ctx.sema.db, file_id) + .text(ctx.sema.db) .char_indices() .take(3) .last() @@ -78,7 +80,11 @@ fn fixes( // If there's an existing module that could add `mod` or `pub mod` items to include the unlinked file, // suggest that as a fix. - let source_root = ctx.sema.db.source_root(ctx.sema.db.file_source_root(file_id)); + let db = ctx.sema.db; + + let source_root = ctx.sema.db.file_source_root(file_id).source_root_id(db); + let source_root = ctx.sema.db.source_root(source_root).source_root(db); + let our_path = source_root.path_for_file(&file_id)?; let parent = our_path.parent()?; let (module_name, _) = our_path.name_and_extension()?; @@ -93,7 +99,8 @@ fn fixes( }; // check crate roots, i.e. main.rs, lib.rs, ... - 'crates: for &krate in &*ctx.sema.db.relevant_crates(file_id) { + let relevant_crates = Upcast::::upcast(db).relevant_crates(file_id); + 'crates: for &krate in &*relevant_crates { let crate_def_map = ctx.sema.db.crate_def_map(krate); let root_module = &crate_def_map[DefMap::ROOT]; @@ -141,7 +148,8 @@ fn fixes( paths.into_iter().find_map(|path| source_root.file_for_path(&path)) })?; stack.pop(); - 'crates: for &krate in ctx.sema.db.relevant_crates(parent_id).iter() { + let relevant_crates = Upcast::::upcast(db).relevant_crates(parent_id); + 'crates: for &krate in relevant_crates.iter() { let crate_def_map = ctx.sema.db.crate_def_map(krate); let Some((_, module)) = crate_def_map.modules().find(|(_, module)| { module.origin.file_id().map(Into::into) == Some(parent_id) && !module.origin.is_inline() diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index e15d349578914..5ce3336eb41f6 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -85,9 +85,10 @@ use hir::{ db::ExpandDatabase, diagnostics::AnyDiagnostic, Crate, DisplayTarget, HirFileId, InFile, Semantics, }; +use ide_db::base_db::salsa::AsDynDatabase; use ide_db::{ assists::{Assist, AssistId, AssistKind, AssistResolveStrategy}, - base_db::{ReleaseChannel, SourceDatabase}, + base_db::{ReleaseChannel, RootQueryDb as _}, generated::lints::{Lint, LintGroup, CLIPPY_LINT_GROUPS, DEFAULT_LINTS, DEFAULT_LINT_GROUPS}, imports::insert_use::InsertUseConfig, label::Label, @@ -319,12 +320,17 @@ pub fn syntax_diagnostics( } let sema = Semantics::new(db); - let file_id = sema + let editioned_file_id = sema .attach_first_edition(file_id) .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); + let (file_id, _) = editioned_file_id.unpack(); + + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(db.as_dyn_database(), editioned_file_id); + // [#3434] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily. - db.parse_errors(file_id) + db.parse_errors(editioned_file_id_wrapper) .as_deref() .into_iter() .flatten() @@ -333,7 +339,7 @@ pub fn syntax_diagnostics( Diagnostic::new( DiagnosticCode::SyntaxError, format!("Syntax Error: {err}"), - FileRange { file_id: file_id.into(), range: err.range() }, + FileRange { file_id, range: err.range() }, ) }) .collect() @@ -349,26 +355,31 @@ pub fn semantic_diagnostics( ) -> Vec { let _p = tracing::info_span!("semantic_diagnostics").entered(); let sema = Semantics::new(db); - let file_id = sema + let editioned_file_id = sema .attach_first_edition(file_id) .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); + + let (file_id, edition) = editioned_file_id.unpack(); + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(db.as_dyn_database(), editioned_file_id); + let mut res = Vec::new(); - let parse = sema.parse(file_id); + let parse = sema.parse(editioned_file_id_wrapper); // FIXME: This iterates the entire file which is a rather expensive operation. // We should implement these differently in some form? // Salsa caching + incremental re-parse would be better here for node in parse.syntax().descendants() { - handlers::useless_braces::useless_braces(&mut res, file_id, &node); - handlers::field_shorthand::field_shorthand(&mut res, file_id, &node); + handlers::useless_braces::useless_braces(&mut res, editioned_file_id, &node); + handlers::field_shorthand::field_shorthand(&mut res, editioned_file_id, &node); handlers::json_is_not_rust::json_in_items( &sema, &mut res, - file_id, + editioned_file_id, &node, config, - file_id.edition(), + edition, ); } @@ -382,25 +393,19 @@ pub fn semantic_diagnostics( (*db.crate_graph().crates_in_topological_order().last().unwrap()).into() }); let display_target = krate.to_display_target(db); - let ctx = DiagnosticsContext { - config, - sema, - resolve, - edition: file_id.edition(), - is_nightly, - display_target, - }; + let ctx = DiagnosticsContext { config, sema, resolve, edition, is_nightly, display_target }; let mut diags = Vec::new(); match module { // A bunch of parse errors in a file indicate some bigger structural parse changes in the // file, so we skip semantic diagnostics so we can show these faster. Some(m) => { - if db.parse_errors(file_id).as_deref().is_none_or(|es| es.len() < 16) { + if db.parse_errors(editioned_file_id_wrapper).as_deref().is_none_or(|es| es.len() < 16) + { m.diagnostics(db, &mut diags, config.style_lints); } } - None => handlers::unlinked_file::unlinked_file(&ctx, &mut res, file_id.file_id()), + None => handlers::unlinked_file::unlinked_file(&ctx, &mut res, editioned_file_id.file_id()), } for diag in diags { @@ -517,7 +522,7 @@ pub fn semantic_diagnostics( &mut FxHashMap::default(), &mut lints, &mut Vec::new(), - file_id.edition(), + editioned_file_id.edition(), ); res.retain(|d| d.severity != Severity::Allow); @@ -559,7 +564,7 @@ fn handle_diag_from_macros( let span_map = sema.db.expansion_span_map(macro_file); let mut spans = span_map.spans_for_range(node.text_range()); if spans.any(|span| { - sema.db.lookup_intern_syntax_context(span.ctx).outer_expn.is_some_and(|expansion| { + span.ctx.outer_expn(sema.db).is_some_and(|expansion| { let macro_call = sema.db.lookup_intern_macro_call(expansion.as_macro_file().macro_call_id); // We don't want to show diagnostics for non-local macros at all, but proc macros authors diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs index fc2a7db7174e9..7b33bbdaa22c4 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs @@ -85,7 +85,7 @@ fn check_nth_fix_with_config( let actual = { let source_change = fix.source_change.as_ref().unwrap(); let file_id = *source_change.source_file_edits.keys().next().unwrap(); - let mut actual = db.file_text(file_id).to_string(); + let mut actual = db.file_text(file_id).text(&db).to_string(); for (edit, snippet_edit) in source_change.source_file_edits.values() { edit.apply(&mut actual); @@ -142,7 +142,7 @@ pub(crate) fn check_has_fix( let actual = { let source_change = fix.source_change.as_ref().unwrap(); let file_id = *source_change.source_file_edits.keys().next().unwrap(); - let mut actual = db.file_text(file_id).to_string(); + let mut actual = db.file_text(file_id).text(&db).to_string(); for (edit, snippet_edit) in source_change.source_file_edits.values() { edit.apply(&mut actual); @@ -190,7 +190,7 @@ pub(crate) fn check_has_single_fix( let actual = { let source_change = fix.source_change.as_ref().unwrap(); let file_id = *source_change.source_file_edits.keys().next().unwrap(); - let mut actual = db.file_text(file_id).to_string(); + let mut actual = db.file_text(file_id).text(&db).to_string(); for (edit, snippet_edit) in source_change.source_file_edits.values() { edit.apply(&mut actual); @@ -276,7 +276,7 @@ pub(crate) fn check_diagnostics_with_config( let line_index = db.line_index(file_id); let mut actual = annotations.remove(&file_id).unwrap_or_default(); - let expected = extract_annotations(&db.file_text(file_id)); + let expected = extract_annotations(&db.file_text(file_id).text(&db)); actual.sort_by_key(|(range, _)| range.start()); // FIXME: We should panic on duplicates instead, but includes currently cause us to report // diagnostics twice for the calling module when both files are queried. @@ -289,7 +289,7 @@ pub(crate) fn check_diagnostics_with_config( for (e, _) in &actual { eprintln!( "Code in range {e:?} = {}", - &db.file_text(file_id)[usize::from(e.start())..usize::from(e.end())] + &db.file_text(file_id).text(&db)[usize::from(e.start())..usize::from(e.end())] ) } } diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/from_comment.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/from_comment.rs index a14e69030e325..f6fe705a98741 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/from_comment.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/from_comment.rs @@ -1,7 +1,10 @@ //! This module allows building an SSR MatchFinder by parsing the SSR rule //! from a comment. -use ide_db::{base_db::SourceDatabase, EditionedFileId, FilePosition, FileRange, RootDatabase}; +use ide_db::{ + base_db::{salsa::AsDynDatabase, RootQueryDb}, + EditionedFileId, FilePosition, FileRange, RootDatabase, +}; use syntax::{ ast::{self, AstNode, AstToken}, TextRange, @@ -17,7 +20,11 @@ pub fn ssr_from_comment( frange: FileRange, ) -> Option<(MatchFinder<'_>, TextRange)> { let comment = { - let file = db.parse(EditionedFileId::current_edition(frange.file_id)); + let editioned_file_id = EditionedFileId::current_edition(frange.file_id); + let file_id = + ide_db::base_db::EditionedFileId::new(db.as_dyn_database(), editioned_file_id); + + let file = db.parse(file_id); file.tree().syntax().token_at_offset(frange.range.start()).find_map(ast::Comment::cast) }?; let comment_text_without_prefix = comment.text().strip_prefix(comment.prefix()).unwrap(); diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs index 889258c94c535..971547ca1f8e6 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs @@ -80,8 +80,12 @@ pub use crate::{errors::SsrError, from_comment::ssr_from_comment, matching::Matc use crate::{errors::bail, matching::MatchFailureReason}; use hir::{FileRange, Semantics}; +use ide_db::symbol_index::SymbolsDatabase; use ide_db::text_edit::TextEdit; -use ide_db::{base_db::SourceDatabase, EditionedFileId, FileId, FxHashMap, RootDatabase}; +use ide_db::{ + base_db::{salsa::AsDynDatabase, SourceDatabase}, + EditionedFileId, FileId, FxHashMap, RootDatabase, +}; use resolving::ResolvedRule; use syntax::{ast, AstNode, SyntaxNode, TextRange}; @@ -137,10 +141,11 @@ impl<'db> MatchFinder<'db> { /// Constructs an instance using the start of the first file in `db` as the lookup context. pub fn at_first_file(db: &'db ide_db::RootDatabase) -> Result, SsrError> { - use ide_db::base_db::SourceRootDatabase; - use ide_db::symbol_index::SymbolsDatabase; - if let Some(first_file_id) = - db.local_roots().iter().next().and_then(|root| db.source_root(*root).iter().next()) + if let Some(first_file_id) = db + .local_roots() + .iter() + .next() + .and_then(|root| db.source_root(*root).source_root(db).iter().next()) { MatchFinder::in_context( db, @@ -184,7 +189,7 @@ impl<'db> MatchFinder<'db> { replacing::matches_to_edit( self.sema.db, &matches, - &self.sema.db.file_text(file_id), + &self.sema.db.file_text(file_id).text(self.sema.db), &self.rules, ), ) @@ -223,9 +228,12 @@ impl<'db> MatchFinder<'db> { file_id: EditionedFileId, snippet: &str, ) -> Vec { - let file = self.sema.parse(file_id); + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(self.sema.db.as_dyn_database(), file_id); + + let file = self.sema.parse(editioned_file_id_wrapper); let mut res = Vec::new(); - let file_text = self.sema.db.file_text(file_id.into()); + let file_text = self.sema.db.file_text(file_id.into()).text(self.sema.db); let mut remaining_text = &*file_text; let mut base = 0; let len = snippet.len() as u32; diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs index e219ba4bf6398..d32ba06f1eb4f 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs @@ -7,7 +7,7 @@ use crate::{ SsrMatches, }; use hir::{FileRange, ImportPathConfig, Semantics}; -use ide_db::{base_db::SourceDatabase, FxHashMap}; +use ide_db::{base_db::RootQueryDb, FxHashMap}; use std::{cell::Cell, iter::Peekable}; use syntax::{ ast::{self, AstNode, AstToken, HasGenericArgs}, diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs index 270ee0b3ec967..8c98d8de9183e 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs @@ -1,7 +1,7 @@ //! This module is responsible for resolving paths within rules. use hir::AsAssocItem; -use ide_db::FxHashMap; +use ide_db::{base_db::salsa::AsDynDatabase, FxHashMap}; use parsing::Placeholder; use syntax::{ ast::{self, HasGenericArgs}, @@ -198,7 +198,12 @@ impl<'db> ResolutionScope<'db> { resolve_context: hir::FilePosition, ) -> Option> { use syntax::ast::AstNode; - let file = sema.parse(resolve_context.file_id); + let editioned_file_id_wrapper = ide_db::base_db::EditionedFileId::new( + sema.db.as_dyn_database(), + resolve_context.file_id, + ); + + let file = sema.parse(editioned_file_id_wrapper); // Find a node at the requested position, falling back to the whole file. let node = file .syntax() diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs index b1cade39266a0..b094712e1bd56 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs @@ -7,6 +7,7 @@ use crate::{ }; use hir::FileRange; use ide_db::{ + base_db::salsa::AsDynDatabase, defs::Definition, search::{SearchScope, UsageSearchResult}, EditionedFileId, FileId, FxHashSet, @@ -74,7 +75,12 @@ impl MatchFinder<'_> { resolved_path: &ResolvedPath, file_range: FileRange, ) -> Vec { - let file = self.sema.parse(file_range.file_id); + let editioned_file_id_wrapper = ide_db::base_db::EditionedFileId::new( + self.sema.db.as_dyn_database(), + file_range.file_id, + ); + + let file = self.sema.parse(editioned_file_id_wrapper); let depth = resolved_path.depth as usize; let offset = file_range.range.start(); @@ -156,10 +162,10 @@ impl MatchFinder<'_> { fn search_files_do(&self, mut callback: impl FnMut(FileId)) { if self.restrict_ranges.is_empty() { // Unrestricted search. - use ide_db::base_db::SourceRootDatabase; + use ide_db::base_db::SourceDatabase; use ide_db::symbol_index::SymbolsDatabase; for &root in self.sema.db.local_roots().iter() { - let sr = self.sema.db.source_root(root); + let sr = self.sema.db.source_root(root).source_root(self.sema.db); for file_id in sr.iter() { callback(file_id); } diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/tests.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/tests.rs index d783e1952526c..0b510c9c6b244 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/tests.rs @@ -1,7 +1,7 @@ use expect_test::{expect, Expect}; use hir::{FilePosition, FileRange}; use ide_db::{ - base_db::{ra_salsa::Durability, SourceDatabase}, + base_db::{salsa::Durability, SourceDatabase}, EditionedFileId, FxHashSet, }; use test_utils::RangeOrOffset; @@ -114,7 +114,7 @@ fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) { } // Note, db.file_text is not necessarily the same as `input`, since fixture parsing alters // stuff. - let mut actual = db.file_text(position.file_id.into()).to_string(); + let mut actual = db.file_text(position.file_id.into()).text(&db).to_string(); edits[&position.file_id.into()].apply(&mut actual); expected.assert_eq(&actual); } diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index 8d2ca33bf254d..0acb129e93986 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -12,7 +12,7 @@ use url::Url; use hir::{db::HirDatabase, sym, Adt, AsAssocItem, AssocItem, AssocItemContainer, HasAttrs}; use ide_db::{ - base_db::{CrateOrigin, LangCrateOrigin, ReleaseChannel, SourceDatabase}, + base_db::{CrateOrigin, LangCrateOrigin, ReleaseChannel, RootQueryDb}, defs::{Definition, NameClass, NameRefClass}, documentation::{docs_with_rangemap, Documentation, HasDocs}, helpers::pick_best_token, diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs index b09e3a3c8047c..d70a3f9706cfd 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs @@ -43,7 +43,7 @@ fn check_external_docs( fn check_rewrite(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); - let sema = &Semantics::new(&*analysis.db); + let sema = &Semantics::new(&analysis.db); let (cursor_def, docs) = def_under_cursor(sema, &position); let res = rewrite_links(sema.db, docs.as_str(), cursor_def); expect.assert_eq(&res) @@ -54,7 +54,7 @@ fn check_doc_links(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position, mut expected) = fixture::annotations(ra_fixture); expected.sort_by_key(key_fn); - let sema = &Semantics::new(&*analysis.db); + let sema = &Semantics::new(&analysis.db); let (cursor_def, docs) = def_under_cursor(sema, &position); let defs = extract_definitions_from_docs(&docs); let actual: Vec<_> = defs diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index ad4308e06a14b..2347e2e8a36d8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -234,7 +234,6 @@ fn _format( file_id: FileId, expansion: &str, ) -> Option { - use ide_db::base_db::{FileLoader, SourceDatabase}; // hack until we get hygiene working (same character amount to preserve formatting as much as possible) const DOLLAR_CRATE_REPLACE: &str = "__r_a_"; const BUILTIN_REPLACE: &str = "builtin__POUND"; @@ -248,8 +247,9 @@ fn _format( }; let expansion = format!("{prefix}{expansion}{suffix}"); - let &crate_id = db.relevant_crates(file_id).iter().next()?; - let edition = db.crate_graph()[crate_id].edition; + let upcast_db = ide_db::base_db::Upcast::::upcast(db); + let &crate_id = upcast_db.relevant_crates(file_id).iter().next()?; + let edition = upcast_db.crate_graph()[crate_id].edition; #[allow(clippy::disallowed_methods)] let mut cmd = std::process::Command::new(toolchain::Tool::Rustfmt.path()); diff --git a/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs b/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs index 5ed2144430741..0e5bb89b6b717 100644 --- a/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs +++ b/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs @@ -1,5 +1,5 @@ use ide_db::{ - base_db::{CrateOrigin, SourceDatabase}, + base_db::{CrateOrigin, RootQueryDb}, FileId, FxIndexSet, RootDatabase, }; diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index 60a904233a9a5..84138986f66ba 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -10,7 +10,7 @@ use hir::{ ModuleDef, Semantics, }; use ide_db::{ - base_db::{AnchoredPath, FileLoader, SourceDatabase}, + base_db::{AnchoredPath, RootQueryDb, SourceDatabase, Upcast}, defs::{Definition, IdentClass}, famous_defs::FamousDefs, helpers::pick_best_token, @@ -216,8 +216,9 @@ fn try_lookup_include_path( } let path = token.value().ok()?; - let file_id = sema.db.resolve_path(AnchoredPath { anchor: file_id, path: &path })?; - let size = sema.db.file_text(file_id).len().try_into().ok()?; + let file_id = Upcast::::upcast(sema.db) + .resolve_path(AnchoredPath { anchor: file_id, path: &path })?; + let size = sema.db.file_text(file_id).text(sema.db).len().try_into().ok()?; Some(NavigationTarget { file_id, full_range: TextRange::new(0.into(), size), diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs index 6463206596af5..0ef7eb503f64a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs +++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs @@ -2,6 +2,7 @@ use std::iter; use hir::{db, FilePosition, FileRange, HirFileId, InFile, Semantics}; use ide_db::{ + base_db::salsa::AsDynDatabase, defs::{Definition, IdentClass}, helpers::pick_best_token, search::{FileReference, ReferenceCategory, SearchScope}, @@ -60,7 +61,10 @@ pub(crate) fn highlight_related( let file_id = sema .attach_first_edition(file_id) .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); - let syntax = sema.parse(file_id).syntax().clone(); + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(sema.db.as_dyn_database(), file_id); + + let syntax = sema.parse(editioned_file_id_wrapper).syntax().clone(); let token = pick_best_token(syntax.token_at_offset(offset), |kind| match kind { T![?] => 4, // prefer `?` when the cursor is sandwiched like in `await$0?` diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index 31ef89a07cde1..5d888ceb5edb9 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -8,7 +8,7 @@ use hir::{ MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef, }; use ide_db::{ - base_db::SourceDatabase, + base_db::RootQueryDb, defs::Definition, documentation::HasDocs, famous_defs::FamousDefs, diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 6b470d921f7a7..736d355ef2276 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -47,7 +47,7 @@ fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { .unwrap(); let content = analysis.db.file_text(position.file_id); - let hovered_element = &content[hover.range]; + let hovered_element = &content.text(&analysis.db)[hover.range]; let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup); expect.assert_eq(&actual) @@ -72,7 +72,7 @@ fn check_hover_fields_limit( .unwrap() .unwrap(); - let content = analysis.db.file_text(position.file_id); + let content = analysis.db.file_text(position.file_id).text(&analysis.db); let hovered_element = &content[hover.range]; let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup); @@ -98,7 +98,7 @@ fn check_hover_enum_variants_limit( .unwrap() .unwrap(); - let content = analysis.db.file_text(position.file_id); + let content = analysis.db.file_text(position.file_id).text(&analysis.db); let hovered_element = &content[hover.range]; let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup); @@ -124,7 +124,7 @@ fn check_assoc_count( .unwrap() .unwrap(); - let content = analysis.db.file_text(position.file_id); + let content = analysis.db.file_text(position.file_id).text(&analysis.db); let hovered_element = &content[hover.range]; let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup); @@ -141,7 +141,7 @@ fn check_hover_no_links(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: .unwrap() .unwrap(); - let content = analysis.db.file_text(position.file_id); + let content = analysis.db.file_text(position.file_id).text(&analysis.db); let hovered_element = &content[hover.range]; let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup); @@ -158,7 +158,7 @@ fn check_hover_no_memory_layout(#[rust_analyzer::rust_fixture] ra_fixture: &str, .unwrap() .unwrap(); - let content = analysis.db.file_text(position.file_id); + let content = analysis.db.file_text(position.file_id).text(&analysis.db); let hovered_element = &content[hover.range]; let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup); @@ -179,7 +179,7 @@ fn check_hover_no_markdown(#[rust_analyzer::rust_fixture] ra_fixture: &str, expe .unwrap() .unwrap(); - let content = analysis.db.file_text(position.file_id); + let content = analysis.db.file_text(position.file_id).text(&analysis.db); let hovered_element = &content[hover.range]; let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup); diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index 6babdff52a2be..3a709e71fbe70 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -8,7 +8,7 @@ use hir::{ sym, ClosureStyle, DisplayTarget, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef, ModuleDefId, Semantics, }; -use ide_db::{famous_defs::FamousDefs, FileRange, RootDatabase}; +use ide_db::{base_db::salsa::AsDynDatabase, famous_defs::FamousDefs, FileRange, RootDatabase}; use ide_db::{text_edit::TextEdit, FxHashSet}; use itertools::Itertools; use smallvec::{smallvec, SmallVec}; @@ -86,7 +86,9 @@ pub(crate) fn inlay_hints( let file_id = sema .attach_first_edition(file_id) .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); - let file = sema.parse(file_id); + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(sema.db.as_dyn_database(), file_id); + let file = sema.parse(editioned_file_id_wrapper); let file = file.syntax(); let mut acc = Vec::new(); @@ -137,7 +139,9 @@ pub(crate) fn inlay_hints_resolve( let file_id = sema .attach_first_edition(file_id) .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); - let file = sema.parse(file_id); + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(sema.db.as_dyn_database(), file_id); + let file = sema.parse(editioned_file_id_wrapper); let file = file.syntax(); let scope = sema.scope(file)?; diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs index 4379153acaa17..592c8603964da 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs @@ -868,15 +868,15 @@ fn main() { //- minicore: fn fn main() { let x = || 2; - //^ {closure#0} + //^ {closure#26624} let y = |t: i32| x() + t; - //^ {closure#1} + //^ {closure#26625} let mut t = 5; //^ i32 let z = |k: i32| { t += k; }; - //^ {closure#2} + //^ {closure#26626} let p = (y, z); - //^ ({closure#1}, {closure#2}) + //^ ({closure#26625}, {closure#26626}) } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide/src/interpret.rs b/src/tools/rust-analyzer/crates/ide/src/interpret.rs index 74dad488b4d30..0499d8a447fbf 100644 --- a/src/tools/rust-analyzer/crates/ide/src/interpret.rs +++ b/src/tools/rust-analyzer/crates/ide/src/interpret.rs @@ -1,5 +1,5 @@ use hir::{ConstEvalError, DefWithBody, DisplayTarget, Semantics}; -use ide_db::{base_db::SourceRootDatabase, FilePosition, LineIndexDatabase, RootDatabase}; +use ide_db::{base_db::SourceDatabase, FilePosition, LineIndexDatabase, RootDatabase}; use std::time::{Duration, Instant}; use stdx::format_to; use syntax::{algo::ancestors_at_offset, ast, AstNode, TextRange}; @@ -35,10 +35,10 @@ fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<(Dura _ => return None, }; let span_formatter = |file_id, text_range: TextRange| { - let path = &db - .source_root(db.file_source_root(file_id)) - .path_for_file(&file_id) - .map(|x| x.to_string()); + let source_root = db.file_source_root(file_id).source_root_id(db); + let source_root = db.source_root(source_root).source_root(db); + + let path = source_root.path_for_file(&file_id).map(|x| x.to_string()); let path = path.as_deref().unwrap_or(""); match db.line_index(file_id).try_line_col(text_range.start()) { Some(line_col) => format!("file://{path}:{}:{}", line_col.line + 1, line_col.col), @@ -64,10 +64,9 @@ pub(crate) fn render_const_eval_error( display_target: DisplayTarget, ) -> String { let span_formatter = |file_id, text_range: TextRange| { - let path = &db - .source_root(db.file_source_root(file_id)) - .path_for_file(&file_id) - .map(|x| x.to_string()); + let source_root = db.file_source_root(file_id).source_root_id(db); + let source_root = db.source_root(source_root).source_root(db); + let path = source_root.path_for_file(&file_id).map(|x| x.to_string()); let path = path.as_deref().unwrap_or(""); match db.line_index(file_id).try_line_col(text_range.start()) { Some(line_col) => format!("file://{path}:{}:{}", line_col.line + 1, line_col.col), diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index 8ac1a96cc6524..dcb170f3f7b63 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -64,9 +64,9 @@ use fetch_crates::CrateInfo; use hir::{sym, ChangeWithProcMacros}; use ide_db::{ base_db::{ - ra_salsa::{self, ParallelDatabase}, - CrateOrigin, CrateWorkspaceData, Env, FileLoader, FileSet, SourceDatabase, - SourceRootDatabase, VfsPath, + salsa::{AsDynDatabase, Cancelled}, + CrateOrigin, CrateWorkspaceData, Env, FileSet, RootQueryDb, SourceDatabase, Upcast, + VfsPath, }, prime_caches, symbol_index, FxHashMap, FxIndexSet, LineIndexDatabase, }; @@ -125,7 +125,7 @@ pub use ide_completion::{ }; pub use ide_db::text_edit::{Indel, TextEdit}; pub use ide_db::{ - base_db::{Cancelled, CrateGraph, CrateId, FileChange, SourceRoot, SourceRootId}, + base_db::{CrateGraph, CrateId, FileChange, SourceRoot, SourceRootId}, documentation::Documentation, label::Label, line_index::{LineCol, LineIndex}, @@ -217,7 +217,7 @@ impl Default for AnalysisHost { /// `Analysis` are canceled (most method return `Err(Canceled)`). #[derive(Debug)] pub struct Analysis { - db: ra_salsa::Snapshot, + db: RootDatabase, } // As a general design guideline, `Analysis` API are intended to be independent @@ -276,12 +276,12 @@ impl Analysis { } pub fn source_root_id(&self, file_id: FileId) -> Cancellable { - self.with_db(|db| db.file_source_root(file_id)) + self.with_db(|db| db.file_source_root(file_id).source_root_id(db)) } pub fn is_local_source_root(&self, source_root_id: SourceRootId) -> Cancellable { self.with_db(|db| { - let sr = db.source_root(source_root_id); + let sr = db.source_root(source_root_id).source_root(db); !sr.is_library }) } @@ -295,18 +295,28 @@ impl Analysis { /// Gets the text of the source file. pub fn file_text(&self, file_id: FileId) -> Cancellable> { - self.with_db(|db| SourceDatabase::file_text(db, file_id)) + self.with_db(|db| SourceDatabase::file_text(db, file_id).text(db)) } /// Gets the syntax tree of the file. pub fn parse(&self, file_id: FileId) -> Cancellable { // FIXME edition - self.with_db(|db| db.parse(EditionedFileId::current_edition(file_id)).tree()) + self.with_db(|db| { + let editioned_file_id_wrapper = ide_db::base_db::EditionedFileId::new( + self.db.as_dyn_database(), + EditionedFileId::current_edition(file_id), + ); + + db.parse(editioned_file_id_wrapper).tree() + }) } /// Returns true if this file belongs to an immutable library. pub fn is_library_file(&self, file_id: FileId) -> Cancellable { - self.with_db(|db| db.source_root(db.file_source_root(file_id)).is_library) + self.with_db(|db| { + let source_root = db.file_source_root(file_id).source_root_id(db); + db.source_root(source_root).source_root(db).is_library + }) } /// Gets the file's `LineIndex`: data structure to convert between absolute @@ -324,7 +334,11 @@ impl Analysis { /// supported). pub fn matching_brace(&self, position: FilePosition) -> Cancellable> { self.with_db(|db| { - let parse = db.parse(EditionedFileId::current_edition(position.file_id)); + let file_id = ide_db::base_db::EditionedFileId::new( + self.db.as_dyn_database(), + EditionedFileId::current_edition(position.file_id), + ); + let parse = db.parse(file_id); let file = parse.tree(); matching_brace::matching_brace(&file, position.offset) }) @@ -383,7 +397,11 @@ impl Analysis { /// stuff like trailing commas. pub fn join_lines(&self, config: &JoinLinesConfig, frange: FileRange) -> Cancellable { self.with_db(|db| { - let parse = db.parse(EditionedFileId::current_edition(frange.file_id)); + let editioned_file_id_wrapper = ide_db::base_db::EditionedFileId::new( + self.db.as_dyn_database(), + EditionedFileId::current_edition(frange.file_id), + ); + let parse = db.parse(editioned_file_id_wrapper); join_lines::join_lines(config, &parse.tree(), frange.range) }) } @@ -419,9 +437,12 @@ impl Analysis { pub fn file_structure(&self, file_id: FileId) -> Cancellable> { // FIXME: Edition self.with_db(|db| { - file_structure::file_structure( - &db.parse(EditionedFileId::current_edition(file_id)).tree(), - ) + let editioned_file_id_wrapper = ide_db::base_db::EditionedFileId::new( + self.db.as_dyn_database(), + EditionedFileId::current_edition(file_id), + ); + + file_structure::file_structure(&db.parse(editioned_file_id_wrapper).tree()) }) } @@ -450,9 +471,12 @@ impl Analysis { /// Returns the set of folding ranges. pub fn folding_ranges(&self, file_id: FileId) -> Cancellable> { self.with_db(|db| { - folding_ranges::folding_ranges( - &db.parse(EditionedFileId::current_edition(file_id)).tree(), - ) + let editioned_file_id_wrapper = ide_db::base_db::EditionedFileId::new( + self.db.as_dyn_database(), + EditionedFileId::current_edition(file_id), + ); + + folding_ranges::folding_ranges(&db.parse(editioned_file_id_wrapper).tree()) }) } @@ -589,7 +613,10 @@ impl Analysis { /// Returns crates that this file *might* belong to. pub fn relevant_crates_for(&self, file_id: FileId) -> Cancellable> { - self.with_db(|db| db.relevant_crates(file_id).iter().copied().collect()) + self.with_db(|db| { + let db = Upcast::::upcast(db); + db.relevant_crates(file_id).iter().copied().collect() + }) } /// Returns the edition of the given crate. @@ -828,7 +855,8 @@ impl Analysis { where F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe, { - Cancelled::catch(|| f(&self.db)) + let snap = self.db.snapshot(); + Cancelled::catch(|| f(&snap)) } } diff --git a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs index 6d82f9b0634b4..90cccca5e80f4 100644 --- a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs +++ b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs @@ -1,6 +1,6 @@ use hir::{db::DefDatabase, Semantics}; use ide_db::{ - base_db::{CrateId, FileLoader}, + base_db::{CrateId, RootQueryDb, Upcast}, FileId, FilePosition, RootDatabase, }; use itertools::Itertools; @@ -54,7 +54,9 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec Vec { - db.relevant_crates(file_id) + let root_db = Upcast::::upcast(db); + root_db + .relevant_crates(file_id) .iter() .copied() .filter(|&crate_id| db.crate_def_map(crate_id).modules_for_file(file_id).next().is_some()) diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs index 08e25dde60631..57d297700ad37 100644 --- a/src/tools/rust-analyzer/crates/ide/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs @@ -6,6 +6,7 @@ use hir::{AsAssocItem, HirFileIdExt, InFile, Semantics}; use ide_db::{ + base_db::salsa::AsDynDatabase, defs::{Definition, NameClass, NameRefClass}, rename::{bail, format_err, source_edit_from_references, IdentifierKind}, source_change::SourceChangeBuilder, @@ -85,7 +86,9 @@ pub(crate) fn rename( let file_id = sema .attach_first_edition(position.file_id) .ok_or_else(|| format_err!("No references found at position"))?; - let source_file = sema.parse(file_id); + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(db.as_dyn_database(), file_id); + let source_file = sema.parse(editioned_file_id_wrapper); let syntax = source_file.syntax(); let defs = find_definitions(&sema, syntax, position)?; diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index b8deed01fb7f2..33eef6d75c21a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -9,7 +9,7 @@ use hir::{ }; use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn}; use ide_db::{ - base_db::SourceDatabase, + base_db::RootQueryDb, defs::Definition, documentation::docs_from_attrs, helpers::visit_file_defs, diff --git a/src/tools/rust-analyzer/crates/ide/src/ssr.rs b/src/tools/rust-analyzer/crates/ide/src/ssr.rs index 5812a92b3893f..81b5988126519 100644 --- a/src/tools/rust-analyzer/crates/ide/src/ssr.rs +++ b/src/tools/rust-analyzer/crates/ide/src/ssr.rs @@ -59,7 +59,7 @@ mod tests { use expect_test::expect; use ide_assists::{Assist, AssistResolveStrategy}; use ide_db::{ - base_db::ra_salsa::Durability, symbol_index::SymbolsDatabase, FileRange, FxHashSet, + base_db::salsa::Durability, symbol_index::SymbolsDatabase, FileRange, FxHashSet, RootDatabase, }; use test_fixture::WithFixture; diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs index 332aecf1e3cc5..ceea34b721373 100644 --- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs +++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs @@ -3,7 +3,7 @@ use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics}; use ide_db::{ - base_db::{SourceDatabase, SourceRootDatabase, VfsPath}, + base_db::{RootQueryDb, SourceDatabase, VfsPath}, defs::Definition, documentation::Documentation, famous_defs::FamousDefs, @@ -267,11 +267,11 @@ impl StaticIndex<'_> { analysis: &'a Analysis, vendored_libs_config: VendoredLibrariesConfig<'_>, ) -> StaticIndex<'a> { - let db = &*analysis.db; + let db = &analysis.db; let work = all_modules(db).into_iter().filter(|module| { let file_id = module.definition_source_file_id(db).original_file(db); - let source_root = db.file_source_root(file_id.into()); - let source_root = db.source_root(source_root); + let source_root = db.file_source_root(file_id.into()).source_root_id(db); + let source_root = db.source_root(source_root).source_root(db); let is_vendored = match vendored_libs_config { VendoredLibrariesConfig::Included { workspace_root } => source_root .path_for_file(&file_id.into()) diff --git a/src/tools/rust-analyzer/crates/ide/src/status.rs b/src/tools/rust-analyzer/crates/ide/src/status.rs index a44be67668ce3..47ac4ebf20e3b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/status.rs +++ b/src/tools/rust-analyzer/crates/ide/src/status.rs @@ -1,29 +1,8 @@ -use std::{fmt, marker::PhantomData}; - -use hir::{ - db::{AstIdMapQuery, AttrsQuery, BlockDefMapQuery, ParseMacroExpansionQuery}, - Attr, Attrs, ExpandResult, MacroFileId, Module, -}; -use ide_db::{ - base_db::{ - ra_salsa::{ - debug::{DebugQueryTable, TableEntry}, - Query, QueryTable, - }, - CompressedFileTextQuery, CrateData, ParseQuery, SourceDatabase, SourceRootId, - }, - symbol_index::ModuleSymbolsQuery, -}; -use ide_db::{ - symbol_index::{LibrarySymbolsQuery, SymbolIndex}, - RootDatabase, -}; +use ide_db::base_db::{CrateData, RootQueryDb, Upcast}; +use ide_db::RootDatabase; use itertools::Itertools; -use profile::{memory_usage, Bytes}; -use span::{EditionedFileId, FileId}; +use span::FileId; use stdx::format_to; -use syntax::{ast, Parse, SyntaxNode}; -use triomphe::Arc; // Feature: Status // @@ -37,17 +16,17 @@ use triomphe::Arc; pub(crate) fn status(db: &RootDatabase, file_id: Option) -> String { let mut buf = String::new(); - format_to!(buf, "{}\n", collect_query(CompressedFileTextQuery.in_db(db))); - format_to!(buf, "{}\n", collect_query(ParseQuery.in_db(db))); - format_to!(buf, "{}\n", collect_query(ParseMacroExpansionQuery.in_db(db))); - format_to!(buf, "{}\n", collect_query(LibrarySymbolsQuery.in_db(db))); - format_to!(buf, "{}\n", collect_query(ModuleSymbolsQuery.in_db(db))); - format_to!(buf, "{} in total\n", memory_usage()); + // format_to!(buf, "{}\n", collect_query(CompressedFileTextQuery.in_db(db))); + // format_to!(buf, "{}\n", collect_query(ParseQuery.in_db(db))); + // format_to!(buf, "{}\n", collect_query(ParseMacroExpansionQuery.in_db(db))); + // format_to!(buf, "{}\n", collect_query(LibrarySymbolsQuery.in_db(db))); + // format_to!(buf, "{}\n", collect_query(ModuleSymbolsQuery.in_db(db))); + // format_to!(buf, "{} in total\n", memory_usage()); - format_to!(buf, "\nDebug info:\n"); - format_to!(buf, "{}\n", collect_query(AttrsQuery.in_db(db))); - format_to!(buf, "{} ast id maps\n", collect_query_count(AstIdMapQuery.in_db(db))); - format_to!(buf, "{} block def maps\n", collect_query_count(BlockDefMapQuery.in_db(db))); + // format_to!(buf, "\nDebug info:\n"); + // format_to!(buf, "{}\n", collect_query(AttrsQuery.in_db(db))); + // format_to!(buf, "{} ast id maps\n", collect_query_count(AstIdMapQuery.in_db(db))); + // format_to!(buf, "{} block def maps\n", collect_query_count(BlockDefMapQuery.in_db(db))); if let Some(file_id) = file_id { format_to!(buf, "\nCrates for file {}:\n", file_id.index()); @@ -55,7 +34,8 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option) -> String { if crates.is_empty() { format_to!(buf, "Does not belong to any crate"); } - let crate_graph = db.crate_graph(); + + let crate_graph = Upcast::::upcast(db).crate_graph(); for crate_id in crates { let CrateData { root_file_id, @@ -97,190 +77,3 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option) -> String { buf.trim().to_owned() } - -fn collect_query<'q, Q>(table: QueryTable<'q, Q>) -> ::Collector -where - QueryTable<'q, Q>: DebugQueryTable, - Q: QueryCollect, - ::Storage: 'q, - ::Collector: StatCollect< - as DebugQueryTable>::Key, - as DebugQueryTable>::Value, - >, -{ - struct StatCollectorWrapper(C); - impl, K, V> FromIterator> for StatCollectorWrapper { - fn from_iter(iter: T) -> StatCollectorWrapper - where - T: IntoIterator>, - { - let mut res = C::default(); - for entry in iter { - res.collect_entry(entry.key, entry.value); - } - StatCollectorWrapper(res) - } - } - table.entries::::Collector>>().0 -} - -fn collect_query_count<'q, Q>(table: QueryTable<'q, Q>) -> usize -where - QueryTable<'q, Q>: DebugQueryTable, - Q: Query, - ::Storage: 'q, -{ - struct EntryCounter(usize); - impl FromIterator> for EntryCounter { - fn from_iter(iter: T) -> EntryCounter - where - T: IntoIterator>, - { - EntryCounter(iter.into_iter().count()) - } - } - table.entries::().0 -} - -trait QueryCollect: Query { - type Collector; -} - -impl QueryCollect for LibrarySymbolsQuery { - type Collector = SymbolsStats; -} - -impl QueryCollect for ParseQuery { - type Collector = SyntaxTreeStats; -} - -impl QueryCollect for ParseMacroExpansionQuery { - type Collector = SyntaxTreeStats; -} - -impl QueryCollect for CompressedFileTextQuery { - type Collector = FilesStats; -} - -impl QueryCollect for ModuleSymbolsQuery { - type Collector = SymbolsStats; -} - -impl QueryCollect for AttrsQuery { - type Collector = AttrsStats; -} - -trait StatCollect: Default { - fn collect_entry(&mut self, key: K, value: Option); -} - -#[derive(Default)] -struct FilesStats { - total: usize, - size: Bytes, -} - -impl fmt::Display for FilesStats { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "{} of files", self.size) - } -} - -impl StatCollect> for FilesStats { - fn collect_entry(&mut self, _: FileId, value: Option>) { - self.total += 1; - self.size += value.unwrap().len(); - } -} - -#[derive(Default)] -pub(crate) struct SyntaxTreeStats { - total: usize, - pub(crate) retained: usize, -} - -impl fmt::Display for SyntaxTreeStats { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - fmt, - "{} trees, {} preserved{}", - self.total, - self.retained, - if MACROS { " (macros)" } else { "" } - ) - } -} - -impl StatCollect> for SyntaxTreeStats { - fn collect_entry(&mut self, _: EditionedFileId, value: Option>) { - self.total += 1; - self.retained += value.is_some() as usize; - } -} - -impl StatCollect, M)>> for SyntaxTreeStats { - fn collect_entry( - &mut self, - _: MacroFileId, - value: Option, M)>>, - ) { - self.total += 1; - self.retained += value.is_some() as usize; - } -} - -struct SymbolsStats { - total: usize, - size: Bytes, - phantom: PhantomData, -} - -impl Default for SymbolsStats { - fn default() -> Self { - Self { total: Default::default(), size: Default::default(), phantom: PhantomData } - } -} - -impl fmt::Display for SymbolsStats { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "{} of module index symbols ({})", self.size, self.total) - } -} -impl fmt::Display for SymbolsStats { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "{} of library index symbols ({})", self.size, self.total) - } -} -impl StatCollect> for SymbolsStats { - fn collect_entry(&mut self, _: Key, value: Option>) { - if let Some(symbols) = value { - self.total += symbols.len(); - self.size += symbols.memory_size(); - } - } -} - -#[derive(Default)] -struct AttrsStats { - entries: usize, - total: usize, -} - -impl fmt::Display for AttrsStats { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let size = self.entries * size_of::() + self.total * size_of::(); - let size = Bytes::new(size as _); - write!( - fmt, - "{} attribute query entries, {} total attributes ({} for storing entries)", - self.entries, self.total, size - ) - } -} - -impl StatCollect for AttrsStats { - fn collect_entry(&mut self, _: Key, value: Option) { - self.entries += 1; - self.total += value.map_or(0, |it| it.len()); - } -} diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs index 83082496d5b64..ef5d480b49c70 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs @@ -18,7 +18,9 @@ use either::Either; use hir::{ DefWithBody, HirFileIdExt, InFile, InRealFile, MacroFileIdExt, MacroKind, Name, Semantics, }; -use ide_db::{FxHashMap, FxHashSet, Ranker, RootDatabase, SymbolKind}; +use ide_db::{ + base_db::salsa::AsDynDatabase, FxHashMap, FxHashSet, Ranker, RootDatabase, SymbolKind, +}; use span::EditionedFileId; use syntax::{ ast::{self, IsString}, @@ -203,7 +205,9 @@ pub(crate) fn highlight( // Determine the root based on the given range. let (root, range_to_highlight) = { - let file = sema.parse(file_id); + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(db.as_dyn_database(), file_id); + let file = sema.parse(editioned_file_id_wrapper); let source_file = file.syntax(); match range_to_highlight { Some(range) => { diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs index 07d40bafeba17..6a03da6a6eaa5 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs @@ -1,6 +1,7 @@ //! Renders a bit of code as HTML. use hir::Semantics; +use ide_db::base_db::salsa::AsDynDatabase; use oorandom::Rand32; use span::EditionedFileId; use stdx::format_to; @@ -16,7 +17,9 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo let file_id = sema .attach_first_edition(file_id) .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); - let file = sema.parse(file_id); + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(db.as_dyn_database(), file_id); + let file = sema.parse(editioned_file_id_wrapper); let file = file.syntax(); fn rainbowify(seed: u64) -> String { let mut rng = Rand32::new(seed); diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html index 7f6b4c2c880e1..e1a8d876c417b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html @@ -41,14 +41,14 @@ .unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
fn main() {
-    let hello = "hello";
-    let x = hello.to_string();
-    let y = hello.to_string();
+    let hello = "hello";
+    let x = hello.to_string();
+    let y = hello.to_string();
 
-    let x = "other color please!";
-    let y = x.to_string();
+    let x = "other color please!";
+    let y = x.to_string();
 }
 
 fn bar() {
-    let mut hello = "hello";
+    let mut hello = "hello";
 }
\ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs index 30b1d4c39b301..68f5c72d20531 100644 --- a/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs +++ b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs @@ -2,7 +2,7 @@ use hir::{Crate, Module, ModuleDef, Semantics}; use ide_db::{ - base_db::{CrateGraph, CrateId, SourceDatabase}, + base_db::{CrateGraph, CrateId, RootQueryDb}, FileId, RootDatabase, }; use syntax::TextRange; diff --git a/src/tools/rust-analyzer/crates/ide/src/typing.rs b/src/tools/rust-analyzer/crates/ide/src/typing.rs index 8c9dd05145272..f583aa801eaac 100644 --- a/src/tools/rust-analyzer/crates/ide/src/typing.rs +++ b/src/tools/rust-analyzer/crates/ide/src/typing.rs @@ -15,10 +15,13 @@ mod on_enter; +use ide_db::{ + base_db::{salsa::AsDynDatabase, RootQueryDb}, + FilePosition, RootDatabase, +}; +use span::{Edition, EditionedFileId}; use std::iter; -use ide_db::{base_db::SourceDatabase, FilePosition, RootDatabase}; -use span::{Edition, EditionedFileId}; use syntax::{ algo::{ancestors_at_offset, find_node_at_offset}, ast::{self, edit::IndentLevel, AstToken}, @@ -73,7 +76,11 @@ pub(crate) fn on_char_typed( // FIXME: We are hitting the database here, if we are unlucky this call might block momentarily // causing the editor to feel sluggish! let edition = Edition::CURRENT_FIXME; - let file = &db.parse(EditionedFileId::new(position.file_id, edition)); + let editioned_file_id_wrapper = ide_db::base_db::EditionedFileId::new( + db.as_dyn_database(), + EditionedFileId::new(position.file_id, edition), + ); + let file = &db.parse(editioned_file_id_wrapper); let char_matches_position = file.tree().syntax().text().char_at(position.offset) == Some(char_typed); if !stdx::always!(char_matches_position) { diff --git a/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs b/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs index c6d1c283f4eca..8cadb61040390 100644 --- a/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs +++ b/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs @@ -1,8 +1,8 @@ //! Handles the `Enter` key press. At the momently, this only continues //! comments, but should handle indent some time in the future as well. -use ide_db::RootDatabase; -use ide_db::{base_db::SourceDatabase, FilePosition}; +use ide_db::base_db::RootQueryDb; +use ide_db::{base_db::salsa::AsDynDatabase, FilePosition, RootDatabase}; use span::EditionedFileId; use syntax::{ algo::find_node_at_offset, @@ -51,7 +51,11 @@ use ide_db::text_edit::TextEdit; // // ![On Enter](https://user-images.githubusercontent.com/48062697/113065578-04c21800-91b1-11eb-82b8-22b8c481e645.gif) pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option { - let parse = db.parse(EditionedFileId::current_edition(position.file_id)); + let editioned_file_id_wrapper = ide_db::base_db::EditionedFileId::new( + db.as_dyn_database(), + EditionedFileId::current_edition(position.file_id), + ); + let parse = db.parse(editioned_file_id_wrapper); let file = parse.tree(); let token = file.syntax().token_at_offset(position.offset).left_biased()?; diff --git a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs index eb6eb7da1e90a..eeb65ac038932 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs @@ -1,6 +1,6 @@ use dot::{Id, LabelText}; use ide_db::{ - base_db::{CrateGraph, CrateId, Dependency, SourceDatabase, SourceRootDatabase}, + base_db::{CrateGraph, CrateId, Dependency, RootQueryDb, SourceDatabase, Upcast}, FxHashSet, RootDatabase, }; use triomphe::Arc; @@ -16,7 +16,7 @@ use triomphe::Arc; // |---------|-------------| // | VS Code | **rust-analyzer: View Crate Graph** | pub(crate) fn view_crate_graph(db: &RootDatabase, full: bool) -> Result { - let crate_graph = db.crate_graph(); + let crate_graph = Upcast::::upcast(db).crate_graph(); let crates_to_render = crate_graph .iter() .filter(|krate| { @@ -24,8 +24,9 @@ pub(crate) fn view_crate_graph(db: &RootDatabase, full: bool) -> Result [joint] 0:0@93..94#2 - PUNCH , [alone] 0:0@94..95#2 + SUBTREE $$ 1:0@0..20#4294967037 1:0@0..20#4294967037 + IDENT struct 0:0@34..40#4294967037 + IDENT MyTraitMap2 1:0@8..19#4294967037 + SUBTREE {} 0:0@48..49#4294967037 0:0@100..101#4294967037 + IDENT map 0:0@58..61#4294967037 + PUNCH : [alone] 0:0@61..62#4294967037 + PUNCH : [joint] 0:0@63..64#4294967037 + PUNCH : [alone] 0:0@64..65#4294967037 + IDENT std 0:0@65..68#4294967037 + PUNCH : [joint] 0:0@68..69#4294967037 + PUNCH : [alone] 0:0@69..70#4294967037 + IDENT collections 0:0@70..81#4294967037 + PUNCH : [joint] 0:0@81..82#4294967037 + PUNCH : [alone] 0:0@82..83#4294967037 + IDENT HashSet 0:0@83..90#4294967037 + PUNCH < [alone] 0:0@90..91#4294967037 + SUBTREE () 0:0@91..92#4294967037 0:0@92..93#4294967037 + PUNCH > [joint] 0:0@93..94#4294967037 + PUNCH , [alone] 0:0@94..95#4294967037 struct MyTraitMap2 { map: ::std::collections::HashSet<()>, @@ -179,28 +179,28 @@ fn main() { } "#, expect![[r#" - SUBTREE $$ 1:0@0..63#2 1:0@0..63#2 - IDENT fn 1:0@1..3#2 - IDENT main 1:0@4..8#2 - SUBTREE () 1:0@8..9#2 1:0@9..10#2 - SUBTREE {} 1:0@11..12#2 1:0@61..62#2 - LITERAL Integer 1 1:0@17..18#2 - PUNCH ; [alone] 1:0@18..19#2 - LITERAL Float 1.0 1:0@24..27#2 - PUNCH ; [alone] 1:0@27..28#2 - SUBTREE () 1:0@33..34#2 1:0@39..40#2 - SUBTREE () 1:0@34..35#2 1:0@37..38#2 - LITERAL Integer 1 1:0@35..36#2 - PUNCH , [alone] 1:0@36..37#2 - PUNCH , [alone] 1:0@38..39#2 - PUNCH . [alone] 1:0@40..41#2 - LITERAL Float 0.0 1:0@41..44#2 - PUNCH ; [alone] 1:0@44..45#2 - IDENT let 1:0@50..53#2 - IDENT x 1:0@54..55#2 - PUNCH = [alone] 1:0@56..57#2 - LITERAL Integer 1 1:0@58..59#2 - PUNCH ; [alone] 1:0@59..60#2 + SUBTREE $$ 1:0@0..63#4294967037 1:0@0..63#4294967037 + IDENT fn 1:0@1..3#4294967037 + IDENT main 1:0@4..8#4294967037 + SUBTREE () 1:0@8..9#4294967037 1:0@9..10#4294967037 + SUBTREE {} 1:0@11..12#4294967037 1:0@61..62#4294967037 + LITERAL Integer 1 1:0@17..18#4294967037 + PUNCH ; [alone] 1:0@18..19#4294967037 + LITERAL Float 1.0 1:0@24..27#4294967037 + PUNCH ; [alone] 1:0@27..28#4294967037 + SUBTREE () 1:0@33..34#4294967037 1:0@39..40#4294967037 + SUBTREE () 1:0@34..35#4294967037 1:0@37..38#4294967037 + LITERAL Integer 1 1:0@35..36#4294967037 + PUNCH , [alone] 1:0@36..37#4294967037 + PUNCH , [alone] 1:0@38..39#4294967037 + PUNCH . [alone] 1:0@40..41#4294967037 + LITERAL Float 0.0 1:0@41..44#4294967037 + PUNCH ; [alone] 1:0@44..45#4294967037 + IDENT let 1:0@50..53#4294967037 + IDENT x 1:0@54..55#4294967037 + PUNCH = [alone] 1:0@56..57#4294967037 + LITERAL Integer 1 1:0@58..59#4294967037 + PUNCH ; [alone] 1:0@59..60#4294967037 fn main(){ 1; @@ -226,14 +226,14 @@ fn expr_2021() { const { 1 }, "#, expect![[r#" - SUBTREE $$ 1:0@0..25#2 1:0@0..25#2 - IDENT _ 1:0@5..6#2 - PUNCH ; [joint] 0:0@36..37#2 - SUBTREE () 0:0@34..35#2 0:0@34..35#2 - IDENT const 1:0@12..17#2 - SUBTREE {} 1:0@18..19#2 1:0@22..23#2 - LITERAL Integer 1 1:0@20..21#2 - PUNCH ; [alone] 0:0@39..40#2 + SUBTREE $$ 1:0@0..25#4294967037 1:0@0..25#4294967037 + IDENT _ 1:0@5..6#4294967037 + PUNCH ; [joint] 0:0@36..37#4294967037 + SUBTREE () 0:0@34..35#4294967037 0:0@34..35#4294967037 + IDENT const 1:0@12..17#4294967037 + SUBTREE {} 1:0@18..19#4294967037 1:0@22..23#4294967037 + LITERAL Integer 1 1:0@20..21#4294967037 + PUNCH ; [alone] 0:0@39..40#4294967037 _; (const { @@ -254,13 +254,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..6#2, + 1:0@5..6#4294967037, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..8#2 1:0@0..8#2 - PUNCH ; [alone] 0:0@39..40#2 + SUBTREE $$ 1:0@0..8#4294967037 1:0@0..8#4294967037 + PUNCH ; [alone] 0:0@39..40#4294967037 ;"#]], ); @@ -278,13 +278,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..10#2, + 1:0@5..10#4294967037, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..18#2 1:0@0..18#2 - PUNCH ; [alone] 0:0@39..40#2 + SUBTREE $$ 1:0@0..18#4294967037 1:0@0..18#4294967037 + PUNCH ; [alone] 0:0@39..40#4294967037 ;"#]], ); @@ -304,26 +304,26 @@ fn expr_2021() { break 'foo bar, "#, expect![[r#" - SUBTREE $$ 1:0@0..76#2 1:0@0..76#2 - LITERAL Integer 4 1:0@5..6#2 - PUNCH ; [joint] 0:0@41..42#2 - LITERAL Str literal 1:0@12..21#2 - PUNCH ; [joint] 0:0@41..42#2 - SUBTREE () 0:0@39..40#2 0:0@39..40#2 - IDENT funcall 1:0@27..34#2 - SUBTREE () 1:0@34..35#2 1:0@35..36#2 - PUNCH ; [joint] 0:0@41..42#2 - SUBTREE () 0:0@39..40#2 0:0@39..40#2 - IDENT future 1:0@42..48#2 - PUNCH . [alone] 1:0@48..49#2 - IDENT await 1:0@49..54#2 - PUNCH ; [joint] 0:0@41..42#2 - SUBTREE () 0:0@39..40#2 0:0@39..40#2 - IDENT break 1:0@60..65#2 - PUNCH ' [joint] 1:0@66..67#2 - IDENT foo 1:0@67..70#2 - IDENT bar 1:0@71..74#2 - PUNCH ; [alone] 0:0@44..45#2 + SUBTREE $$ 1:0@0..76#4294967037 1:0@0..76#4294967037 + LITERAL Integer 4 1:0@5..6#4294967037 + PUNCH ; [joint] 0:0@41..42#4294967037 + LITERAL Str literal 1:0@12..21#4294967037 + PUNCH ; [joint] 0:0@41..42#4294967037 + SUBTREE () 0:0@39..40#4294967037 0:0@39..40#4294967037 + IDENT funcall 1:0@27..34#4294967037 + SUBTREE () 1:0@34..35#4294967037 1:0@35..36#4294967037 + PUNCH ; [joint] 0:0@41..42#4294967037 + SUBTREE () 0:0@39..40#4294967037 0:0@39..40#4294967037 + IDENT future 1:0@42..48#4294967037 + PUNCH . [alone] 1:0@48..49#4294967037 + IDENT await 1:0@49..54#4294967037 + PUNCH ; [joint] 0:0@41..42#4294967037 + SUBTREE () 0:0@39..40#4294967037 0:0@39..40#4294967037 + IDENT break 1:0@60..65#4294967037 + PUNCH ' [joint] 1:0@66..67#4294967037 + IDENT foo 1:0@67..70#4294967037 + IDENT bar 1:0@71..74#4294967037 + PUNCH ; [alone] 0:0@44..45#4294967037 4; "literal"; @@ -345,13 +345,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..6#2, + 1:0@5..6#4294967037, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..8#2 1:0@0..8#2 - PUNCH ; [alone] 0:0@44..45#2 + SUBTREE $$ 1:0@0..8#4294967037 1:0@0..8#4294967037 + PUNCH ; [alone] 0:0@44..45#4294967037 ;"#]], ); diff --git a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml index 24e059f40bee5..99d1bf7e2c7ce 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml +++ b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml @@ -17,7 +17,7 @@ heck = "0.5.0" proc-macro2 = "1.0" quote = "1.0" syn = { version = "2.0", features = ["full", "extra-traits"] } -salsa = { version = "0.19.0" } +salsa.workspace = true [dev-dependencies] expect-test = "1.5.0" diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index dee76ee15c3df..a391a01fae74e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -22,21 +22,15 @@ use ide::{ Analysis, AnalysisHost, AnnotationConfig, DiagnosticsConfig, Edition, InlayFieldsToResolve, InlayHintsConfig, LineCol, RootDatabase, }; -use ide_db::{ - base_db::{ - ra_salsa::{self, debug::DebugQueryTable, ParallelDatabase}, - SourceDatabase, SourceRootDatabase, - }, - EditionedFileId, LineIndexDatabase, SnippetCap, -}; +use ide_db::{base_db::SourceDatabase, EditionedFileId, LineIndexDatabase, SnippetCap}; use itertools::Itertools; use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice}; use oorandom::Rand32; -use profile::{Bytes, StopWatch}; +use profile::StopWatch; use project_model::{CargoConfig, CfgOverrides, ProjectManifest, ProjectWorkspace, RustLibSource}; use rayon::prelude::*; use rustc_hash::{FxHashMap, FxHashSet}; -use syntax::{AstNode, SyntaxNode}; +use syntax::AstNode; use vfs::{AbsPathBuf, Vfs, VfsPath}; use crate::cli::{ @@ -46,14 +40,6 @@ use crate::cli::{ report_metric, Verbosity, }; -/// Need to wrap Snapshot to provide `Clone` impl for `map_with` -struct Snap(DB); -impl Clone for Snap> { - fn clone(&self) -> Snap> { - Snap(self.0.snapshot()) - } -} - impl flags::AnalysisStats { pub fn run(self, verbosity: Verbosity) -> anyhow::Result<()> { let mut rng = { @@ -129,10 +115,13 @@ impl flags::AnalysisStats { let mut item_tree_sw = self.stop_watch(); let mut num_item_trees = 0; - let source_roots = - krates.iter().cloned().map(|krate| db.file_source_root(krate.root_file(db))).unique(); + let source_roots = krates + .iter() + .cloned() + .map(|krate| db.file_source_root(krate.root_file(db)).source_root_id(db)) + .unique(); for source_root_id in source_roots { - let source_root = db.source_root(source_root_id); + let source_root = db.source_root(source_root_id).source_root(db); if !source_root.is_library || self.with_deps { for file_id in source_root.iter() { if let Some(p) = source_root.path_for_file(&file_id) { @@ -157,8 +146,9 @@ impl flags::AnalysisStats { let module = krate.root_module(); let file_id = module.definition_source_file_id(db); let file_id = file_id.original_file(db); - let source_root = db.file_source_root(file_id.into()); - let source_root = db.source_root(source_root); + + let source_root = db.file_source_root(file_id.into()).source_root_id(db); + let source_root = db.source_root(source_root).source_root(db); if !source_root.is_library || self.with_deps { num_crates += 1; visit_queue.push(module); @@ -268,17 +258,21 @@ impl flags::AnalysisStats { report_metric("total memory", total_span.memory.allocated.megabytes() as u64, "MB"); if self.source_stats { - let mut total_file_size = Bytes::default(); - for e in ide_db::base_db::ParseQuery.in_db(db).entries::>() { - total_file_size += syntax_len(db.parse(e.key).syntax_node()) - } - - let mut total_macro_file_size = Bytes::default(); - for e in hir::db::ParseMacroExpansionQuery.in_db(db).entries::>() { - let val = db.parse_macro_expansion(e.key).value.0; - total_macro_file_size += syntax_len(val.syntax_node()) - } - eprintln!("source files: {total_file_size}, macro files: {total_macro_file_size}"); + // FIXME(salsa-transition): bring back stats for ParseQuery (file size) + // and ParseMacroExpansionQuery (mcaro expansion "file") size whenever we implement + // Salsa's memory usage tracking works with tracked functions. + + // let mut total_file_size = Bytes::default(); + // for e in ide_db::base_db::ParseQuery.in_db(db).entries::>() { + // total_file_size += syntax_len(db.parse(e.key).syntax_node()) + // } + + // let mut total_macro_file_size = Bytes::default(); + // for e in hir::db::ParseMacroExpansionQuery.in_db(db).entries::>() { + // let val = db.parse_macro_expansion(e.key).value.0; + // total_macro_file_size += syntax_len(val.syntax_node()) + // } + // eprintln!("source files: {total_file_size}, macro files: {total_macro_file_size}"); } if verbosity.is_verbose() { @@ -423,6 +417,7 @@ impl flags::AnalysisStats { let range = sema.original_range(expected_tail.syntax()).range; let original_text: String = db .file_text(file_id.into()) + .text(db) .chars() .skip(usize::from(range.start())) .take(usize::from(range.end()) - usize::from(range.start())) @@ -475,7 +470,7 @@ impl flags::AnalysisStats { syntax_hit_found |= trim(&original_text) == trim(&generated); // Validate if type-checks - let mut txt = file_txt.to_string(); + let mut txt = file_txt.text(db).to_string(); let edit = ide::TextEdit::replace(range, generated.clone()); edit.apply(&mut txt); @@ -530,7 +525,7 @@ impl flags::AnalysisStats { } // Revert file back to original state if self.validate_term_search { - std::fs::write(path, file_txt.to_string()).unwrap(); + std::fs::write(path, file_txt.text(db).to_string()).unwrap(); } bar.inc(1); @@ -572,6 +567,11 @@ impl flags::AnalysisStats { } fn run_mir_lowering(&self, db: &RootDatabase, bodies: &[DefWithBody], verbosity: Verbosity) { + let mut bar = match verbosity { + Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(), + _ if self.parallel || self.output.is_some() => ProgressReport::hidden(), + _ => ProgressReport::new(bodies.len() as u64), + }; let mut sw = self.stop_watch(); let mut all = 0; let mut fail = 0; @@ -593,11 +593,13 @@ impl flags::AnalysisStats { .chain(Some(body.name(db).unwrap_or_else(Name::missing))) .map(|it| it.display(db, Edition::LATEST).to_string()) .join("::"); - println!("Mir body for {full_name} failed due {e:?}"); + bar.println(format!("Mir body for {full_name} failed due {e:?}")); } fail += 1; + bar.tick(); } let mir_lowering_time = sw.elapsed(); + bar.finish_and_clear(); eprintln!("{:<20} {}", "MIR lowering:", mir_lowering_time); eprintln!("Mir failed bodies: {fail} ({}%)", percentage(fail, all)); report_metric("mir failed bodies", fail, "#"); @@ -619,12 +621,12 @@ impl flags::AnalysisStats { if self.parallel { let mut inference_sw = self.stop_watch(); - let snap = Snap(db.snapshot()); + let snap = db.snapshot(); bodies .par_iter() .map_with(snap, |snap, &body| { - snap.0.body(body.into()); - snap.0.infer(body.into()); + snap.body(body.into()); + snap.infer(body.into()); }) .count(); eprintln!("{:<20} {}", "Parallel Inference:", inference_sw.elapsed()); @@ -1206,8 +1208,10 @@ fn percentage(n: u64, total: u64) -> u64 { (n * 100).checked_div(total).unwrap_or(100) } -fn syntax_len(node: SyntaxNode) -> usize { - // Macro expanded code doesn't contain whitespace, so erase *all* whitespace - // to make macro and non-macro code comparable. - node.to_string().replace(|it: char| it.is_ascii_whitespace(), "").len() -} +// FIXME(salsa-transition): bring this back whenever we implement +// Salsa's memory usage tracking to work with tracked functions. +// fn syntax_len(node: SyntaxNode) -> usize { +// // Macro expanded code doesn't contain whitespace, so erase *all* whitespace +// // to make macro and non-macro code comparable. +// node.to_string().replace(|it: char| it.is_ascii_whitespace(), "").len() +// } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs index 6a3ceb640b91a..ae1054a804980 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs @@ -6,7 +6,7 @@ use rustc_hash::FxHashSet; use hir::{db::HirDatabase, sym, Crate, HirFileIdExt, Module}; use ide::{AnalysisHost, AssistResolveStrategy, Diagnostic, DiagnosticsConfig, Severity}; -use ide_db::{base_db::SourceRootDatabase, LineIndexDatabase}; +use ide_db::{base_db::SourceDatabase, LineIndexDatabase}; use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice}; use crate::cli::flags; @@ -51,8 +51,8 @@ impl flags::Diagnostics { let work = all_modules(db).into_iter().filter(|module| { let file_id = module.definition_source_file_id(db).original_file(db); - let source_root = db.file_source_root(file_id.into()); - let source_root = db.source_root(source_root); + let source_root = db.file_source_root(file_id.into()).source_root_id(db); + let source_root = db.source_root(source_root).source_root(db); !source_root.is_library }); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs index 7398b9a9ef0b0..20da40f384b17 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs @@ -2,7 +2,7 @@ use hir::{Crate, Module}; use hir_ty::db::HirDatabase; -use ide_db::{base_db::SourceRootDatabase, LineIndexDatabase}; +use ide_db::{base_db::SourceDatabase, LineIndexDatabase}; use profile::StopWatch; use project_model::{CargoConfig, RustLibSource}; use syntax::TextRange; @@ -40,10 +40,10 @@ impl flags::RunTests { None => " (unknown line col)".to_owned(), Some(x) => format!("#{}:{}", x.line + 1, x.col), }; - let path = &db - .source_root(db.file_source_root(file_id)) - .path_for_file(&file_id) - .map(|x| x.to_string()); + let source_root = db.file_source_root(file_id).source_root_id(db); + let source_root = db.source_root(source_root).source_root(db); + + let path = source_root.path_for_file(&file_id).map(|x| x.to_string()); let path = path.as_deref().unwrap_or(""); format!("file://{path}{line_col}") }; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index e9ca12deaf6e6..7c7ed911293f5 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -164,13 +164,13 @@ impl Tester { let analysis = self.host.analysis(); let root_file = self.root_file; move || { - let res = std::panic::catch_unwind(move || { + let res = std::panic::catch_unwind(AssertUnwindSafe(move || { analysis.full_diagnostics( diagnostic_config, ide::AssistResolveStrategy::None, root_file, ) - }); + })); main.unpark(); res } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs index c03688e8009cb..a3bb70421512a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs @@ -34,7 +34,7 @@ impl flags::Ssr { let edits = match_finder.edits(); for (file_id, edit) in edits { if let Some(path) = vfs.file_path(file_id).as_path() { - let mut contents = db.file_text(file_id).to_string(); + let mut contents = db.file_text(file_id).text(db).to_string(); edit.apply(&mut contents); std::fs::write(path, contents) .with_context(|| format!("failed to write {path}"))?; @@ -49,7 +49,7 @@ impl flags::Search { /// `debug_snippet`. This is intended for debugging and probably isn't in it's current form useful /// for much else. pub fn run(self) -> anyhow::Result<()> { - use ide_db::base_db::SourceRootDatabase; + use ide_db::base_db::SourceDatabase; use ide_db::symbol_index::SymbolsDatabase; let cargo_config = CargoConfig { all_targets: true, set_test: true, ..CargoConfig::default() }; @@ -70,7 +70,7 @@ impl flags::Search { } if let Some(debug_snippet) = &self.debug { for &root in db.local_roots().iter() { - let sr = db.source_root(root); + let sr = db.source_root(root).source_root(db); for file_id in sr.iter() { for debug_info in match_finder.debug_where_text_equal( EditionedFileId::current_edition(file_id), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs index 021b1bff39301..9acf4b85334cb 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs @@ -2,7 +2,7 @@ use hir::{db::HirDatabase, sym, AnyDiagnostic, Crate, HirFileIdExt as _, Module, Semantics}; use ide::{AnalysisHost, RootDatabase, TextRange}; use ide_db::{ - base_db::{SourceDatabase, SourceRootDatabase}, + base_db::{salsa::AsDynDatabase, SourceDatabase}, defs::NameRefClass, EditionedFileId, FxHashSet, LineIndexDatabase as _, }; @@ -57,8 +57,8 @@ impl flags::UnresolvedReferences { let work = all_modules(db).into_iter().filter(|module| { let file_id = module.definition_source_file_id(db).original_file(db); - let source_root = db.file_source_root(file_id.into()); - let source_root = db.source_root(source_root); + let source_root = db.file_source_root(file_id.into()).source_root_id(db); + let source_root = db.source_root(source_root).source_root(db); !source_root.is_library }); @@ -77,7 +77,7 @@ impl flags::UnresolvedReferences { let line_col = line_index.line_col(range.start()); let line = line_col.line + 1; let col = line_col.col + 1; - let text = &file_text[range]; + let text = &file_text.text(db)[range]; println!("{file_path}:{line}:{col}: {text}"); } @@ -141,7 +141,9 @@ fn all_unresolved_references( let file_id = sema .attach_first_edition(file_id) .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); - let file = sema.parse(file_id); + let editioned_file_id_wrapper = + ide_db::base_db::EditionedFileId::new(sema.db.as_dyn_database(), file_id); + let file = sema.parse(editioned_file_id_wrapper); let root = file.syntax(); let mut unresolved_references = Vec::new(); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index 54670b675984d..f114a4454e002 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -8,7 +8,7 @@ use std::{ops::Not as _, time::Instant}; use crossbeam_channel::{unbounded, Receiver, Sender}; use hir::ChangeWithProcMacros; use ide::{Analysis, AnalysisHost, Cancellable, FileId, SourceRootId}; -use ide_db::base_db::{CrateId, ProcMacroPaths, SourceDatabase, SourceRootDatabase}; +use ide_db::base_db::{CrateId, ProcMacroPaths, SourceDatabase}; use itertools::Itertools; use load_cargo::SourceRootConfig; use lsp_types::{SemanticTokens, Url}; @@ -426,29 +426,28 @@ impl GlobalState { tracing::info!(%vfs_path, ?change_kind, "Processing rust-analyzer.toml changes"); if vfs_path.as_path() == user_config_abs_path { tracing::info!(%vfs_path, ?change_kind, "Use config rust-analyzer.toml changes"); - change.change_user_config(Some(db.file_text(file_id))); - continue; + change.change_user_config(Some(db.file_text(file_id).text(db))); } // If change has been made to a ratoml file that // belongs to a non-local source root, we will ignore it. - let sr_id = db.file_source_root(file_id); - let sr = db.source_root(sr_id); + let source_root_id = db.file_source_root(file_id).source_root_id(db); + let source_root = db.source_root(source_root_id).source_root(db); - if !sr.is_library { + if !source_root.is_library { let entry = if workspace_ratoml_paths.contains(&vfs_path) { - tracing::info!(%vfs_path, ?sr_id, "workspace rust-analyzer.toml changes"); + tracing::info!(%vfs_path, ?source_root_id, "workspace rust-analyzer.toml changes"); change.change_workspace_ratoml( - sr_id, + source_root_id, vfs_path.clone(), - Some(db.file_text(file_id)), + Some(db.file_text(file_id).text(db)), ) } else { - tracing::info!(%vfs_path, ?sr_id, "crate rust-analyzer.toml changes"); + tracing::info!(%vfs_path, ?source_root_id, "crate rust-analyzer.toml changes"); change.change_ratoml( - sr_id, + source_root_id, vfs_path.clone(), - Some(db.file_text(file_id)), + Some(db.file_text(file_id).text(db)), ) }; @@ -459,10 +458,14 @@ impl GlobalState { // Put the old one back in. match kind { RatomlFileKind::Crate => { - change.change_ratoml(sr_id, old_path, old_text); + change.change_ratoml(source_root_id, old_path, old_text); } RatomlFileKind::Workspace => { - change.change_workspace_ratoml(sr_id, old_path, old_text); + change.change_workspace_ratoml( + source_root_id, + old_path, + old_text, + ); } } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs index 4683877db69b0..680ff00608378 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs @@ -4,8 +4,7 @@ use std::{ panic, thread, }; -use ide::Cancelled; -use ide_db::base_db::ra_salsa::Cycle; +use ide_db::base_db::salsa::{self, Cancelled, Cycle}; use lsp_server::{ExtractError, Response, ResponseError}; use serde::{de::DeserializeOwned, Serialize}; use stdx::thread::ThreadIntent; @@ -311,7 +310,7 @@ impl RequestDispatcher<'_> { #[derive(Debug)] enum HandlerCancelledError { PropagatedPanic, - Inner(ide::Cancelled), + Inner(salsa::Cancelled), } impl std::error::Error for HandlerCancelledError { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs index 55344a4d6ac60..a30e5d8ce268e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs @@ -3,6 +3,7 @@ use std::ops::{Deref, Not as _}; +use ide_db::base_db::salsa::Cancelled; use itertools::Itertools; use lsp_types::{ CancelParams, DidChangeConfigurationParams, DidChangeTextDocumentParams, @@ -305,7 +306,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool { let invocation_strategy_once = state.config.flycheck(None).invocation_strategy_once(); let may_flycheck_workspace = state.config.flycheck_workspace(None); let mut updated = false; - let task = move || -> std::result::Result<(), ide::Cancelled> { + let task = move || -> std::result::Result<(), Cancelled> { if invocation_strategy_once { let saved_file = vfs_path.as_path().map(|p| p.to_owned()); world.flycheck[0].restart_workspace(saved_file.clone()); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 68b2d6b696289..170481ea70164 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -502,6 +502,7 @@ pub(crate) fn handle_document_diagnostics( if !snap.analysis.is_local_source_root(source_root)? { return Ok(empty_diagnostic_report()); } + let source_root = snap.analysis.source_root_id(file_id)?; let config = snap.config.diagnostics(Some(source_root)); if !config.enabled { return Ok(empty_diagnostic_report()); @@ -1068,7 +1069,11 @@ pub(crate) fn handle_related_tests( pub(crate) fn handle_completion( snap: GlobalStateSnapshot, - lsp_types::CompletionParams { text_document_position, context,.. }: lsp_types::CompletionParams, + lsp_types::CompletionParams { + text_document_position, + context, + .. + }: lsp_types::CompletionParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_completion").entered(); let mut position = @@ -1117,7 +1122,9 @@ pub(crate) fn handle_completion_resolve( .into()); } - let Some(data) = original_completion.data.take() else { return Ok(original_completion) }; + let Some(data) = original_completion.data.take() else { + return Ok(original_completion); + }; let resolve_data: lsp_ext::CompletionResolveData = serde_json::from_value(data)?; @@ -1500,7 +1507,7 @@ pub(crate) fn handle_code_action_resolve( "Failed to parse action id string '{}': {e}", params.id )) - .into()) + .into()); } }; @@ -1608,7 +1615,9 @@ pub(crate) fn handle_code_lens_resolve( snap: GlobalStateSnapshot, mut code_lens: CodeLens, ) -> anyhow::Result { - let Some(data) = code_lens.data.take() else { return Ok(code_lens) }; + let Some(data) = code_lens.data.take() else { + return Ok(code_lens); + }; let resolve = serde_json::from_value::(data)?; let Some(annotation) = from_proto::annotation(&snap, code_lens.range, resolve)? else { return Ok(code_lens); @@ -1718,14 +1727,18 @@ pub(crate) fn handle_inlay_hints_resolve( ) -> anyhow::Result { let _p = tracing::info_span!("handle_inlay_hints_resolve").entered(); - let Some(data) = original_hint.data.take() else { return Ok(original_hint) }; + let Some(data) = original_hint.data.take() else { + return Ok(original_hint); + }; let resolve_data: lsp_ext::InlayHintResolveData = serde_json::from_value(data)?; let file_id = FileId::from_raw(resolve_data.file_id); if resolve_data.version != snap.file_version(file_id) { tracing::warn!("Inlay hint resolve data is outdated"); return Ok(original_hint); } - let Some(hash) = resolve_data.hash.parse().ok() else { return Ok(original_hint) }; + let Some(hash) = resolve_data.hash.parse().ok() else { + return Ok(original_hint); + }; anyhow::ensure!(snap.file_exists(file_id), "Invalid LSP resolve data"); let line_index = snap.file_line_index(file_id)?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index f5d9469f2622f..b47a126424aa0 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -10,7 +10,7 @@ use std::{ use always_assert::always; use crossbeam_channel::{select, Receiver}; -use ide_db::base_db::{SourceDatabase, SourceRootDatabase, VfsPath}; +use ide_db::base_db::{RootQueryDb, SourceDatabase, VfsPath}; use lsp_server::{Connection, Notification, Request}; use lsp_types::{notification::Notification as _, TextDocumentIdentifier}; use stdx::thread::ThreadIntent; @@ -529,7 +529,7 @@ impl GlobalState { let num_worker_threads = self.config.prime_caches_num_threads(); self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, { - let analysis = self.snapshot().analysis; + let analysis = AssertUnwindSafe(self.snapshot().analysis); move |sender| { sender.send(Task::PrimeCaches(PrimeCachesProgress::Begin)).unwrap(); let res = analysis.parallel_prime_caches(num_worker_threads, |progress| { @@ -555,13 +555,14 @@ impl GlobalState { (excluded == vfs::FileExcluded::No).then_some(file_id) }) .filter(|&file_id| { - let source_root = db.file_source_root(file_id); + let source_root_id = db.file_source_root(file_id).source_root_id(db); + let source_root = db.source_root(source_root_id).source_root(db); // Only publish diagnostics for files in the workspace, not from crates.io deps // or the sysroot. // While theoretically these should never have errors, we have quite a few false // positives particularly in the stdlib, and those diagnostics would stay around // forever if we emitted them here. - !db.source_root(source_root).is_library + !source_root.is_library }) .collect::>() }; @@ -642,8 +643,9 @@ impl GlobalState { (excluded == vfs::FileExcluded::No).then_some(file_id) }) .filter(|&file_id| { - let source_root = db.file_source_root(file_id); - !db.source_root(source_root).is_library + let source_root_id = db.file_source_root(file_id).source_root_id(db); + let source_root = db.source_root(source_root_id).source_root(db); + !source_root.is_library }) .collect::>(); tracing::trace!("updating tests for {:?}", subscriptions); @@ -908,12 +910,12 @@ impl GlobalState { } QueuedTask::CheckProcMacroSources(modified_rust_files) => { let crate_graph = self.analysis_host.raw_database().crate_graph(); - let snap = self.snapshot(); + let analysis = AssertUnwindSafe(self.snapshot().analysis); self.task_pool.handle.spawn_with_sender(stdx::thread::ThreadIntent::Worker, { move |sender| { if modified_rust_files.into_iter().any(|file_id| { // FIXME: Check whether these files could be build script related - match snap.analysis.crates_for(file_id) { + match analysis.crates_for(file_id) { Ok(crates) => { crates.iter().any(|&krate| crate_graph[krate].is_proc_macro) } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 09b0adfeb8ae6..1a60fa06c9eb8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -18,7 +18,7 @@ use std::{iter, mem}; use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros, ProcMacrosBuilder}; use ide::CrateId; use ide_db::{ - base_db::{ra_salsa::Durability, CrateGraph, CrateWorkspaceData, ProcMacroPaths}, + base_db::{salsa::Durability, CrateGraph, CrateWorkspaceData, ProcMacroPaths}, FxHashMap, }; use itertools::Itertools; diff --git a/src/tools/rust-analyzer/crates/span/Cargo.toml b/src/tools/rust-analyzer/crates/span/Cargo.toml index 097a056c99a45..3381dac0b4255 100644 --- a/src/tools/rust-analyzer/crates/span/Cargo.toml +++ b/src/tools/rust-analyzer/crates/span/Cargo.toml @@ -12,7 +12,7 @@ authors.workspace = true [dependencies] la-arena.workspace = true -ra-salsa = { workspace = true, optional = true } +salsa.workspace = true rustc-hash.workspace = true hashbrown.workspace = true text-size.workspace = true @@ -22,8 +22,5 @@ vfs.workspace = true syntax.workspace = true stdx.workspace = true -[features] -default = ["ra-salsa"] - [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/span/src/hygiene.rs b/src/tools/rust-analyzer/crates/span/src/hygiene.rs index 6becc8e41ed00..a6402e870150e 100644 --- a/src/tools/rust-analyzer/crates/span/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/span/src/hygiene.rs @@ -21,44 +21,287 @@ //! `ExpnData::call_site` in rustc, [`MacroCallLoc::call_site`] in rust-analyzer. use std::fmt; -#[cfg(not(feature = "ra-salsa"))] -use crate::InternId; -#[cfg(feature = "ra-salsa")] -use ra_salsa::{InternId, InternValue}; - use crate::{Edition, MacroCallId}; -/// Interned [`SyntaxContextData`]. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct SyntaxContextId(InternId); +// Recursive expansion of interned macro +// ====================================== -impl fmt::Debug for SyntaxContextId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if f.alternate() { - write!(f, "{}", self.0.as_u32()) - } else { - f.debug_tuple("SyntaxContextId").field(&self.0).finish() +/// A syntax context describes a hierarchy tracking order of macro definitions. +#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +pub struct SyntaxContext( + salsa::Id, + std::marker::PhantomData<&'static salsa::plumbing::interned::Value>, +); + +/// The underlying data interned by Salsa. +#[derive(Clone, Eq, Debug)] +pub struct SyntaxContextUnderlyingData { + pub outer_expn: Option, + pub outer_transparency: Transparency, + pub edition: Edition, + pub parent: SyntaxContext, + pub opaque: SyntaxContext, + pub opaque_and_semitransparent: SyntaxContext, +} + +const _: () = { + use salsa::plumbing as zalsa_; + use salsa::plumbing::interned as zalsa_struct_; + + impl PartialEq for SyntaxContextUnderlyingData { + fn eq(&self, other: &Self) -> bool { + self.outer_expn == other.outer_expn + && self.outer_transparency == other.outer_transparency + && self.edition == other.edition + && self.parent == other.parent } } -} -#[cfg(feature = "ra-salsa")] -impl ra_salsa::InternKey for SyntaxContextId { - fn from_intern_id(v: ra_salsa::InternId) -> Self { - SyntaxContextId(v) + impl std::hash::Hash for SyntaxContextUnderlyingData { + fn hash(&self, state: &mut H) { + self.outer_expn.hash(state); + self.outer_transparency.hash(state); + self.edition.hash(state); + self.parent.hash(state); + } + } + /// Key to use during hash lookups. Each field is some type that implements `Lookup` + /// for the owned type. This permits interning with an `&str` when a `String` is required and so forth. + #[derive(Hash)] + struct StructKey<'db, T0, T1, T2, T3>(T0, T1, T2, T3, std::marker::PhantomData<&'db ()>); + + impl<'db, T0, T1, T2, T3> zalsa_::interned::HashEqLike> + for SyntaxContextUnderlyingData + where + Option: zalsa_::interned::HashEqLike, + Transparency: zalsa_::interned::HashEqLike, + Edition: zalsa_::interned::HashEqLike, + SyntaxContext: zalsa_::interned::HashEqLike, + { + fn hash(&self, h: &mut H) { + zalsa_::interned::HashEqLike::::hash(&self.outer_expn, &mut *h); + zalsa_::interned::HashEqLike::::hash(&self.outer_transparency, &mut *h); + zalsa_::interned::HashEqLike::::hash(&self.edition, &mut *h); + zalsa_::interned::HashEqLike::::hash(&self.parent, &mut *h); + } + fn eq(&self, data: &StructKey<'db, T0, T1, T2, T3>) -> bool { + zalsa_::interned::HashEqLike::::eq(&self.outer_expn, &data.0) + && zalsa_::interned::HashEqLike::::eq(&self.outer_transparency, &data.1) + && zalsa_::interned::HashEqLike::::eq(&self.edition, &data.2) + && zalsa_::interned::HashEqLike::::eq(&self.parent, &data.3) + } + } + impl zalsa_struct_::Configuration for SyntaxContext { + const DEBUG_NAME: &'static str = "SyntaxContextData"; + type Fields<'a> = SyntaxContextUnderlyingData; + type Struct<'a> = SyntaxContext; + fn struct_from_id<'db>(id: salsa::Id) -> Self::Struct<'db> { + SyntaxContext(id, std::marker::PhantomData) + } + fn deref_struct(s: Self::Struct<'_>) -> salsa::Id { + s.0 + } } - fn as_intern_id(&self) -> ra_salsa::InternId { - self.0 + impl SyntaxContext { + pub fn ingredient(db: &Db) -> &zalsa_struct_::IngredientImpl + where + Db: ?Sized + zalsa_::Database, + { + static CACHE: zalsa_::IngredientCache> = + zalsa_::IngredientCache::new(); + CACHE.get_or_create(db.as_dyn_database(), || { + db.zalsa().add_or_lookup_jar_by_type::>() + }) + } } -} + impl zalsa_::AsId for SyntaxContext { + fn as_id(&self) -> salsa::Id { + self.0 + } + } + impl zalsa_::FromId for SyntaxContext { + fn from_id(id: salsa::Id) -> Self { + Self(id, std::marker::PhantomData) + } + } + unsafe impl Send for SyntaxContext {} -impl fmt::Display for SyntaxContextId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0.as_u32()) + unsafe impl Sync for SyntaxContext {} + + impl zalsa_::SalsaStructInDb for SyntaxContext { + type MemoIngredientMap = salsa::plumbing::MemoIngredientSingletonIndex; + + fn lookup_or_create_ingredient_index( + aux: &salsa::plumbing::Zalsa, + ) -> salsa::plumbing::IngredientIndices { + aux.add_or_lookup_jar_by_type::>().into() + } + + #[inline] + fn cast(id: salsa::Id, type_id: std::any::TypeId) -> Option { + if type_id == std::any::TypeId::of::() { + Some(::from_id(id)) + } else { + None + } + } + } + + unsafe impl salsa::plumbing::Update for SyntaxContext { + unsafe fn maybe_update(old_pointer: *mut Self, new_value: Self) -> bool { + if unsafe { *old_pointer } != new_value { + unsafe { *old_pointer = new_value }; + true + } else { + false + } + } + } + impl<'db> SyntaxContext { + pub fn new< + Db, + T0: zalsa_::interned::Lookup> + std::hash::Hash, + T1: zalsa_::interned::Lookup + std::hash::Hash, + T2: zalsa_::interned::Lookup + std::hash::Hash, + T3: zalsa_::interned::Lookup + std::hash::Hash, + >( + db: &'db Db, + outer_expn: T0, + outer_transparency: T1, + edition: T2, + parent: T3, + opaque: impl FnOnce(SyntaxContext) -> SyntaxContext, + opaque_and_semitransparent: impl FnOnce(SyntaxContext) -> SyntaxContext, + ) -> Self + where + Db: ?Sized + salsa::Database, + Option: zalsa_::interned::HashEqLike, + Transparency: zalsa_::interned::HashEqLike, + Edition: zalsa_::interned::HashEqLike, + SyntaxContext: zalsa_::interned::HashEqLike, + { + SyntaxContext::ingredient(db).intern( + db.as_dyn_database(), + StructKey::<'db>( + outer_expn, + outer_transparency, + edition, + parent, + std::marker::PhantomData, + ), + |id, data| SyntaxContextUnderlyingData { + outer_expn: zalsa_::interned::Lookup::into_owned(data.0), + outer_transparency: zalsa_::interned::Lookup::into_owned(data.1), + edition: zalsa_::interned::Lookup::into_owned(data.2), + parent: zalsa_::interned::Lookup::into_owned(data.3), + opaque: opaque(zalsa_::FromId::from_id(id)), + opaque_and_semitransparent: opaque_and_semitransparent( + zalsa_::FromId::from_id(id), + ), + }, + ) + } + + /// Invariant: Only [`SyntaxContext::ROOT`] has a [`None`] outer expansion. + // FIXME: The None case needs to encode the context crate id. We can encode that as the MSB of + // MacroCallId is reserved anyways so we can do bit tagging here just fine. + // The bigger issue is that this will cause interning to now create completely separate chains + // per crate. Though that is likely not a problem as `MacroCallId`s are already crate calling dependent. + pub fn outer_expn(self, db: &'db Db) -> Option + where + Db: ?Sized + zalsa_::Database, + { + if self.is_root() { + return None; + } + let fields = SyntaxContext::ingredient(db).fields(db.as_dyn_database(), self); + std::clone::Clone::clone(&fields.outer_expn) + } + + pub fn outer_transparency(self, db: &'db Db) -> Transparency + where + Db: ?Sized + zalsa_::Database, + { + if self.is_root() { + return Transparency::Opaque; + } + let fields = SyntaxContext::ingredient(db).fields(db.as_dyn_database(), self); + std::clone::Clone::clone(&fields.outer_transparency) + } + + pub fn edition(self, db: &'db Db) -> Edition + where + Db: ?Sized + zalsa_::Database, + { + if self.is_root() { + return Edition::from_u32(SyntaxContext::MAX_ID - self.0.as_u32()); + } + let fields = SyntaxContext::ingredient(db).fields(db.as_dyn_database(), self); + std::clone::Clone::clone(&fields.edition) + } + + pub fn parent(self, db: &'db Db) -> SyntaxContext + where + Db: ?Sized + zalsa_::Database, + { + if self.is_root() { + return self; + } + let fields = SyntaxContext::ingredient(db).fields(db.as_dyn_database(), self); + std::clone::Clone::clone(&fields.parent) + } + + /// This context, but with all transparent and semi-transparent expansions filtered away. + pub fn opaque(self, db: &'db Db) -> SyntaxContext + where + Db: ?Sized + zalsa_::Database, + { + if self.is_root() { + return self; + } + let fields = SyntaxContext::ingredient(db).fields(db.as_dyn_database(), self); + std::clone::Clone::clone(&fields.opaque) + } + + /// This context, but with all transparent expansions filtered away. + pub fn opaque_and_semitransparent(self, db: &'db Db) -> SyntaxContext + where + Db: ?Sized + zalsa_::Database, + { + if self.is_root() { + return self; + } + let fields = SyntaxContext::ingredient(db).fields(db.as_dyn_database(), self); + std::clone::Clone::clone(&fields.opaque_and_semitransparent) + } + + pub fn default_debug_fmt(this: Self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + salsa::with_attached_database(|db| { + let fields = SyntaxContext::ingredient(db).fields(db.as_dyn_database(), this); + let mut f = f.debug_struct("SyntaxContextData"); + let f = f.field("outer_expn", &fields.outer_expn); + let f = f.field("outer_transparency", &fields.outer_expn); + let f = f.field("edition", &fields.edition); + let f = f.field("parent", &fields.parent); + let f = f.field("opaque", &fields.opaque); + let f = f.field("opaque_and_semitransparent", &fields.opaque_and_semitransparent); + f.finish() + }) + .unwrap_or_else(|| { + f.debug_tuple("SyntaxContextData").field(&zalsa_::AsId::as_id(&this)).finish() + }) + } + } +}; + +impl SyntaxContext { + const MAX_ID: u32 = salsa::Id::MAX_U32 - 1; + + pub fn is_root(self) -> bool { + (SyntaxContext::MAX_ID - Edition::LATEST as u32) <= self.into_u32() + && self.into_u32() <= (SyntaxContext::MAX_ID - Edition::Edition2015 as u32) } -} -impl SyntaxContextId { #[inline] pub fn remove_root_edition(&mut self) { if self.is_root() { @@ -68,75 +311,19 @@ impl SyntaxContextId { /// The root context, which is the parent of all other contexts. All [`FileId`]s have this context. pub const fn root(edition: Edition) -> Self { - SyntaxContextId(unsafe { InternId::new_unchecked(edition as u32) }) + let edition = edition as u32; + SyntaxContext( + salsa::Id::from_u32(SyntaxContext::MAX_ID - edition), + std::marker::PhantomData, + ) } - pub fn is_root(self) -> bool { - self.into_u32() <= Edition::LATEST as u32 - } - - /// Deconstruct a `SyntaxContextId` into a raw `u32`. - /// This should only be used for deserialization purposes for the proc-macro server. pub fn into_u32(self) -> u32 { self.0.as_u32() } - /// Constructs a `SyntaxContextId` from a raw `u32`. - /// This should only be used for serialization purposes for the proc-macro server. pub fn from_u32(u32: u32) -> Self { - Self(InternId::from(u32)) - } -} - -/// A syntax context describes a hierarchy tracking order of macro definitions. -#[derive(Copy, Clone, Hash, PartialEq, Eq)] -pub struct SyntaxContextData { - /// Invariant: Only [`SyntaxContextId::ROOT`] has a [`None`] outer expansion. - // FIXME: The None case needs to encode the context crate id. We can encode that as the MSB of - // MacroCallId is reserved anyways so we can do bit tagging here just fine. - // The bigger issue is that this will cause interning to now create completely separate chains - // per crate. Though that is likely not a problem as `MacroCallId`s are already crate calling dependent. - pub outer_expn: Option, - pub outer_transparency: Transparency, - pub edition: Edition, - pub parent: SyntaxContextId, - /// This context, but with all transparent and semi-transparent expansions filtered away. - pub opaque: SyntaxContextId, - /// This context, but with all transparent expansions filtered away. - pub opaque_and_semitransparent: SyntaxContextId, -} - -#[cfg(feature = "ra-salsa")] -impl InternValue for SyntaxContextData { - type Key = (SyntaxContextId, Option, Transparency, Edition); - - fn into_key(&self) -> Self::Key { - (self.parent, self.outer_expn, self.outer_transparency, self.edition) - } -} - -impl std::fmt::Debug for SyntaxContextData { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("SyntaxContextData") - .field("outer_expn", &self.outer_expn) - .field("outer_transparency", &self.outer_transparency) - .field("parent", &self.parent) - .field("opaque", &self.opaque) - .field("opaque_and_semitransparent", &self.opaque_and_semitransparent) - .finish() - } -} - -impl SyntaxContextData { - pub fn root(edition: Edition) -> Self { - SyntaxContextData { - outer_expn: None, - outer_transparency: Transparency::Opaque, - parent: SyntaxContextId::root(edition), - opaque: SyntaxContextId::root(edition), - opaque_and_semitransparent: SyntaxContextId::root(edition), - edition, - } + Self(salsa::Id::from_u32(u32), std::marker::PhantomData) } } @@ -167,3 +354,19 @@ impl Transparency { matches!(self, Self::Opaque) } } + +impl fmt::Display for SyntaxContext { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0.as_u32()) + } +} + +impl std::fmt::Debug for SyntaxContext { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if f.alternate() { + write!(f, "{}", self.0.as_u32()) + } else { + f.debug_tuple("SyntaxContext").field(&self.0).finish() + } + } +} diff --git a/src/tools/rust-analyzer/crates/span/src/lib.rs b/src/tools/rust-analyzer/crates/span/src/lib.rs index 8dc957350381c..7abdacee2b970 100644 --- a/src/tools/rust-analyzer/crates/span/src/lib.rs +++ b/src/tools/rust-analyzer/crates/span/src/lib.rs @@ -1,19 +1,19 @@ //! File and span related types. use std::fmt::{self, Write}; -#[cfg(feature = "ra-salsa")] -use ra_salsa::InternId; - mod ast_id; mod hygiene; mod map; pub use self::{ ast_id::{AstIdMap, AstIdNode, ErasedFileAstId, FileAstId}, - hygiene::{SyntaxContextData, SyntaxContextId, Transparency}, + hygiene::{SyntaxContext, Transparency}, map::{RealSpanMap, SpanMap}, }; +// Remove this +pub use self::hygiene::{SyntaxContext as SyntaxContextId, SyntaxContextUnderlyingData}; + pub use syntax::Edition; pub use text_size::{TextRange, TextSize}; pub use vfs::FileId; @@ -202,11 +202,23 @@ impl EditionedFileId { /// `MacroCallId`. // FIXME: Give this a better fitting name #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct HirFileId(u32); +pub struct HirFileId(salsa::Id); + +impl salsa::plumbing::AsId for HirFileId { + fn as_id(&self) -> salsa::Id { + self.0 + } +} + +impl salsa::plumbing::FromId for HirFileId { + fn from_id(id: salsa::Id) -> Self { + HirFileId(id) + } +} impl From for u32 { fn from(value: HirFileId) -> Self { - value.0 + value.0.as_u32() } } @@ -262,18 +274,20 @@ pub struct MacroFileId { /// `MacroCallId` identifies a particular macro invocation, like /// `println!("Hello, {}", world)`. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct MacroCallId(InternId); +pub struct MacroCallId(salsa::Id); -#[cfg(feature = "ra-salsa")] -impl ra_salsa::InternKey for MacroCallId { - fn from_intern_id(v: ra_salsa::InternId) -> Self { - MacroCallId(v) - } - fn as_intern_id(&self) -> ra_salsa::InternId { +impl salsa::plumbing::AsId for MacroCallId { + fn as_id(&self) -> salsa::Id { self.0 } } +impl salsa::plumbing::FromId for MacroCallId { + fn from_id(id: salsa::Id) -> Self { + MacroCallId(id) + } +} + impl MacroCallId { pub const MAX_ID: u32 = 0x7fff_ffff; @@ -307,16 +321,16 @@ impl From for HirFileId { #[allow(clippy::let_unit_value)] fn from(id: EditionedFileId) -> Self { assert!(id.as_u32() <= Self::MAX_HIR_FILE_ID, "FileId index {} is too large", id.as_u32()); - HirFileId(id.as_u32()) + HirFileId(salsa::Id::from_u32(id.0)) } } impl From for HirFileId { #[allow(clippy::let_unit_value)] fn from(MacroFileId { macro_call_id: MacroCallId(id) }: MacroFileId) -> Self { - let id = id.as_u32(); + let id: u32 = id.as_u32(); assert!(id <= Self::MAX_HIR_FILE_ID, "MacroCallId index {id} is too large"); - HirFileId(id | Self::MACRO_FILE_TAG_MASK) + HirFileId(salsa::Id::from_u32(id | Self::MACRO_FILE_TAG_MASK)) } } @@ -326,33 +340,37 @@ impl HirFileId { #[inline] pub fn is_macro(self) -> bool { - self.0 & Self::MACRO_FILE_TAG_MASK != 0 + self.0.as_u32() & Self::MACRO_FILE_TAG_MASK != 0 } #[inline] pub fn macro_file(self) -> Option { - match self.0 & Self::MACRO_FILE_TAG_MASK { + match self.0.as_u32() & Self::MACRO_FILE_TAG_MASK { 0 => None, _ => Some(MacroFileId { - macro_call_id: MacroCallId(InternId::from(self.0 ^ Self::MACRO_FILE_TAG_MASK)), + macro_call_id: MacroCallId(salsa::Id::from_u32( + self.0.as_u32() ^ Self::MACRO_FILE_TAG_MASK, + )), }), } } #[inline] pub fn file_id(self) -> Option { - match self.0 & Self::MACRO_FILE_TAG_MASK { - 0 => Some(EditionedFileId(self.0)), + match self.0.as_u32() & Self::MACRO_FILE_TAG_MASK { + 0 => Some(EditionedFileId(self.0.as_u32())), _ => None, } } #[inline] pub fn repr(self) -> HirFileIdRepr { - match self.0 & Self::MACRO_FILE_TAG_MASK { - 0 => HirFileIdRepr::FileId(EditionedFileId(self.0)), + match self.0.as_u32() & Self::MACRO_FILE_TAG_MASK { + 0 => HirFileIdRepr::FileId(EditionedFileId(self.0.as_u32())), _ => HirFileIdRepr::MacroFile(MacroFileId { - macro_call_id: MacroCallId(InternId::from(self.0 ^ Self::MACRO_FILE_TAG_MASK)), + macro_call_id: MacroCallId(salsa::Id::from_u32( + self.0.as_u32() ^ Self::MACRO_FILE_TAG_MASK, + )), }), } } @@ -369,72 +387,3 @@ impl std::fmt::Debug for TokenId { self.0.fmt(f) } } - -#[cfg(not(feature = "ra-salsa"))] -mod intern_id_proxy { - use std::fmt; - use std::num::NonZeroU32; - - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub(super) struct InternId { - value: NonZeroU32, - } - - impl InternId { - pub(super) const MAX: u32 = 0xFFFF_FF00; - - pub(super) const unsafe fn new_unchecked(value: u32) -> Self { - debug_assert!(value < InternId::MAX); - let value = unsafe { NonZeroU32::new_unchecked(value + 1) }; - InternId { value } - } - - pub(super) fn as_u32(self) -> u32 { - self.value.get() - 1 - } - - pub(super) fn as_usize(self) -> usize { - self.as_u32() as usize - } - } - - impl From for u32 { - fn from(raw: InternId) -> u32 { - raw.as_u32() - } - } - - impl From for usize { - fn from(raw: InternId) -> usize { - raw.as_usize() - } - } - - impl From for InternId { - fn from(id: u32) -> InternId { - assert!(id < InternId::MAX); - unsafe { InternId::new_unchecked(id) } - } - } - - impl From for InternId { - fn from(id: usize) -> InternId { - assert!(id < (InternId::MAX as usize)); - unsafe { InternId::new_unchecked(id as u32) } - } - } - - impl fmt::Debug for InternId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.as_usize().fmt(f) - } - } - - impl fmt::Display for InternId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.as_usize().fmt(f) - } - } -} -#[cfg(not(feature = "ra-salsa"))] -use intern_id_proxy::InternId; diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs index 37dfb87721c83..4b5c2ff4cf7d2 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs +++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs @@ -3,7 +3,8 @@ use std::{iter, mem, str::FromStr, sync}; use base_db::{ CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, CrateWorkspaceData, Dependency, - Env, FileChange, FileSet, LangCrateOrigin, SourceRoot, SourceRootDatabase, Version, VfsPath, + Env, FileChange, FileSet, LangCrateOrigin, RootQueryDb, SourceDatabase, SourceRoot, Version, + VfsPath, }; use cfg::CfgOptions; use hir_expand::{ @@ -28,7 +29,7 @@ use test_utils::{ pub const WORKSPACE: base_db::SourceRootId = base_db::SourceRootId(0); -pub trait WithFixture: Default + ExpandDatabase + SourceRootDatabase + 'static { +pub trait WithFixture: Default + ExpandDatabase + SourceDatabase + 'static { #[track_caller] fn with_single_file( #[rust_analyzer::rust_fixture] ra_fixture: &str, @@ -101,7 +102,7 @@ pub trait WithFixture: Default + ExpandDatabase + SourceRootDatabase + 'static { } fn test_crate(&self) -> CrateId { - let crate_graph = self.crate_graph(); + let crate_graph = RootQueryDb::crate_graph(self); let mut it = crate_graph.iter(); let mut res = it.next().unwrap(); while crate_graph[res].origin.is_lang() { @@ -111,7 +112,7 @@ pub trait WithFixture: Default + ExpandDatabase + SourceRootDatabase + 'static { } } -impl WithFixture for DB {} +impl WithFixture for DB {} pub struct ChangeFixture { pub file_position: Option<(EditionedFileId, RangeOrOffset)>, diff --git a/src/tools/rust-analyzer/xtask/src/tidy.rs b/src/tools/rust-analyzer/xtask/src/tidy.rs index 04952de731893..0e4208e096738 100644 --- a/src/tools/rust-analyzer/xtask/src/tidy.rs +++ b/src/tools/rust-analyzer/xtask/src/tidy.rs @@ -127,7 +127,7 @@ fn check_cargo_toml(path: &Path, text: String) { fn check_licenses(sh: &Shell) { let expected = " -(MIT OR Apache-2.0) AND Unicode-DFS-2016 +(MIT OR Apache-2.0) AND Unicode-3.0 0BSD OR MIT OR Apache-2.0 Apache-2.0 Apache-2.0 OR BSL-1.0 @@ -141,14 +141,13 @@ ISC MIT MIT / Apache-2.0 MIT OR Apache-2.0 -MIT OR Apache-2.0 OR Zlib MIT OR Zlib OR Apache-2.0 MIT/Apache-2.0 MPL-2.0 +Unicode-3.0 Unlicense OR MIT Unlicense/MIT Zlib -Zlib OR Apache-2.0 OR MIT " .lines() .filter(|it| !it.is_empty()) From 521fa18d5d6fd01e6cfb37d61471c26d0f6d3998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Florian?= <¨flodiebold@gmail.com¨> Date: Sun, 23 Feb 2025 18:40:31 +0100 Subject: [PATCH 0100/2248] Make GenericParamsCollector::type_or_consts not unnecessarily pub(crate) --- .../rust-analyzer/crates/hir-def/src/generics.rs | 14 +++++++++++++- .../crates/hir-def/src/item_tree/lower.rs | 11 ++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs index 80820193796de..ed5038c5aebd3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs @@ -10,6 +10,7 @@ use hir_expand::{ name::{AsName, Name}, ExpandResult, }; +use intern::sym; use la_arena::{Arena, RawIdx}; use stdx::{ impl_from, @@ -446,12 +447,23 @@ impl GenericParams { #[derive(Clone, Default)] pub(crate) struct GenericParamsCollector { - pub(crate) type_or_consts: Arena, + type_or_consts: Arena, lifetimes: Arena, where_predicates: Vec, } impl GenericParamsCollector { + pub(crate) fn fill_self_param(&mut self) { + self.type_or_consts.alloc( + TypeParamData { + name: Some(Name::new_symbol_root(sym::Self_.clone())), + default: None, + provenance: TypeParamProvenance::TraitSelf, + } + .into(), + ); + } + pub(crate) fn fill( &mut self, lower_ctx: &mut LowerCtx<'_>, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 71848845a84df..b0546d4f33fde 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -21,7 +21,7 @@ use triomphe::Arc; use crate::{ db::DefDatabase, - generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance}, + generics::{GenericParams, GenericParamsCollector}, item_tree::{ AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldParent, FieldsShape, FileItemTreeId, FnFlags, Function, GenericArgs, GenericItemSourceMapBuilder, @@ -881,14 +881,7 @@ impl<'a> Ctx<'a> { if let HasImplicitSelf::Yes(bounds) = has_implicit_self { // Traits and trait aliases get the Self type as an implicit first type parameter. - generics.type_or_consts.alloc( - TypeParamData { - name: Some(Name::new_symbol_root(sym::Self_.clone())), - default: None, - provenance: TypeParamProvenance::TraitSelf, - } - .into(), - ); + generics.fill_self_param(); // add super traits as bounds on Self // i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar` let bound_target = Either::Left(body_ctx.alloc_type_ref_desugared(TypeRef::Path( From 3a6d0ae0086baf30df19390700560c5a346dbe0e Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Tue, 11 Mar 2025 15:47:57 -0700 Subject: [PATCH 0101/2248] Move ByteStr compare and index traits to a separate module This parallels the layout of `core::str`. --- library/core/src/{bstr.rs => bstr/mod.rs} | 280 +--------------------- library/core/src/bstr/traits.rs | 275 +++++++++++++++++++++ 2 files changed, 282 insertions(+), 273 deletions(-) rename library/core/src/{bstr.rs => bstr/mod.rs} (54%) create mode 100644 library/core/src/bstr/traits.rs diff --git a/library/core/src/bstr.rs b/library/core/src/bstr/mod.rs similarity index 54% rename from library/core/src/bstr.rs rename to library/core/src/bstr/mod.rs index ae84fd8adb61c..c33dd244ad970 100644 --- a/library/core/src/bstr.rs +++ b/library/core/src/bstr/mod.rs @@ -1,12 +1,13 @@ //! The `ByteStr` type and trait implementations. +mod traits; + +#[unstable(feature = "bstr_internals", issue = "none")] +pub use traits::{impl_partial_eq, impl_partial_eq_n, impl_partial_eq_ord}; + use crate::borrow::{Borrow, BorrowMut}; -use crate::cmp::Ordering; -use crate::ops::{ - Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, - RangeTo, RangeToInclusive, -}; -use crate::{fmt, hash}; +use crate::fmt; +use crate::ops::{Deref, DerefMut, DerefPure}; /// A wrapper for `&[u8]` representing a human-readable string that's conventionally, but not /// always, UTF-8. @@ -295,273 +296,6 @@ impl<'a> Default for &'a mut ByteStr { // } // } -#[unstable(feature = "bstr", issue = "134915")] -impl hash::Hash for ByteStr { - #[inline] - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index for ByteStr { - type Output = u8; - - #[inline] - fn index(&self, idx: usize) -> &u8 { - &self.0[idx] - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, _: RangeFull) -> &ByteStr { - self - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: Range) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeInclusive) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeFrom) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeTo) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeToInclusive) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut for ByteStr { - #[inline] - fn index_mut(&mut self, idx: usize) -> &mut u8 { - &mut self.0[idx] - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut for ByteStr { - #[inline] - fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr { - self - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: Range) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeInclusive) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeFrom) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeTo) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeToInclusive) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Eq for ByteStr {} - -#[unstable(feature = "bstr", issue = "134915")] -impl PartialEq for ByteStr { - #[inline] - fn eq(&self, other: &ByteStr) -> bool { - &self.0 == &other.0 - } -} - -#[doc(hidden)] -#[macro_export] -#[unstable(feature = "bstr_internals", issue = "none")] -macro_rules! impl_partial_eq { - ($lhs:ty, $rhs:ty) => { - #[allow(unused_lifetimes)] - impl<'a> PartialEq<$rhs> for $lhs { - #[inline] - fn eq(&self, other: &$rhs) -> bool { - let other: &[u8] = other.as_ref(); - PartialEq::eq(self.as_bytes(), other) - } - } - - #[allow(unused_lifetimes)] - impl<'a> PartialEq<$lhs> for $rhs { - #[inline] - fn eq(&self, other: &$lhs) -> bool { - let this: &[u8] = self.as_ref(); - PartialEq::eq(this, other.as_bytes()) - } - } - }; -} - -#[doc(hidden)] -#[unstable(feature = "bstr_internals", issue = "none")] -pub use impl_partial_eq; - -#[doc(hidden)] -#[macro_export] -#[unstable(feature = "bstr_internals", issue = "none")] -macro_rules! impl_partial_eq_ord { - ($lhs:ty, $rhs:ty) => { - $crate::bstr::impl_partial_eq!($lhs, $rhs); - - #[allow(unused_lifetimes)] - #[unstable(feature = "bstr", issue = "134915")] - impl<'a> PartialOrd<$rhs> for $lhs { - #[inline] - fn partial_cmp(&self, other: &$rhs) -> Option { - let other: &[u8] = other.as_ref(); - PartialOrd::partial_cmp(self.as_bytes(), other) - } - } - - #[allow(unused_lifetimes)] - #[unstable(feature = "bstr", issue = "134915")] - impl<'a> PartialOrd<$lhs> for $rhs { - #[inline] - fn partial_cmp(&self, other: &$lhs) -> Option { - let this: &[u8] = self.as_ref(); - PartialOrd::partial_cmp(this, other.as_bytes()) - } - } - }; -} - -#[doc(hidden)] -#[unstable(feature = "bstr_internals", issue = "none")] -pub use impl_partial_eq_ord; - -#[doc(hidden)] -#[macro_export] -#[unstable(feature = "bstr_internals", issue = "none")] -macro_rules! impl_partial_eq_n { - ($lhs:ty, $rhs:ty) => { - #[allow(unused_lifetimes)] - #[unstable(feature = "bstr", issue = "134915")] - impl PartialEq<$rhs> for $lhs { - #[inline] - fn eq(&self, other: &$rhs) -> bool { - let other: &[u8] = other.as_ref(); - PartialEq::eq(self.as_bytes(), other) - } - } - - #[allow(unused_lifetimes)] - #[unstable(feature = "bstr", issue = "134915")] - impl PartialEq<$lhs> for $rhs { - #[inline] - fn eq(&self, other: &$lhs) -> bool { - let this: &[u8] = self.as_ref(); - PartialEq::eq(this, other.as_bytes()) - } - } - }; -} - -#[doc(hidden)] -#[unstable(feature = "bstr_internals", issue = "none")] -pub use impl_partial_eq_n; - -// PartialOrd with `[u8]` omitted to avoid inference failures -impl_partial_eq!(ByteStr, [u8]); -// PartialOrd with `&[u8]` omitted to avoid inference failures -impl_partial_eq!(ByteStr, &[u8]); -// PartialOrd with `str` omitted to avoid inference failures -impl_partial_eq!(ByteStr, str); -// PartialOrd with `&str` omitted to avoid inference failures -impl_partial_eq!(ByteStr, &str); -// PartialOrd with `[u8; N]` omitted to avoid inference failures -impl_partial_eq_n!(ByteStr, [u8; N]); -// PartialOrd with `[u8; N]` omitted to avoid inference failures -impl_partial_eq_n!(ByteStr, &[u8; N]); - -#[unstable(feature = "bstr", issue = "134915")] -impl Ord for ByteStr { - #[inline] - fn cmp(&self, other: &ByteStr) -> Ordering { - Ord::cmp(&self.0, &other.0) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl PartialOrd for ByteStr { - #[inline] - fn partial_cmp(&self, other: &ByteStr) -> Option { - PartialOrd::partial_cmp(&self.0, &other.0) - } -} - #[unstable(feature = "bstr", issue = "134915")] impl<'a> TryFrom<&'a ByteStr> for &'a str { type Error = crate::str::Utf8Error; diff --git a/library/core/src/bstr/traits.rs b/library/core/src/bstr/traits.rs new file mode 100644 index 0000000000000..14b862cbb3ccf --- /dev/null +++ b/library/core/src/bstr/traits.rs @@ -0,0 +1,275 @@ +//! Trait implementations for `ByteStr`. + +use crate::bstr::ByteStr; +use crate::cmp::Ordering; +use crate::hash; +use crate::ops::{ + Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, +}; + +#[unstable(feature = "bstr", issue = "134915")] +impl Ord for ByteStr { + #[inline] + fn cmp(&self, other: &ByteStr) -> Ordering { + Ord::cmp(&self.0, &other.0) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl PartialOrd for ByteStr { + #[inline] + fn partial_cmp(&self, other: &ByteStr) -> Option { + PartialOrd::partial_cmp(&self.0, &other.0) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl PartialEq for ByteStr { + #[inline] + fn eq(&self, other: &ByteStr) -> bool { + &self.0 == &other.0 + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Eq for ByteStr {} + +#[unstable(feature = "bstr", issue = "134915")] +impl hash::Hash for ByteStr { + #[inline] + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +#[doc(hidden)] +#[macro_export] +#[unstable(feature = "bstr_internals", issue = "none")] +macro_rules! impl_partial_eq { + ($lhs:ty, $rhs:ty) => { + #[allow(unused_lifetimes)] + impl<'a> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + let other: &[u8] = other.as_ref(); + PartialEq::eq(self.as_bytes(), other) + } + } + + #[allow(unused_lifetimes)] + impl<'a> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + let this: &[u8] = self.as_ref(); + PartialEq::eq(this, other.as_bytes()) + } + } + }; +} + +#[doc(hidden)] +#[unstable(feature = "bstr_internals", issue = "none")] +pub use impl_partial_eq; + +#[doc(hidden)] +#[macro_export] +#[unstable(feature = "bstr_internals", issue = "none")] +macro_rules! impl_partial_eq_ord { + ($lhs:ty, $rhs:ty) => { + $crate::bstr::impl_partial_eq!($lhs, $rhs); + + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<'a> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option { + let other: &[u8] = other.as_ref(); + PartialOrd::partial_cmp(self.as_bytes(), other) + } + } + + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<'a> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option { + let this: &[u8] = self.as_ref(); + PartialOrd::partial_cmp(this, other.as_bytes()) + } + } + }; +} + +#[doc(hidden)] +#[unstable(feature = "bstr_internals", issue = "none")] +pub use impl_partial_eq_ord; + +#[doc(hidden)] +#[macro_export] +#[unstable(feature = "bstr_internals", issue = "none")] +macro_rules! impl_partial_eq_n { + ($lhs:ty, $rhs:ty) => { + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + let other: &[u8] = other.as_ref(); + PartialEq::eq(self.as_bytes(), other) + } + } + + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + let this: &[u8] = self.as_ref(); + PartialEq::eq(this, other.as_bytes()) + } + } + }; +} + +#[doc(hidden)] +#[unstable(feature = "bstr_internals", issue = "none")] +pub use impl_partial_eq_n; + +// PartialOrd with `[u8]` omitted to avoid inference failures +impl_partial_eq!(ByteStr, [u8]); +// PartialOrd with `&[u8]` omitted to avoid inference failures +impl_partial_eq!(ByteStr, &[u8]); +// PartialOrd with `str` omitted to avoid inference failures +impl_partial_eq!(ByteStr, str); +// PartialOrd with `&str` omitted to avoid inference failures +impl_partial_eq!(ByteStr, &str); +// PartialOrd with `[u8; N]` omitted to avoid inference failures +impl_partial_eq_n!(ByteStr, [u8; N]); +// PartialOrd with `[u8; N]` omitted to avoid inference failures +impl_partial_eq_n!(ByteStr, &[u8; N]); + +#[unstable(feature = "bstr", issue = "134915")] +impl Index for ByteStr { + type Output = u8; + + #[inline] + fn index(&self, idx: usize) -> &u8 { + &self.0[idx] + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, _: RangeFull) -> &ByteStr { + self + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: Range) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeInclusive) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeFrom) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeTo) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeToInclusive) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut for ByteStr { + #[inline] + fn index_mut(&mut self, idx: usize) -> &mut u8 { + &mut self.0[idx] + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut for ByteStr { + #[inline] + fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr { + self + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut> for ByteStr { + #[inline] + fn index_mut(&mut self, r: Range) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeInclusive) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeFrom) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeTo) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeToInclusive) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} From 9d379e11a6e9d8b491ce7143600495ae101e8c69 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Tue, 11 Mar 2025 17:37:36 -0700 Subject: [PATCH 0102/2248] Implement SliceIndex for ByteStr --- library/core/src/bstr/mod.rs | 7 + library/core/src/bstr/traits.rs | 178 +++++++++--------- tests/ui/indexing/index-help.stderr | 5 +- .../indexing/indexing-requires-a-uint.stderr | 5 +- tests/ui/integral-indexing.stderr | 40 ++-- tests/ui/on-unimplemented/slice-index.stderr | 6 +- tests/ui/str/str-idx.stderr | 21 ++- tests/ui/str/str-mut-idx.stderr | 19 +- .../suggest-dereferencing-index.stderr | 7 +- 9 files changed, 158 insertions(+), 130 deletions(-) diff --git a/library/core/src/bstr/mod.rs b/library/core/src/bstr/mod.rs index c33dd244ad970..c8d0c701ba8b7 100644 --- a/library/core/src/bstr/mod.rs +++ b/library/core/src/bstr/mod.rs @@ -92,6 +92,13 @@ impl ByteStr { pub fn as_bytes(&self) -> &[u8] { &self.0 } + + #[doc(hidden)] + #[unstable(feature = "bstr_internals", issue = "none")] + #[inline] + pub fn as_bytes_mut(&mut self) -> &mut [u8] { + &mut self.0 + } } #[unstable(feature = "bstr", issue = "134915")] diff --git a/library/core/src/bstr/traits.rs b/library/core/src/bstr/traits.rs index 14b862cbb3ccf..ff46bb13ba4eb 100644 --- a/library/core/src/bstr/traits.rs +++ b/library/core/src/bstr/traits.rs @@ -2,10 +2,8 @@ use crate::bstr::ByteStr; use crate::cmp::Ordering; -use crate::hash; -use crate::ops::{ - Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, -}; +use crate::slice::SliceIndex; +use crate::{hash, ops, range}; #[unstable(feature = "bstr", issue = "134915")] impl Ord for ByteStr { @@ -149,127 +147,131 @@ impl_partial_eq_n!(ByteStr, [u8; N]); impl_partial_eq_n!(ByteStr, &[u8; N]); #[unstable(feature = "bstr", issue = "134915")] -impl Index for ByteStr { - type Output = u8; +impl ops::Index for ByteStr +where + I: SliceIndex, +{ + type Output = I::Output; #[inline] - fn index(&self, idx: usize) -> &u8 { - &self.0[idx] + fn index(&self, index: I) -> &I::Output { + index.index(self) } } #[unstable(feature = "bstr", issue = "134915")] -impl Index for ByteStr { - type Output = ByteStr; - +impl ops::IndexMut for ByteStr +where + I: SliceIndex, +{ #[inline] - fn index(&self, _: RangeFull) -> &ByteStr { - self + fn index_mut(&mut self, index: I) -> &mut I::Output { + index.index_mut(self) } } #[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { +unsafe impl SliceIndex for ops::RangeFull { type Output = ByteStr; - #[inline] - fn index(&self, r: Range) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) + fn get(self, slice: &ByteStr) -> Option<&Self::Output> { + Some(slice) } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - #[inline] - fn index(&self, r: RangeInclusive) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) + fn get_mut(self, slice: &mut ByteStr) -> Option<&mut Self::Output> { + Some(slice) } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - #[inline] - fn index(&self, r: RangeFrom) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) + unsafe fn get_unchecked(self, slice: *const ByteStr) -> *const Self::Output { + slice } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - #[inline] - fn index(&self, r: RangeTo) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) + unsafe fn get_unchecked_mut(self, slice: *mut ByteStr) -> *mut Self::Output { + slice } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - #[inline] - fn index(&self, r: RangeToInclusive) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) + fn index(self, slice: &ByteStr) -> &Self::Output { + slice } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut for ByteStr { #[inline] - fn index_mut(&mut self, idx: usize) -> &mut u8 { - &mut self.0[idx] + fn index_mut(self, slice: &mut ByteStr) -> &mut Self::Output { + slice } } #[unstable(feature = "bstr", issue = "134915")] -impl IndexMut for ByteStr { +unsafe impl SliceIndex for usize { + type Output = u8; #[inline] - fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr { - self + fn get(self, slice: &ByteStr) -> Option<&Self::Output> { + self.get(slice.as_bytes()) } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { #[inline] - fn index_mut(&mut self, r: Range) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) + fn get_mut(self, slice: &mut ByteStr) -> Option<&mut Self::Output> { + self.get_mut(slice.as_bytes_mut()) } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { #[inline] - fn index_mut(&mut self, r: RangeInclusive) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) + unsafe fn get_unchecked(self, slice: *const ByteStr) -> *const Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { self.get_unchecked(slice as *const [u8]) } } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { #[inline] - fn index_mut(&mut self, r: RangeFrom) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) + unsafe fn get_unchecked_mut(self, slice: *mut ByteStr) -> *mut Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { self.get_unchecked_mut(slice as *mut [u8]) } } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { #[inline] - fn index_mut(&mut self, r: RangeTo) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) + fn index(self, slice: &ByteStr) -> &Self::Output { + self.index(slice.as_bytes()) } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { #[inline] - fn index_mut(&mut self, r: RangeToInclusive) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) + fn index_mut(self, slice: &mut ByteStr) -> &mut Self::Output { + self.index_mut(slice.as_bytes_mut()) } } + +macro_rules! impl_slice_index { + ($index:ty) => { + #[unstable(feature = "bstr", issue = "134915")] + unsafe impl SliceIndex for $index { + type Output = ByteStr; + #[inline] + fn get(self, slice: &ByteStr) -> Option<&Self::Output> { + self.get(slice.as_bytes()).map(ByteStr::from_bytes) + } + #[inline] + fn get_mut(self, slice: &mut ByteStr) -> Option<&mut Self::Output> { + self.get_mut(slice.as_bytes_mut()).map(ByteStr::from_bytes_mut) + } + #[inline] + unsafe fn get_unchecked(self, slice: *const ByteStr) -> *const Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { self.get_unchecked(slice as *const [u8]) as *const ByteStr } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut ByteStr) -> *mut Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { self.get_unchecked_mut(slice as *mut [u8]) as *mut ByteStr } + } + #[inline] + fn index(self, slice: &ByteStr) -> &Self::Output { + ByteStr::from_bytes(self.index(slice.as_bytes())) + } + #[inline] + fn index_mut(self, slice: &mut ByteStr) -> &mut Self::Output { + ByteStr::from_bytes_mut(self.index_mut(slice.as_bytes_mut())) + } + } + }; +} + +impl_slice_index!(ops::IndexRange); +impl_slice_index!(ops::Range); +impl_slice_index!(range::Range); +impl_slice_index!(ops::RangeTo); +impl_slice_index!(ops::RangeFrom); +impl_slice_index!(range::RangeFrom); +impl_slice_index!(ops::RangeInclusive); +impl_slice_index!(range::RangeInclusive); +impl_slice_index!(ops::RangeToInclusive); +impl_slice_index!((ops::Bound, ops::Bound)); diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr index 1974e13eabcee..ac79e3f12bd03 100644 --- a/tests/ui/indexing/index-help.stderr +++ b/tests/ui/indexing/index-help.stderr @@ -5,8 +5,9 @@ LL | x[0i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `Vec<{integer}>` to implement `Index` error: aborting due to 1 previous error diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr index 5c60a30946d37..62a1ca3d0573c 100644 --- a/tests/ui/indexing/indexing-requires-a-uint.stderr +++ b/tests/ui/indexing/indexing-requires-a-uint.stderr @@ -5,8 +5,9 @@ LL | [0][0u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `u8` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[{integer}]` to implement `Index` = note: 1 redundant requirement hidden = note: required for `[{integer}; 1]` to implement `Index` diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr index e7a45c2c88dd9..26253e078cb40 100644 --- a/tests/ui/integral-indexing.stderr +++ b/tests/ui/integral-indexing.stderr @@ -5,8 +5,9 @@ LL | v[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `u8` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `i8` @@ -16,8 +17,9 @@ LL | v[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i8` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `u32` @@ -27,8 +29,9 @@ LL | v[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `u32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `i32` @@ -38,8 +41,9 @@ LL | v[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `Vec` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `u8` @@ -49,8 +53,9 @@ LL | s.as_bytes()[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `u8` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `i8` @@ -60,8 +65,9 @@ LL | s.as_bytes()[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i8` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `u32` @@ -71,8 +77,9 @@ LL | s.as_bytes()[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `u32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `i32` @@ -82,8 +89,9 @@ LL | s.as_bytes()[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[u8]` to implement `Index` error: aborting due to 8 previous errors diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr index 0a9ebe3f088e0..e011826bc8f7b 100644 --- a/tests/ui/on-unimplemented/slice-index.stderr +++ b/tests/ui/on-unimplemented/slice-index.stderr @@ -5,8 +5,9 @@ LL | x[1i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[i32]` to implement `Index` error[E0277]: the type `[i32]` cannot be indexed by `RangeTo` @@ -17,6 +18,7 @@ LL | x[..1i32]; | = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo` = help: the following other types implement trait `SliceIndex`: + `RangeTo` implements `SliceIndex` `RangeTo` implements `SliceIndex<[T]>` `RangeTo` implements `SliceIndex` = note: required for `[i32]` to implement `Index>` diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr index bedbbd9cb5029..60cae7e84e373 100644 --- a/tests/ui/str/str-idx.stderr +++ b/tests/ui/str/str-idx.stderr @@ -4,11 +4,12 @@ error[E0277]: the type `str` cannot be indexed by `{integer}` LL | let _: u8 = s[4]; | ^ string indices are ranges of `usize` | + = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex` is not implemented for `{integer}` - but trait `SliceIndex<[_]>` is implemented for `usize` - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `str` to implement `Index<{integer}>` error[E0277]: the type `str` cannot be indexed by `{integer}` @@ -19,11 +20,12 @@ LL | let _ = s.get(4); | | | required by a bound introduced by this call | + = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex` is not implemented for `{integer}` - but trait `SliceIndex<[_]>` is implemented for `usize` - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` note: required by a bound in `core::str::::get` --> $SRC_DIR/core/src/str/mod.rs:LL:COL @@ -35,11 +37,12 @@ LL | let _ = s.get_unchecked(4); | | | required by a bound introduced by this call | + = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex` is not implemented for `{integer}` - but trait `SliceIndex<[_]>` is implemented for `usize` - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` note: required by a bound in `core::str::::get_unchecked` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr index f09a4c329e5d8..4e3fe126ed838 100644 --- a/tests/ui/str/str-mut-idx.stderr +++ b/tests/ui/str/str-mut-idx.stderr @@ -31,8 +31,9 @@ LL | s[1usize] = bot(); | ^^^^^^ string indices are ranges of `usize` | = help: the trait `SliceIndex` is not implemented for `usize` - but trait `SliceIndex<[_]>` is implemented for it - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `str` to implement `Index` error[E0277]: the type `str` cannot be indexed by `{integer}` @@ -43,11 +44,12 @@ LL | s.get_mut(1); | | | required by a bound introduced by this call | + = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex` is not implemented for `{integer}` - but trait `SliceIndex<[_]>` is implemented for `usize` - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` note: required by a bound in `core::str::::get_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL @@ -59,11 +61,12 @@ LL | s.get_unchecked_mut(1); | | | required by a bound introduced by this call | + = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex` is not implemented for `{integer}` - but trait `SliceIndex<[_]>` is implemented for `usize` - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` note: required by a bound in `core::str::::get_unchecked_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr index 0335d8eafde4b..937f32677a6c8 100644 --- a/tests/ui/suggestions/suggest-dereferencing-index.stderr +++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr @@ -4,9 +4,10 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `&usize` LL | let one_item_please: i32 = [1, 2, 3][i]; | ^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&_` - but it is implemented for `_` - = help: for that trait implementation, expected `usize`, found `&usize` + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[{integer}]` to implement `Index<&usize>` = note: 1 redundant requirement hidden = note: required for `[{integer}; 3]` to implement `Index<&usize>` From 7989568b8edd6531ed062614b71c327677b581ba Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 12 Mar 2025 08:03:54 +0100 Subject: [PATCH 0103/2248] 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 3dad35bc4ce47..5544aee9eaf16 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -595,25 +595,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 1066ee09ed106a19cd902dfb1d4d44fdf472cb56 Mon Sep 17 00:00:00 2001 From: yanglsh Date: Wed, 12 Mar 2025 21:55:31 +0800 Subject: [PATCH 0104/2248] fix: `redundant_clone` FP on enum cast --- clippy_utils/src/mir/mod.rs | 2 +- tests/ui/redundant_clone.fixed | 15 +++++++++++++++ tests/ui/redundant_clone.rs | 15 +++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/clippy_utils/src/mir/mod.rs b/clippy_utils/src/mir/mod.rs index ffcfcd240ea5a..9ba644fdd20ec 100644 --- a/clippy_utils/src/mir/mod.rs +++ b/clippy_utils/src/mir/mod.rs @@ -76,7 +76,7 @@ impl<'tcx> Visitor<'tcx> for V<'_> { } if matches!( ctx, - PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move | NonMutatingUseContext::Inspect) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) ) { self.results[i].local_consume_or_mutate_locs.push(loc); diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index 23c00b34a00a8..7d5195b62175b 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -259,3 +259,18 @@ fn false_negative_5707() { let _z = x.clone(); // pr 7346 can't lint on `x` drop(y); } + +mod issue10074 { + #[derive(Debug, Clone)] + enum MyEnum { + A = 1, + } + + fn false_positive_on_as() { + let e = MyEnum::A; + let v = e.clone() as u16; + + println!("{e:?}"); + println!("{v}"); + } +} diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index f9fe8ba0236d0..0ea1024a5681a 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -259,3 +259,18 @@ fn false_negative_5707() { let _z = x.clone(); // pr 7346 can't lint on `x` drop(y); } + +mod issue10074 { + #[derive(Debug, Clone)] + enum MyEnum { + A = 1, + } + + fn false_positive_on_as() { + let e = MyEnum::A; + let v = e.clone() as u16; + + println!("{e:?}"); + println!("{v}"); + } +} From 5c7292336873999ae979cc17c9f251bee14d6cf8 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Thu, 2 Jan 2025 01:45:32 +0200 Subject: [PATCH 0105/2248] Salsify the crate graph I.e. make it not one giant input but multiple, for incrementality and decreased memory usage for Salsa 3 reasons. --- src/tools/rust-analyzer/Cargo.lock | 1 + .../crates/base-db/src/change.rs | 21 +- .../rust-analyzer/crates/base-db/src/input.rs | 510 +++++++--- .../rust-analyzer/crates/base-db/src/lib.rs | 86 +- src/tools/rust-analyzer/crates/cfg/src/lib.rs | 12 + .../rust-analyzer/crates/hir-def/src/attr.rs | 7 +- .../rust-analyzer/crates/hir-def/src/data.rs | 18 +- .../crates/hir-def/src/data/adt.rs | 12 +- .../rust-analyzer/crates/hir-def/src/db.rs | 41 +- .../crates/hir-def/src/expander.rs | 6 +- .../crates/hir-def/src/expr_store/body.rs | 3 +- .../crates/hir-def/src/expr_store/lower.rs | 19 +- .../crates/hir-def/src/expr_store/tests.rs | 4 +- .../crates/hir-def/src/find_path.rs | 20 +- .../crates/hir-def/src/generics.rs | 21 +- .../crates/hir-def/src/import_map.rs | 29 +- .../crates/hir-def/src/item_scope.rs | 4 +- .../crates/hir-def/src/item_tree.rs | 6 +- .../crates/hir-def/src/lang_item.rs | 31 +- .../rust-analyzer/crates/hir-def/src/lib.rs | 47 +- .../hir-def/src/macro_expansion_tests/mod.rs | 4 + .../crates/hir-def/src/nameres.rs | 110 +- .../hir-def/src/nameres/attr_resolution.rs | 10 +- .../crates/hir-def/src/nameres/collector.rs | 162 ++- .../hir-def/src/nameres/path_resolution.rs | 60 +- .../hir-def/src/nameres/tests/incremental.rs | 75 +- .../hir-def/src/nameres/tests/macros.rs | 4 +- .../crates/hir-def/src/pretty.rs | 11 +- .../crates/hir-def/src/resolver.rs | 102 +- .../rust-analyzer/crates/hir-def/src/src.rs | 4 +- .../crates/hir-def/src/test_db.rs | 28 +- .../crates/hir-expand/src/attrs.rs | 7 +- .../crates/hir-expand/src/builtin/fn_macro.rs | 8 +- .../crates/hir-expand/src/cfg_process.rs | 16 +- .../crates/hir-expand/src/change.rs | 23 +- .../rust-analyzer/crates/hir-expand/src/db.rs | 11 +- .../crates/hir-expand/src/declarative.rs | 10 +- .../crates/hir-expand/src/eager.rs | 10 +- .../crates/hir-expand/src/lib.rs | 12 +- .../crates/hir-expand/src/mod_path.rs | 6 +- .../crates/hir-expand/src/name.rs | 2 +- .../src/prettify_macro_expansion_.rs | 9 +- .../crates/hir-expand/src/proc_macro.rs | 159 ++- .../crates/hir-ty/src/chalk_db.rs | 22 +- .../crates/hir-ty/src/consteval.rs | 6 +- .../crates/hir-ty/src/consteval/tests.rs | 5 +- .../rust-analyzer/crates/hir-ty/src/db.rs | 43 +- .../hir-ty/src/diagnostics/decl_check.rs | 2 +- .../crates/hir-ty/src/diagnostics/expr.rs | 4 +- .../hir-ty/src/diagnostics/unsafe_check.rs | 2 +- .../crates/hir-ty/src/display.rs | 16 +- .../crates/hir-ty/src/infer/closure.rs | 6 +- .../crates/hir-ty/src/layout/target.rs | 6 +- .../rust-analyzer/crates/hir-ty/src/lower.rs | 11 +- .../crates/hir-ty/src/method_resolution.rs | 29 +- .../rust-analyzer/crates/hir-ty/src/mir.rs | 4 +- .../crates/hir-ty/src/mir/eval.rs | 6 +- .../crates/hir-ty/src/mir/eval/shim.rs | 2 +- .../crates/hir-ty/src/mir/lower.rs | 8 +- .../crates/hir-ty/src/test_db.rs | 16 +- .../rust-analyzer/crates/hir-ty/src/tests.rs | 8 +- .../rust-analyzer/crates/hir-ty/src/traits.rs | 16 +- .../rust-analyzer/crates/hir-ty/src/utils.rs | 7 +- .../rust-analyzer/crates/hir/src/from_id.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 70 +- .../rust-analyzer/crates/hir/src/semantics.rs | 2 +- .../rust-analyzer/crates/hir/src/symbols.rs | 5 +- .../ide-assists/src/handlers/inline_call.rs | 6 +- .../crates/ide-db/src/apply_change.rs | 8 +- .../crates/ide-db/src/famous_defs.rs | 5 +- .../rust-analyzer/crates/ide-db/src/lib.rs | 27 +- .../crates/ide-db/src/prime_caches.rs | 36 +- .../rust-analyzer/crates/ide-db/src/search.rs | 10 +- .../ide-db/src/test_data/test_doc_alias.txt | 4 +- .../test_symbol_index_collection.txt | 20 +- .../crates/ide-diagnostics/src/lib.rs | 6 +- .../crates/ide-ssr/src/matching.rs | 10 +- .../rust-analyzer/crates/ide/src/doc_links.rs | 4 +- .../crates/ide/src/expand_macro.rs | 8 +- .../crates/ide/src/fetch_crates.rs | 21 +- .../crates/ide/src/hover/render.rs | 4 +- .../crates/ide/src/hover/tests.rs | 2 +- .../crates/ide/src/inlay_hints/bind_pat.rs | 8 +- src/tools/rust-analyzer/crates/ide/src/lib.rs | 44 +- .../crates/ide/src/parent_module.rs | 4 +- .../rust-analyzer/crates/ide/src/runnables.rs | 5 +- .../crates/ide/src/static_index.rs | 4 +- .../rust-analyzer/crates/ide/src/status.rs | 23 +- .../crates/ide/src/test_explorer.rs | 37 +- .../crates/ide/src/view_crate_graph.rs | 60 +- .../rust-analyzer/crates/intern/src/symbol.rs | 14 +- .../crates/load-cargo/src/lib.rs | 31 +- .../crates/proc-macro-api/src/lib.rs | 10 +- .../crates/proc-macro-srv/src/tests/mod.rs | 130 +-- .../crates/project-model/src/project_json.rs | 2 +- .../crates/project-model/src/tests.rs | 12 +- .../crates/project-model/src/workspace.rs | 184 ++-- .../cargo_hello_world_project_model.txt | 448 ++++---- ...project_model_with_selective_overrides.txt | 448 ++++---- ..._project_model_with_wildcard_overrides.txt | 448 ++++---- .../output/rust_project_cfg_groups.txt | 962 ++++++++++-------- ...rust_project_hello_world_project_model.txt | 832 ++++++++------- .../crates/rust-analyzer/src/global_state.rs | 6 +- .../crates/rust-analyzer/src/main_loop.rs | 20 +- .../crates/rust-analyzer/src/reload.rs | 95 +- .../crates/rust-analyzer/src/target_spec.rs | 4 +- .../crates/test-fixture/Cargo.toml | 1 + .../crates/test-fixture/src/lib.rs | 98 +- 108 files changed, 3629 insertions(+), 2511 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index efd7362594c21..00da1c973dc0f 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -2418,6 +2418,7 @@ dependencies = [ "span", "stdx", "test-utils", + "triomphe", "tt", ] diff --git a/src/tools/rust-analyzer/crates/base-db/src/change.rs b/src/tools/rust-analyzer/crates/base-db/src/change.rs index 90413a573aef3..1f19556a766c2 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/change.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/change.rs @@ -3,20 +3,18 @@ use std::fmt; -use rustc_hash::FxHashMap; use salsa::Durability; use triomphe::Arc; use vfs::FileId; -use crate::{CrateGraph, CrateId, CrateWorkspaceData, RootQueryDb, SourceRoot, SourceRootId}; +use crate::{CrateGraphBuilder, CratesIdMap, RootQueryDb, SourceRoot, SourceRootId}; /// Encapsulate a bunch of raw `.set` calls on the database. #[derive(Default)] pub struct FileChange { pub roots: Option>, pub files_changed: Vec<(FileId, Option)>, - pub crate_graph: Option, - pub ws_data: Option>>, + pub crate_graph: Option, } impl fmt::Debug for FileChange { @@ -48,15 +46,11 @@ impl FileChange { self.files_changed.push((file_id, new_text)) } - pub fn set_crate_graph(&mut self, graph: CrateGraph) { + pub fn set_crate_graph(&mut self, graph: CrateGraphBuilder) { self.crate_graph = Some(graph); } - pub fn set_ws_data(&mut self, data: FxHashMap>) { - self.ws_data = Some(data); - } - - pub fn apply(self, db: &mut dyn RootQueryDb) { + pub fn apply(self, db: &mut dyn RootQueryDb) -> Option { let _p = tracing::info_span!("FileChange::apply").entered(); if let Some(roots) = self.roots { for (idx, root) in roots.into_iter().enumerate() { @@ -79,12 +73,11 @@ impl FileChange { let text = text.unwrap_or_default(); db.set_file_text_with_durability(file_id, &text, durability) } + if let Some(crate_graph) = self.crate_graph { - db.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH); - } - if let Some(data) = self.ws_data { - db.set_crate_workspace_data_with_durability(Arc::new(data), Durability::HIGH); + return Some(crate_graph.set_in_db(db)); } + None } } diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index bd08387b58219..c4e64b372f36a 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -6,17 +6,23 @@ //! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how //! actual IO is done and lowered to input. +use std::hash::BuildHasherDefault; use std::{fmt, mem, ops}; -use cfg::CfgOptions; +use cfg::{CfgOptions, HashableCfgOptions}; +use dashmap::mapref::entry::Entry; +use dashmap::DashMap; use intern::Symbol; use la_arena::{Arena, Idx, RawIdx}; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; +use salsa::{Durability, Setter}; use span::{Edition, EditionedFileId}; use triomphe::Arc; use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath}; -pub type ProcMacroPaths = FxHashMap>; +use crate::{CrateWorkspaceData, RootQueryDb}; + +pub type ProcMacroPaths = FxHashMap>; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct SourceRootId(pub u32); @@ -64,30 +70,31 @@ impl SourceRoot { } } -/// `CrateGraph` is a bit of information which turns a set of text files into a -/// number of Rust crates. -/// -/// Each crate is defined by the `FileId` of its root module, the set of enabled -/// `cfg` flags and the set of dependencies. -/// -/// Note that, due to cfg's, there might be several crates for a single `FileId`! -/// -/// For the purposes of analysis, a crate does not have a name. Instead, names -/// are specified on dependency edges. That is, a crate might be known under -/// different names in different dependent crates. -/// -/// Note that `CrateGraph` is build-system agnostic: it's a concept of the Rust -/// language proper, not a concept of the build system. In practice, we get -/// `CrateGraph` by lowering `cargo metadata` output. -/// -/// `CrateGraph` is `!Serialize` by design, see -/// -#[derive(Clone, Default)] -pub struct CrateGraph { - arena: Arena, +#[derive(Default, Clone)] +pub struct CrateGraphBuilder { + arena: Arena, } -impl fmt::Debug for CrateGraph { +pub type CrateBuilderId = Idx; + +impl ops::Index for CrateGraphBuilder { + type Output = CrateBuilder; + + fn index(&self, index: CrateBuilderId) -> &Self::Output { + &self.arena[index] + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct CrateBuilder { + pub basic: CrateDataBuilder, + pub extra: ExtraCrateData, + pub cfg_options: Arc, + pub env: Env, + ws_data: Arc, +} + +impl fmt::Debug for CrateGraphBuilder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_map() .entries(self.arena.iter().map(|(id, data)| (u32::from(id.into_raw()), data))) @@ -95,8 +102,6 @@ impl fmt::Debug for CrateGraph { } } -pub type CrateId = Idx; - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CrateName(Symbol); @@ -272,28 +277,34 @@ impl ReleaseChannel { } } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct CrateData { +/// The crate data from which we derive the `Crate`. +/// +/// We want this to contain as little data as possible, because if it contains dependencies and +/// something changes, this crate and all of its dependencies ids are invalidated, which causes +/// pretty much everything to be recomputed. If the crate id is not invalidated, only this crate's +/// information needs to be recomputed. +/// +/// *Most* different crates have different root files (actually, pretty much all of them). +/// Still, it is possible to have crates distinguished by other factors (e.g. dependencies). +/// So we store only the root file - unless we find that this crate has the same root file as +/// another crate, in which case we store all data for one of them (if one is a dependency of +/// the other, we store for it, because it has more dependencies to be invalidated). +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct UniqueCrateData { + root_file_id: FileId, + disambiguator: Option>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct CrateData { pub root_file_id: FileId, pub edition: Edition, - pub version: Option, - /// A name used in the package's project declaration: for Cargo projects, - /// its `[package].name` can be different for other project types or even - /// absent (a dummy crate for the code snippet, for example). - /// - /// For purposes of analysis, crates are anonymous (only names in - /// `Dependency` matters), this name should only be used for UI. - pub display_name: Option, - pub cfg_options: Arc, - /// The cfg options that could be used by the crate - pub potential_cfg_options: Option>, - pub env: Env, /// The dependencies of this crate. /// /// Note that this may contain more dependencies than the crate actually uses. /// A common example is the test crate which is included but only actually is active when /// declared in source via `extern crate test`. - pub dependencies: Vec, + pub dependencies: Vec>, pub origin: CrateOrigin, pub is_proc_macro: bool, /// The working directory to run proc-macros in. This is the workspace root of the cargo workspace @@ -301,6 +312,23 @@ pub struct CrateData { pub proc_macro_cwd: Option, } +pub type CrateDataBuilder = CrateData; +pub type BuiltCrateData = CrateData; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ExtraCrateData { + pub version: Option, + /// A name used in the package's project declaration: for Cargo projects, + /// its `[package].name` can be different for other project types or even + /// absent (a dummy crate for the code snippet, for example). + /// + /// For purposes of analysis, crates are anonymous (only names in + /// `Dependency` matters), this name should only be used for UI. + pub display_name: Option, + /// The cfg options that could be used by the crate + pub potential_cfg_options: Option, +} + #[derive(Default, Clone, PartialEq, Eq)] pub struct Env { entries: FxHashMap, @@ -326,22 +354,32 @@ impl fmt::Debug for Env { } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Dependency { - pub crate_id: CrateId, +pub struct Dependency { + pub crate_id: Id, pub name: CrateName, prelude: bool, sysroot: bool, } -impl Dependency { - pub fn new(name: CrateName, crate_id: CrateId) -> Self { +pub type DependencyBuilder = Dependency; +pub type BuiltDependency = Dependency; + +impl DependencyBuilder { + pub fn new(name: CrateName, crate_id: CrateBuilderId) -> Self { Self { name, crate_id, prelude: true, sysroot: false } } - pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool, sysroot: bool) -> Self { + pub fn with_prelude( + name: CrateName, + crate_id: CrateBuilderId, + prelude: bool, + sysroot: bool, + ) -> Self { Self { name, crate_id, prelude, sysroot } } +} +impl BuiltDependency { /// Whether this dependency is to be added to the depending crate's extern prelude. pub fn is_prelude(&self) -> bool { self.prelude @@ -353,7 +391,32 @@ impl Dependency { } } -impl CrateGraph { +pub type CratesIdMap = FxHashMap; + +#[salsa::input] +pub struct Crate { + #[return_ref] + pub data: BuiltCrateData, + /// Crate data that is not needed for analysis. + /// + /// This is split into a separate field to increase incrementality. + #[return_ref] + pub extra_data: ExtraCrateData, + // This is in `Arc` because it is shared for all crates in a workspace. + #[return_ref] + pub workspace_data: Arc, + // FIXME: Remove this `Arc`. + #[return_ref] + pub cfg_options: Arc, + #[return_ref] + pub env: Env, +} + +/// The mapping from [`UniqueCrateData`] to their [`Crate`] input. +#[derive(Debug, Default)] +pub struct CratesMap(DashMap>); + +impl CrateGraphBuilder { pub fn add_crate_root( &mut self, root_file_id: FileId, @@ -361,33 +424,34 @@ impl CrateGraph { display_name: Option, version: Option, cfg_options: Arc, - potential_cfg_options: Option>, + potential_cfg_options: Option, mut env: Env, origin: CrateOrigin, is_proc_macro: bool, proc_macro_cwd: Option, - ) -> CrateId { + ws_data: Arc, + ) -> CrateBuilderId { env.entries.shrink_to_fit(); - let data = CrateData { - root_file_id, - edition, - version, - display_name, + self.arena.alloc(CrateBuilder { + basic: CrateData { + root_file_id, + edition, + dependencies: Vec::new(), + origin, + is_proc_macro, + proc_macro_cwd, + }, + extra: ExtraCrateData { version, display_name, potential_cfg_options }, cfg_options, - potential_cfg_options, env, - dependencies: Vec::new(), - origin, - is_proc_macro, - proc_macro_cwd, - }; - self.arena.alloc(data) + ws_data, + }) } pub fn add_dep( &mut self, - from: CrateId, - dep: Dependency, + from: CrateBuilderId, + dep: DependencyBuilder, ) -> Result<(), CyclicDependenciesError> { let _p = tracing::info_span!("add_dep").entered(); @@ -395,37 +459,160 @@ impl CrateGraph { // that out, look for a path in the *opposite* direction, from `to` to // `from`. if let Some(path) = self.find_path(&mut FxHashSet::default(), dep.crate_id, from) { - let path = path.into_iter().map(|it| (it, self[it].display_name.clone())).collect(); + let path = + path.into_iter().map(|it| (it, self[it].extra.display_name.clone())).collect(); let err = CyclicDependenciesError { path }; assert!(err.from().0 == from && err.to().0 == dep.crate_id); return Err(err); } - self.arena[from].add_dep(dep); + self.arena[from].basic.dependencies.push(dep); Ok(()) } - pub fn is_empty(&self) -> bool { - self.arena.is_empty() - } + pub fn set_in_db(self, db: &mut dyn RootQueryDb) -> CratesIdMap { + let mut all_crates = Vec::with_capacity(self.arena.len()); + let mut visited = FxHashMap::default(); + let mut visited_root_files = FxHashSet::default(); - pub fn len(&self) -> usize { - self.arena.len() + let old_all_crates = db.all_crates(); + + let crates_map = db.crates_map(); + // salsa doesn't compare new input to old input to see if they are the same, so here we are doing all the work ourselves. + for krate in self.iter() { + go( + &self, + db, + &crates_map, + &mut visited, + &mut visited_root_files, + &mut all_crates, + krate, + ); + } + + if **old_all_crates != *all_crates { + db.set_all_crates_with_durability( + Arc::new(all_crates.into_boxed_slice()), + Durability::HIGH, + ); + } + + return visited; + + fn go( + graph: &CrateGraphBuilder, + db: &mut dyn RootQueryDb, + crates_map: &CratesMap, + visited: &mut FxHashMap, + visited_root_files: &mut FxHashSet, + all_crates: &mut Vec, + source: CrateBuilderId, + ) -> Crate { + if let Some(&crate_id) = visited.get(&source) { + return crate_id; + } + let krate = &graph[source]; + let dependencies = krate + .basic + .dependencies + .iter() + .map(|dep| BuiltDependency { + crate_id: go( + graph, + db, + crates_map, + visited, + visited_root_files, + all_crates, + dep.crate_id, + ), + name: dep.name.clone(), + prelude: dep.prelude, + sysroot: dep.sysroot, + }) + .collect::>(); + let crate_data = BuiltCrateData { + dependencies, + edition: krate.basic.edition, + is_proc_macro: krate.basic.is_proc_macro, + origin: krate.basic.origin.clone(), + root_file_id: krate.basic.root_file_id, + proc_macro_cwd: krate.basic.proc_macro_cwd.clone(), + }; + let disambiguator = if visited_root_files.insert(krate.basic.root_file_id) { + None + } else { + Some(Box::new((crate_data.clone(), krate.cfg_options.to_hashable()))) + }; + + let unique_crate_data = + UniqueCrateData { root_file_id: krate.basic.root_file_id, disambiguator }; + let crate_input = match crates_map.0.entry(unique_crate_data) { + Entry::Occupied(entry) => { + let old_crate = *entry.get(); + if crate_data != *old_crate.data(db) { + old_crate.set_data(db).with_durability(Durability::HIGH).to(crate_data); + } + if krate.extra != *old_crate.extra_data(db) { + old_crate + .set_extra_data(db) + .with_durability(Durability::HIGH) + .to(krate.extra.clone()); + } + if krate.cfg_options != *old_crate.cfg_options(db) { + old_crate + .set_cfg_options(db) + .with_durability(Durability::HIGH) + .to(krate.cfg_options.clone()); + } + if krate.env != *old_crate.env(db) { + old_crate + .set_env(db) + .with_durability(Durability::HIGH) + .to(krate.env.clone()); + } + if krate.ws_data != *old_crate.workspace_data(db) { + old_crate + .set_workspace_data(db) + .with_durability(Durability::HIGH) + .to(krate.ws_data.clone()); + } + old_crate + } + Entry::Vacant(entry) => { + let input = Crate::builder( + crate_data, + krate.extra.clone(), + krate.ws_data.clone(), + krate.cfg_options.clone(), + krate.env.clone(), + ) + .durability(Durability::HIGH) + .new(db); + entry.insert(input); + input + } + }; + all_crates.push(crate_input); + visited.insert(source, crate_input); + crate_input + } } - pub fn iter(&self) -> impl Iterator + '_ { + pub fn iter(&self) -> impl Iterator + '_ { self.arena.iter().map(|(idx, _)| idx) } // FIXME: used for fixing up the toolchain sysroot, should be removed and done differently #[doc(hidden)] - pub fn iter_mut(&mut self) -> impl Iterator + '_ { + pub fn iter_mut(&mut self) -> impl Iterator + '_ { self.arena.iter_mut() } /// Returns an iterator over all transitive dependencies of the given crate, /// including the crate itself. - pub fn transitive_deps(&self, of: CrateId) -> impl Iterator { + pub fn transitive_deps(&self, of: CrateBuilderId) -> impl Iterator { let mut worklist = vec![of]; let mut deps = FxHashSet::default(); @@ -434,42 +621,15 @@ impl CrateGraph { continue; } - worklist.extend(self[krate].dependencies.iter().map(|dep| dep.crate_id)); + worklist.extend(self[krate].basic.dependencies.iter().map(|dep| dep.crate_id)); } deps.into_iter() } - /// Returns all transitive reverse dependencies of the given crate, - /// including the crate itself. - pub fn transitive_rev_deps(&self, of: CrateId) -> impl Iterator { - let mut worklist = vec![of]; - let mut rev_deps = FxHashSet::default(); - rev_deps.insert(of); - - let mut inverted_graph = FxHashMap::<_, Vec<_>>::default(); - self.arena.iter().for_each(|(krate, data)| { - data.dependencies - .iter() - .for_each(|dep| inverted_graph.entry(dep.crate_id).or_default().push(krate)) - }); - - while let Some(krate) = worklist.pop() { - if let Some(krate_rev_deps) = inverted_graph.get(&krate) { - krate_rev_deps - .iter() - .copied() - .filter(|&rev_dep| rev_deps.insert(rev_dep)) - .for_each(|rev_dep| worklist.push(rev_dep)); - } - } - - rev_deps.into_iter() - } - /// Returns all crates in the graph, sorted in topological order (ie. dependencies of a crate /// come before the crate itself). - pub fn crates_in_topological_order(&self) -> Vec { + fn crates_in_topological_order(&self) -> Vec { let mut res = Vec::new(); let mut visited = FxHashSet::default(); @@ -480,15 +640,15 @@ impl CrateGraph { return res; fn go( - graph: &CrateGraph, - visited: &mut FxHashSet, - res: &mut Vec, - source: CrateId, + graph: &CrateGraphBuilder, + visited: &mut FxHashSet, + res: &mut Vec, + source: CrateBuilderId, ) { if !visited.insert(source) { return; } - for dep in graph[source].dependencies.iter() { + for dep in graph[source].basic.dependencies.iter() { go(graph, visited, res, dep.crate_id) } res.push(source) @@ -504,23 +664,27 @@ impl CrateGraph { /// Returns a map mapping `other`'s IDs to the new IDs in `self`. pub fn extend( &mut self, - mut other: CrateGraph, + mut other: CrateGraphBuilder, proc_macros: &mut ProcMacroPaths, - ) -> FxHashMap { + ) -> FxHashMap { // Sorting here is a bit pointless because the input is likely already sorted. // However, the overhead is small and it makes the `extend` method harder to misuse. self.arena .iter_mut() - .for_each(|(_, data)| data.dependencies.sort_by_key(|dep| dep.crate_id)); + .for_each(|(_, data)| data.basic.dependencies.sort_by_key(|dep| dep.crate_id)); - let m = self.len(); + let m = self.arena.len(); let topo = other.crates_in_topological_order(); - let mut id_map: FxHashMap = FxHashMap::default(); + let mut id_map: FxHashMap = FxHashMap::default(); for topo in topo { let crate_data = &mut other.arena[topo]; - crate_data.dependencies.iter_mut().for_each(|dep| dep.crate_id = id_map[&dep.crate_id]); - crate_data.dependencies.sort_by_key(|dep| dep.crate_id); + crate_data + .basic + .dependencies + .iter_mut() + .for_each(|dep| dep.crate_id = id_map[&dep.crate_id]); + crate_data.basic.dependencies.sort_by_key(|dep| dep.crate_id); let find = self.arena.iter().take(m).find_map(|(k, v)| (v == crate_data).then_some(k)); let new_id = find.unwrap_or_else(|| self.arena.alloc(crate_data.clone())); @@ -534,10 +698,10 @@ impl CrateGraph { fn find_path( &self, - visited: &mut FxHashSet, - from: CrateId, - to: CrateId, - ) -> Option> { + visited: &mut FxHashSet, + from: CrateBuilderId, + to: CrateBuilderId, + ) -> Option> { if !visited.insert(from) { return None; } @@ -546,7 +710,7 @@ impl CrateGraph { return Some(vec![to]); } - for dep in &self[from].dependencies { + for dep in &self[from].basic.dependencies { let crate_id = dep.crate_id; if let Some(mut path) = self.find_path(visited, crate_id, to) { path.push(from); @@ -559,7 +723,10 @@ impl CrateGraph { /// Removes all crates from this crate graph except for the ones in `to_keep` and fixes up the dependencies. /// Returns a mapping from old crate ids to new crate ids. - pub fn remove_crates_except(&mut self, to_keep: &[CrateId]) -> Vec> { + pub fn remove_crates_except( + &mut self, + to_keep: &[CrateBuilderId], + ) -> Vec> { let mut id_map = vec![None; self.arena.len()]; self.arena = std::mem::take(&mut self.arena) .into_iter() @@ -567,12 +734,12 @@ impl CrateGraph { .enumerate() .map(|(new_id, (id, data))| { id_map[id.into_raw().into_u32() as usize] = - Some(CrateId::from_raw(RawIdx::from_u32(new_id as u32))); + Some(CrateBuilderId::from_raw(RawIdx::from_u32(new_id as u32))); data }) .collect(); for (_, data) in self.arena.iter_mut() { - data.dependencies.iter_mut().for_each(|dep| { + data.basic.dependencies.iter_mut().for_each(|dep| { dep.crate_id = id_map[dep.crate_id.into_raw().into_u32() as usize].expect("crate was filtered") }); @@ -585,20 +752,34 @@ impl CrateGraph { } } -impl ops::Index for CrateGraph { - type Output = CrateData; - fn index(&self, crate_id: CrateId) -> &CrateData { - &self.arena[crate_id] +pub(crate) fn transitive_rev_deps(db: &dyn RootQueryDb, of: Crate) -> FxHashSet { + let mut worklist = vec![of]; + let mut rev_deps = FxHashSet::default(); + rev_deps.insert(of); + + let mut inverted_graph = FxHashMap::<_, Vec<_>>::default(); + db.all_crates().iter().for_each(|&krate| { + krate + .data(db) + .dependencies + .iter() + .for_each(|dep| inverted_graph.entry(dep.crate_id).or_default().push(krate)) + }); + + while let Some(krate) = worklist.pop() { + if let Some(crate_rev_deps) = inverted_graph.get(&krate) { + crate_rev_deps + .iter() + .copied() + .filter(|&rev_dep| rev_deps.insert(rev_dep)) + .for_each(|rev_dep| worklist.push(rev_dep)); + } } -} -impl CrateData { - /// Add a dependency to `self` without checking if the dependency - // is existent among `self.dependencies`. - fn add_dep(&mut self, dep: Dependency) { - self.dependencies.push(dep) - } + rev_deps +} +impl BuiltCrateData { pub fn root_file_id(&self) -> EditionedFileId { EditionedFileId::new(self.root_file_id, self.edition) } @@ -657,21 +838,21 @@ impl<'a> IntoIterator for &'a Env { #[derive(Debug)] pub struct CyclicDependenciesError { - path: Vec<(CrateId, Option)>, + path: Vec<(CrateBuilderId, Option)>, } impl CyclicDependenciesError { - fn from(&self) -> &(CrateId, Option) { + fn from(&self) -> &(CrateBuilderId, Option) { self.path.first().unwrap() } - fn to(&self) -> &(CrateId, Option) { + fn to(&self) -> &(CrateBuilderId, Option) { self.path.last().unwrap() } } impl fmt::Display for CyclicDependenciesError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let render = |(id, name): &(CrateId, Option)| match name { + let render = |(id, name): &(CrateBuilderId, Option)| match name { Some(it) => format!("{it}({id:?})"), None => format!("{id:?}"), }; @@ -688,13 +869,19 @@ impl fmt::Display for CyclicDependenciesError { #[cfg(test)] mod tests { - use crate::CrateOrigin; + use triomphe::Arc; + + use crate::{CrateWorkspaceData, DependencyBuilder}; - use super::{CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId}; + use super::{CrateGraphBuilder, CrateName, CrateOrigin, Edition::Edition2018, Env, FileId}; + + fn empty_ws_data() -> Arc { + Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None }) + } #[test] fn detect_cyclic_dependency_indirect() { - let mut graph = CrateGraph::default(); + let mut graph = CrateGraphBuilder::default(); let crate1 = graph.add_crate_root( FileId::from_raw(1u32), Edition2018, @@ -706,6 +893,7 @@ mod tests { CrateOrigin::Local { repo: None, name: None }, false, None, + empty_ws_data(), ); let crate2 = graph.add_crate_root( FileId::from_raw(2u32), @@ -718,6 +906,7 @@ mod tests { CrateOrigin::Local { repo: None, name: None }, false, None, + empty_ws_data(), ); let crate3 = graph.add_crate_root( FileId::from_raw(3u32), @@ -730,21 +919,22 @@ mod tests { CrateOrigin::Local { repo: None, name: None }, false, None, + empty_ws_data(), ); assert!(graph - .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,)) + .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) .is_ok()); assert!(graph - .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3,)) + .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate3").unwrap(), crate3,)) .is_ok()); assert!(graph - .add_dep(crate3, Dependency::new(CrateName::new("crate1").unwrap(), crate1,)) + .add_dep(crate3, DependencyBuilder::new(CrateName::new("crate1").unwrap(), crate1,)) .is_err()); } #[test] fn detect_cyclic_dependency_direct() { - let mut graph = CrateGraph::default(); + let mut graph = CrateGraphBuilder::default(); let crate1 = graph.add_crate_root( FileId::from_raw(1u32), Edition2018, @@ -756,6 +946,7 @@ mod tests { CrateOrigin::Local { repo: None, name: None }, false, None, + empty_ws_data(), ); let crate2 = graph.add_crate_root( FileId::from_raw(2u32), @@ -768,18 +959,19 @@ mod tests { CrateOrigin::Local { repo: None, name: None }, false, None, + empty_ws_data(), ); assert!(graph - .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,)) + .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) .is_ok()); assert!(graph - .add_dep(crate2, Dependency::new(CrateName::new("crate2").unwrap(), crate2,)) + .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) .is_err()); } #[test] fn it_works() { - let mut graph = CrateGraph::default(); + let mut graph = CrateGraphBuilder::default(); let crate1 = graph.add_crate_root( FileId::from_raw(1u32), Edition2018, @@ -791,6 +983,7 @@ mod tests { CrateOrigin::Local { repo: None, name: None }, false, None, + empty_ws_data(), ); let crate2 = graph.add_crate_root( FileId::from_raw(2u32), @@ -803,6 +996,7 @@ mod tests { CrateOrigin::Local { repo: None, name: None }, false, None, + empty_ws_data(), ); let crate3 = graph.add_crate_root( FileId::from_raw(3u32), @@ -815,18 +1009,19 @@ mod tests { CrateOrigin::Local { repo: None, name: None }, false, None, + empty_ws_data(), ); assert!(graph - .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,)) + .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) .is_ok()); assert!(graph - .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3,)) + .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate3").unwrap(), crate3,)) .is_ok()); } #[test] fn dashes_are_normalized() { - let mut graph = CrateGraph::default(); + let mut graph = CrateGraphBuilder::default(); let crate1 = graph.add_crate_root( FileId::from_raw(1u32), Edition2018, @@ -838,6 +1033,7 @@ mod tests { CrateOrigin::Local { repo: None, name: None }, false, None, + empty_ws_data(), ); let crate2 = graph.add_crate_root( FileId::from_raw(2u32), @@ -850,16 +1046,22 @@ mod tests { CrateOrigin::Local { repo: None, name: None }, false, None, + empty_ws_data(), ); assert!(graph .add_dep( crate1, - Dependency::new(CrateName::normalize_dashes("crate-name-with-dashes"), crate2,) + DependencyBuilder::new( + CrateName::normalize_dashes("crate-name-with-dashes"), + crate2, + ) ) .is_ok()); assert_eq!( - graph[crate1].dependencies, - vec![Dependency::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2,)] + graph.arena[crate1].basic.dependencies, + vec![ + DependencyBuilder::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2,) + ] ); } } diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index 9ec9100968d22..324979b2e463b 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -8,14 +8,15 @@ use std::hash::BuildHasherDefault; pub use crate::{ change::FileChange, input::{ - CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, - LangCrateOrigin, ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, - TargetLayoutLoadResult, + BuiltCrateData, BuiltDependency, Crate, CrateBuilder, CrateBuilderId, CrateDataBuilder, + CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CratesIdMap, CratesMap, + DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroPaths, ReleaseChannel, + SourceRoot, SourceRootId, TargetLayoutLoadResult, UniqueCrateData, }, }; use dashmap::{mapref::entry::Entry, DashMap}; pub use query_group::{self}; -use rustc_hash::{FxHashMap, FxHasher}; +use rustc_hash::{FxHashSet, FxHasher}; pub use salsa::{self}; use salsa::{Durability, Setter}; pub use semver::{BuildMetadata, Prerelease, Version, VersionReq}; @@ -200,21 +201,53 @@ pub trait RootQueryDb: SourceDatabase + salsa::Database { /// Returns the set of errors obtained from parsing the file including validation errors. fn parse_errors(&self, file_id: EditionedFileId) -> Option>; - /// The crate graph. - #[salsa::input] - fn crate_graph(&self) -> Arc; + #[salsa::transparent] + fn toolchain_channel(&self, krate: Crate) -> Option; - #[salsa::input] - fn crate_workspace_data(&self) -> Arc>>; + /// Crates whose root file is in `id`. + fn source_root_crates(&self, id: SourceRootId) -> Arc<[Crate]>; #[salsa::transparent] - fn toolchain_channel(&self, krate: CrateId) -> Option; + fn relevant_crates(&self, file_id: FileId) -> Arc<[Crate]>; - /// Crates whose root file is in `id`. - fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>; + /// Returns the crates in topological order. + /// + /// **Warning**: do not use this query in analysis! It kills incrementality across crate metadata modifications. + #[salsa::input] + fn all_crates(&self) -> Arc>; + + /// Returns an iterator over all transitive dependencies of the given crate, + /// including the crate itself. + /// + /// **Warning**: do not use this query in analysis! It kills incrementality across crate metadata modifications. + /// + #[salsa::transparent] + fn transitive_deps(&self, crate_id: Crate) -> FxHashSet; + /// Returns all transitive reverse dependencies of the given crate, + /// including the crate itself. + /// + /// **Warning**: Do not use this query in analysis! It kills incrementality across crate metadata modifications. + #[salsa::invoke(input::transitive_rev_deps)] #[salsa::transparent] - fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>; + fn transitive_rev_deps(&self, of: Crate) -> FxHashSet; +} + +pub fn transitive_deps(db: &dyn SourceDatabase, crate_id: Crate) -> FxHashSet { + // There is a bit of duplication here and in `CrateGraphBuilder` in the same method, but it's not terrible + // and removing that is a bit difficult. + let mut worklist = vec![crate_id]; + let mut deps = FxHashSet::default(); + + while let Some(krate) = worklist.pop() { + if !deps.insert(krate) { + continue; + } + + worklist.extend(krate.data(db).dependencies.iter().map(|dep| dep.crate_id)); + } + + deps } #[salsa::db] @@ -257,6 +290,9 @@ pub trait SourceDatabase: salsa::Database { let source_root = self.source_root(source_root.source_root_id(self)); source_root.source_root(self).resolve_path(path) } + + #[doc(hidden)] + fn crates_map(&self) -> Arc; } /// Crate related data shared by the whole workspace. @@ -268,12 +304,8 @@ pub struct CrateWorkspaceData { pub toolchain: Option, } -fn toolchain_channel(db: &dyn RootQueryDb, krate: CrateId) -> Option { - db.crate_workspace_data() - .get(&krate)? - .toolchain - .as_ref() - .and_then(|v| ReleaseChannel::from_str(&v.pre)) +fn toolchain_channel(db: &dyn RootQueryDb, krate: Crate) -> Option { + krate.workspace_data(db).toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre)) } fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse { @@ -291,21 +323,19 @@ fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option Arc<[CrateId]> { - let graph = db.crate_graph(); - let mut crates = graph +fn source_root_crates(db: &dyn RootQueryDb, id: SourceRootId) -> Arc<[Crate]> { + let crates = db.all_crates(); + crates .iter() + .copied() .filter(|&krate| { - let root_file = graph[krate].root_file_id; + let root_file = krate.data(db).root_file_id; db.file_source_root(root_file).source_root_id(db) == id }) - .collect::>(); - crates.sort(); - crates.dedup(); - crates.into_iter().collect() + .collect() } -fn relevant_crates(db: &dyn RootQueryDb, file_id: FileId) -> Arc<[CrateId]> { +fn relevant_crates(db: &dyn RootQueryDb, file_id: FileId) -> Arc<[Crate]> { let _p = tracing::info_span!("relevant_crates").entered(); let source_root = db.file_source_root(file_id); diff --git a/src/tools/rust-analyzer/crates/cfg/src/lib.rs b/src/tools/rust-analyzer/crates/cfg/src/lib.rs index 08545b685119d..26860fb932077 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/lib.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/lib.rs @@ -104,6 +104,12 @@ impl CfgOptions { _ => None, }) } + + pub fn to_hashable(&self) -> HashableCfgOptions { + let mut enabled = self.enabled.iter().cloned().collect::>(); + enabled.sort_unstable(); + HashableCfgOptions { _enabled: enabled } + } } impl Extend for CfgOptions { @@ -256,3 +262,9 @@ impl fmt::Display for InactiveReason { Ok(()) } } + +/// A `CfgOptions` that implements `Hash`, for the sake of hashing only. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct HashableCfgOptions { + _enabled: Box<[CfgAtom]>, +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 52a72bce91dce..579ea12e6ae03 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, hash::Hash, ops}; -use base_db::CrateId; +use base_db::Crate; use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_expand::{ @@ -44,7 +44,7 @@ impl Attrs { (**self).iter().find(|attr| attr.id == id) } - pub(crate) fn filter(db: &dyn DefDatabase, krate: CrateId, raw_attrs: RawAttrs) -> Attrs { + pub(crate) fn filter(db: &dyn DefDatabase, krate: Crate, raw_attrs: RawAttrs) -> Attrs { Attrs(raw_attrs.filter(db.upcast(), krate)) } } @@ -76,7 +76,6 @@ impl Attrs { // FIXME: There should be some proper form of mapping between item tree field ids and hir field ids let mut res = ArenaMap::default(); - let crate_graph = db.crate_graph(); let item_tree; let (parent, fields, krate) = match v { VariantId::EnumVariantId(it) => { @@ -102,7 +101,7 @@ impl Attrs { } }; - let cfg_options = &crate_graph[krate].cfg_options; + let cfg_options = krate.cfg_options(db); let mut idx = 0; for (id, _field) in fields.iter().enumerate() { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index bec662787728c..9c87dc31dba95 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -2,7 +2,7 @@ pub mod adt; -use base_db::CrateId; +use base_db::Crate; use hir_expand::{ name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind, }; @@ -22,7 +22,7 @@ use crate::{ attr_resolution::ResolvedAttr, diagnostics::{DefDiagnostic, DefDiagnostics}, proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind}, - DefMap, MacroSubNs, + DefMap, LocalDefMap, MacroSubNs, }, path::ImportAlias, type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap}, @@ -57,8 +57,7 @@ impl FunctionData { item_tree[func.visibility].clone() }; - let crate_graph = db.crate_graph(); - let cfg_options = &crate_graph[krate].cfg_options; + let cfg_options = krate.cfg_options(db); let attr_owner = |idx| { item_tree::AttrOwner::Param(loc.id.value, Idx::from_raw(RawIdx::from(idx as u32))) }; @@ -525,7 +524,7 @@ pub struct ExternCrateDeclData { pub name: Name, pub alias: Option, pub visibility: RawVisibility, - pub crate_id: Option, + pub crate_id: Option, } impl ExternCrateDeclData { @@ -542,7 +541,7 @@ impl ExternCrateDeclData { let crate_id = if name == sym::self_.clone() { Some(krate) } else { - db.crate_graph()[krate].dependencies.iter().find_map(|dep| { + krate.data(db).dependencies.iter().find_map(|dep| { if dep.name.symbol() == name.symbol() { Some(dep.crate_id) } else { @@ -633,6 +632,7 @@ struct AssocItemCollector<'a> { db: &'a dyn DefDatabase, module_id: ModuleId, def_map: Arc, + local_def_map: Arc, diagnostics: Vec, container: ItemContainerId, expander: Expander, @@ -648,10 +648,12 @@ impl<'a> AssocItemCollector<'a> { file_id: HirFileId, container: ItemContainerId, ) -> Self { + let (def_map, local_def_map) = module_id.local_def_map(db); Self { db, module_id, - def_map: module_id.def_map(db), + def_map, + local_def_map, container, expander: Expander::new(db, file_id, module_id), items: Vec::new(), @@ -697,6 +699,7 @@ impl<'a> AssocItemCollector<'a> { let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id }; match self.def_map.resolve_attr_macro( + &self.local_def_map, self.db, self.module_id.local_id, ast_id_with_path, @@ -780,6 +783,7 @@ impl<'a> AssocItemCollector<'a> { let resolver = |path: &_| { self.def_map .resolve_path( + &self.local_def_map, self.db, module, path, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index 28992ec600aeb..bf8f5024c2d6a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -1,6 +1,6 @@ //! Defines hir-level representation of structs, enums and unions -use base_db::CrateId; +use base_db::Crate; use bitflags::bitflags; use cfg::CfgOptions; use either::Either; @@ -90,7 +90,7 @@ pub struct FieldData { fn repr_from_value( db: &dyn DefDatabase, - krate: CrateId, + krate: Crate, item_tree: &ItemTree, of: AttrOwner, ) -> Option { @@ -222,7 +222,7 @@ impl StructData { loc.container.local_id, loc.id.tree_id(), &item_tree, - &db.crate_graph()[krate].cfg_options, + krate.cfg_options(db), FieldParent::Struct(loc.id.value), &strukt.fields, None, @@ -274,7 +274,7 @@ impl StructData { loc.container.local_id, loc.id.tree_id(), &item_tree, - &db.crate_graph()[krate].cfg_options, + krate.cfg_options(db), FieldParent::Union(loc.id.value), &union.fields, None, @@ -377,7 +377,7 @@ impl EnumVariantData { container.local_id, loc.id.tree_id(), &item_tree, - &db.crate_graph()[krate].cfg_options, + krate.cfg_options(db), FieldParent::Variant(loc.id.value), &variant.fields, Some(item_tree[loc.parent.lookup(db).id.value].visibility), @@ -448,7 +448,7 @@ pub enum StructKind { fn lower_fields( db: &dyn DefDatabase, - krate: CrateId, + krate: Crate, container: LocalModuleId, tree_id: TreeId, item_tree: &ItemTree, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 0772d00f03c8a..b6707af618115 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -1,5 +1,5 @@ //! Defines database & queries for name resolution. -use base_db::{CrateId, RootQueryDb, SourceDatabase, Upcast}; +use base_db::{Crate, RootQueryDb, SourceDatabase, Upcast}; use either::Either; use hir_expand::{db::ExpandDatabase, HirFileId, MacroDefId}; use intern::sym; @@ -20,7 +20,7 @@ use crate::{ import_map::ImportMap, item_tree::{AttrOwner, ItemTree, ItemTreeSourceMaps}, lang_item::{self, LangItem, LangItemTarget, LangItems}, - nameres::{diagnostics::DefDiagnostics, DefMap}, + nameres::{diagnostics::DefDiagnostics, DefMap, LocalDefMap}, tt, type_ref::TypesSourceMap, visibility::{self, Visibility}, @@ -130,8 +130,11 @@ pub trait DefDatabase: block_id: BlockId, ) -> (Arc, Arc); - #[salsa::invoke(DefMap::crate_def_map_query)] - fn crate_def_map(&self, krate: CrateId) -> Arc; + #[salsa::invoke_actual(DefMap::crate_local_def_map_query)] + fn crate_local_def_map(&self, krate: Crate) -> (Arc, Arc); + + #[salsa::invoke_actual(DefMap::crate_def_map_query)] + fn crate_def_map(&self, krate: Crate) -> Arc; /// Computes the block-level `DefMap`. #[salsa::invoke_actual(DefMap::block_def_map_query)] @@ -258,10 +261,10 @@ pub trait DefDatabase: // endregion:attrs #[salsa::invoke(LangItems::lang_item_query)] - fn lang_item(&self, start_crate: CrateId, item: LangItem) -> Option; + fn lang_item(&self, start_crate: Crate, item: LangItem) -> Option; - #[salsa::invoke(ImportMap::import_map_query)] - fn import_map(&self, krate: CrateId) -> Arc; + #[salsa::invoke_actual(ImportMap::import_map_query)] + fn import_map(&self, krate: Crate) -> Arc; // region:visibilities @@ -277,23 +280,25 @@ pub trait DefDatabase: // endregion:visibilities - #[salsa::invoke(LangItems::crate_lang_items_query)] - fn crate_lang_items(&self, krate: CrateId) -> Option>; + #[salsa::invoke_actual(LangItems::crate_lang_items_query)] + fn crate_lang_items(&self, krate: Crate) -> Option>; - #[salsa::invoke(crate::lang_item::notable_traits_in_deps)] - fn notable_traits_in_deps(&self, krate: CrateId) -> Arc<[Arc<[TraitId]>]>; - #[salsa::invoke(crate::lang_item::crate_notable_traits)] - fn crate_notable_traits(&self, krate: CrateId) -> Option>; + #[salsa::invoke_actual(crate::lang_item::notable_traits_in_deps)] + fn notable_traits_in_deps(&self, krate: Crate) -> Arc<[Arc<[TraitId]>]>; + #[salsa::invoke_actual(crate::lang_item::crate_notable_traits)] + fn crate_notable_traits(&self, krate: Crate) -> Option>; - fn crate_supports_no_std(&self, crate_id: CrateId) -> bool; + #[salsa::invoke_actual(crate_supports_no_std)] + fn crate_supports_no_std(&self, crate_id: Crate) -> bool; - fn include_macro_invoc(&self, crate_id: CrateId) -> Arc<[(MacroCallId, EditionedFileId)]>; + #[salsa::invoke_actual(include_macro_invoc)] + fn include_macro_invoc(&self, crate_id: Crate) -> Arc<[(MacroCallId, EditionedFileId)]>; } // return: macro call id and include file id fn include_macro_invoc( db: &dyn DefDatabase, - krate: CrateId, + krate: Crate, ) -> Arc<[(MacroCallId, EditionedFileId)]> { db.crate_def_map(krate) .modules @@ -307,8 +312,8 @@ fn include_macro_invoc( .collect() } -fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool { - let file = db.crate_graph()[crate_id].root_file_id(); +fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool { + let file = crate_id.data(db).root_file_id(); let item_tree = db.file_item_tree(file.into()); let attrs = item_tree.raw_attrs(AttrOwner::TopLevel); for attr in &**attrs { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs index a1b3123c9914e..c5ce8c454ce35 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs @@ -2,7 +2,7 @@ use std::cell::OnceCell; -use base_db::CrateId; +use base_db::Crate; use cfg::CfgOptions; use drop_bomb::DropBomb; use hir_expand::{ @@ -44,7 +44,7 @@ impl Expander { module, recursion_depth: 0, recursion_limit, - cfg_options: db.crate_graph()[module.krate].cfg_options.clone(), + cfg_options: Arc::clone(module.krate.cfg_options(db)), span_map: OnceCell::new(), } } @@ -53,7 +53,7 @@ impl Expander { self.span_map.get_or_init(|| db.span_map(self.current_file_id)) } - pub fn krate(&self) -> CrateId { + pub fn krate(&self) -> Crate { self.module.krate } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/body.rs index a55fec4f8b1e1..8aca4eb9bc1ef 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/body.rs @@ -86,7 +86,6 @@ impl Body { let item_tree = f.id.item_tree(db); let func = &item_tree[f.id.value]; let krate = f.container.module(db).krate; - let crate_graph = db.crate_graph(); ( param_list, (0..func.params.len()).map(move |idx| { @@ -99,7 +98,7 @@ impl Body { Idx::from_raw(RawIdx::from(idx as u32)), ), ) - .is_cfg_enabled(&crate_graph[krate].cfg_options) + .is_cfg_enabled(krate.cfg_options(db)) }), ) }); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index c3ca610faecbe..c346cec242eb6 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -5,7 +5,7 @@ mod asm; use std::mem; -use base_db::CrateId; +use base_db::Crate; use either::Either; use hir_expand::{ mod_path::tool_path, @@ -50,7 +50,7 @@ use crate::{ item_scope::BuiltinShadowMode, lang_item::LangItem, lower::LowerCtx, - nameres::{DefMap, MacroSubNs}, + nameres::{DefMap, LocalDefMap, MacroSubNs}, path::{GenericArgs, Path}, type_ref::{Mutability, Rawness, TypeRef}, AdtId, BlockId, BlockLoc, ConstBlockLoc, DefWithBodyId, MacroId, ModuleDefId, UnresolvedMacro, @@ -64,7 +64,7 @@ pub(super) fn lower_body( expander: Expander, parameters: Option<(ast::ParamList, impl Iterator)>, body: Option, - krate: CrateId, + krate: Crate, is_async_fn: bool, ) -> (Body, BodySourceMap) { // We cannot leave the root span map empty and let any identifier from it be treated as root, @@ -189,7 +189,7 @@ pub(super) fn lower( owner: ExprStoreOwnerId, expander: Expander, body: Option, - krate: CrateId, + krate: Crate, ) -> (ExpressionStore, ExpressionStoreSourceMap) { // We cannot leave the root span map empty and let any identifier from it be treated as root, // because when inside nested macros `SyntaxContextId`s from the outer macro will be interleaved @@ -214,8 +214,9 @@ struct ExprCollector<'a> { expander: Expander, owner: ExprStoreOwnerId, def_map: Arc, + local_def_map: Arc, ast_id_map: Arc, - krate: CrateId, + krate: Crate, store: ExpressionStoreBuilder, source_map: ExpressionStoreSourceMap, @@ -327,14 +328,16 @@ impl ExprCollector<'_> { db: &dyn DefDatabase, owner: ExprStoreOwnerId, expander: Expander, - krate: CrateId, + krate: Crate, span_map: Option>, ) -> ExprCollector<'_> { + let (def_map, local_def_map) = expander.module.local_def_map(db); ExprCollector { db, owner, krate, - def_map: expander.module.def_map(db), + def_map, + local_def_map, source_map: ExpressionStoreSourceMap::default(), ast_id_map: db.ast_id_map(expander.current_file_id()), store: ExpressionStoreBuilder::default(), @@ -1306,6 +1309,7 @@ impl ExprCollector<'_> { None => self.expander.enter_expand(self.db, mcall, |path| { self.def_map .resolve_path( + &self.local_def_map, self.db, module, path, @@ -1608,6 +1612,7 @@ impl ExprCollector<'_> { // This could also be a single-segment path pattern. To // decide that, we need to try resolving the name. let (resolved, _) = self.def_map.resolve_path( + &self.local_def_map, self.db, self.expander.module.local_id, &name.clone().into(), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs index 16bf46d3e3f95..7bf27747c464a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs @@ -293,7 +293,7 @@ impl SsrError { assert_eq!(db.body_with_source_map(def).1.diagnostics(), &[]); expect![[r#" fn main() -> () { - _ = $crate::error::SsrError::new( + _ = ra_test_fixture::error::SsrError::new( builtin#lang(Arguments::new_v1_formatted)( &[ "Failed to resolve path `", "`", @@ -353,7 +353,7 @@ fn f(a: i32, b: u32) -> String { expect![[r#" fn f(a: i32, b: u32) -> String { { - $crate::panicking::panic_fmt( + core::panicking::panic_fmt( builtin#lang(Arguments::new_v1_formatted)( &[ "cc", diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs index c30ad0163b9db..48f31698ddf8e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs @@ -2,7 +2,7 @@ use std::{cell::Cell, cmp::Ordering, iter}; -use base_db::{CrateId, CrateOrigin, LangCrateOrigin}; +use base_db::{Crate, CrateOrigin, LangCrateOrigin}; use hir_expand::{ name::{AsName, Name}, Lookup, @@ -50,7 +50,7 @@ pub fn find_path( prefix: prefix_kind, cfg, ignore_local_imports, - is_std_item: db.crate_graph()[item_module.krate()].origin.is_lang(), + is_std_item: item_module.krate().data(db).origin.is_lang(), from, from_def_map: &from.def_map(db), fuel: Cell::new(FIND_PATH_FUEL), @@ -174,9 +174,9 @@ fn find_path_for_module( } // - otherwise if the item is the crate root of a dependency crate, return the name from the extern prelude - let root_def_map = ctx.from.derive_crate_root().def_map(ctx.db); + let root_local_def_map = ctx.from.derive_crate_root().local_def_map(ctx.db).1; // rev here so we prefer looking at renamed extern decls first - for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude().rev() { + for (name, (def_id, _extern_crate)) in root_local_def_map.extern_prelude().rev() { if crate_root != def_id { continue; } @@ -360,7 +360,7 @@ fn calculate_best_path( // too (unless we can't name it at all). It could *also* be (re)exported by the same crate // that wants to import it here, but we always prefer to use the external path here. - ctx.db.crate_graph()[ctx.from.krate].dependencies.iter().for_each(|dep| { + ctx.from.krate.data(ctx.db).dependencies.iter().for_each(|dep| { find_in_dep(ctx, visited_modules, item, max_len, best_choice, dep.crate_id) }); } @@ -373,11 +373,10 @@ fn find_in_sysroot( max_len: usize, best_choice: &mut Option, ) { - let crate_graph = ctx.db.crate_graph(); - let dependencies = &crate_graph[ctx.from.krate].dependencies; + let dependencies = &ctx.from.krate.data(ctx.db).dependencies; let mut search = |lang, best_choice: &mut _| { if let Some(dep) = dependencies.iter().filter(|it| it.is_sysroot()).find(|dep| { - match crate_graph[dep.crate_id].origin { + match dep.crate_id.data(ctx.db).origin { CrateOrigin::Lang(l) => l == lang, _ => false, } @@ -419,7 +418,7 @@ fn find_in_dep( item: ItemInNs, max_len: usize, best_choice: &mut Option, - dep: CrateId, + dep: Crate, ) { let import_map = ctx.db.import_map(dep); let Some(import_info_for) = import_map.import_info_for(item) else { @@ -688,9 +687,10 @@ mod tests { }) .unwrap(); - let def_map = module.def_map(&db); + let (def_map, local_def_map) = module.local_def_map(&db); let resolved = def_map .resolve_path( + &local_def_map, &db, module.local_id, &mod_path, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs index 80820193796de..09b4591a21a6f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs @@ -23,7 +23,7 @@ use crate::{ expander::Expander, item_tree::{AttrOwner, FileItemTreeId, GenericModItem, GenericsItemTreeNode, ItemTree}, lower::LowerCtx, - nameres::{DefMap, MacroSubNs}, + nameres::{DefMap, LocalDefMap, MacroSubNs}, path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path}, type_ref::{ ArrayType, ConstRef, FnType, LifetimeRef, PathId, RefType, TypeBound, TypeRef, TypeRefId, @@ -313,8 +313,7 @@ impl GenericParams { let _p = tracing::info_span!("generic_params_query").entered(); let krate = def.krate(db); - let cfg_options = db.crate_graph(); - let cfg_options = &cfg_options[krate].cfg_options; + let cfg_options = &krate.cfg_options(db); // Returns the generic parameters that are enabled under the current `#[cfg]` options let enabled_params = @@ -413,7 +412,12 @@ impl GenericParams { &mut types_source_maps, &mut expander, &mut || { - (module.def_map(db), Expander::new(db, loc.id.file_id(), module)) + let (def_map, local_def_map) = module.local_def_map(db); + ( + def_map, + local_def_map, + Expander::new(db, loc.id.file_id(), module), + ) }, param, &item.types_map, @@ -626,8 +630,8 @@ impl GenericParamsCollector { generics_types_map: &mut TypesMap, generics_types_source_map: &mut TypesSourceMap, // FIXME: Change this back to `LazyCell` if https://github.com/rust-lang/libs-team/issues/429 is accepted. - exp: &mut Option<(Arc, Expander)>, - exp_fill: &mut dyn FnMut() -> (Arc, Expander), + exp: &mut Option<(Arc, Arc, Expander)>, + exp_fill: &mut dyn FnMut() -> (Arc, Arc, Expander), type_ref: TypeRefId, types_map: &TypesMap, types_source_map: &TypesSourceMap, @@ -657,12 +661,13 @@ impl GenericParamsCollector { if let TypeRef::Macro(mc) = type_ref { let macro_call = mc.to_node(db.upcast()); - let (def_map, expander) = exp.get_or_insert_with(&mut *exp_fill); + let (def_map, local_def_map, expander) = exp.get_or_insert_with(&mut *exp_fill); let module = expander.module.local_id; let resolver = |path: &_| { def_map .resolve_path( + local_def_map, db, module, path, @@ -690,7 +695,7 @@ impl GenericParamsCollector { ¯o_types_map, ¯o_types_source_map, ); - exp.get_or_insert_with(&mut *exp_fill).1.exit(mark); + exp.get_or_insert_with(&mut *exp_fill).2.exit(mark); } } }); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs index 64c1d0d274f34..1cdc4c025975c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs @@ -2,7 +2,7 @@ use std::fmt; -use base_db::CrateId; +use base_db::Crate; use fst::{raw::IndexedValue, Automaton, Streamer}; use hir_expand::name::Name; use itertools::Itertools; @@ -78,7 +78,7 @@ impl ImportMap { out } - pub(crate) fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc { + pub(crate) fn import_map_query(db: &dyn DefDatabase, krate: Crate) -> Arc { let _p = tracing::info_span!("import_map_query").entered(); let map = Self::collect_import_map(db, krate); @@ -129,7 +129,7 @@ impl ImportMap { self.item_to_info_map.get(&item).map(|(info, _)| &**info) } - fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex { + fn collect_import_map(db: &dyn DefDatabase, krate: Crate) -> ImportMapIndex { let _p = tracing::info_span!("collect_import_map").entered(); let def_map = db.crate_def_map(krate); @@ -400,15 +400,13 @@ impl Query { /// This returns a list of items that could be imported from dependencies of `krate`. pub fn search_dependencies( db: &dyn DefDatabase, - krate: CrateId, + krate: Crate, query: &Query, ) -> FxHashSet { let _p = tracing::info_span!("search_dependencies", ?query).entered(); - let graph = db.crate_graph(); - let import_maps: Vec<_> = - graph[krate].dependencies.iter().map(|dep| db.import_map(dep.crate_id)).collect(); + krate.data(db).dependencies.iter().map(|dep| db.import_map(dep.crate_id)).collect(); let mut op = fst::map::OpBuilder::new(); @@ -512,11 +510,13 @@ mod tests { expect: Expect, ) { let db = TestDB::with_files(ra_fixture); - let crate_graph = db.crate_graph(); - let krate = crate_graph + let all_crates = db.all_crates(); + let krate = all_crates .iter() + .copied() .find(|&krate| { - crate_graph[krate] + krate + .extra_data(&db) .display_name .as_ref() .is_some_and(|it| it.crate_name().as_str() == crate_name) @@ -545,7 +545,7 @@ mod tests { Some(format!( "{}::{} ({})\n", - crate_graph[dependency_krate].display_name.as_ref()?, + dependency_krate.extra_data(&db).display_name.as_ref()?, path, mark )) @@ -590,12 +590,13 @@ mod tests { fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let db = TestDB::with_files(ra_fixture); - let crate_graph = db.crate_graph(); + let all_crates = db.all_crates(); - let actual = crate_graph + let actual = all_crates .iter() + .copied() .filter_map(|krate| { - let cdata = &crate_graph[krate]; + let cdata = &krate.extra_data(&db); let name = cdata.display_name.as_ref()?; let map = db.import_map(krate); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index 0ca1eb9bcfe37..0c683f3531c95 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -3,7 +3,7 @@ use std::sync::LazyLock; -use base_db::CrateId; +use base_db::Crate; use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId}; use indexmap::map::Entry; use itertools::Itertools; @@ -916,7 +916,7 @@ impl ItemInNs { } /// Returns the crate defining this item (or `None` if `self` is built-in). - pub fn krate(&self, db: &dyn DefDatabase) -> Option { + pub fn krate(&self, db: &dyn DefDatabase) -> Option { match self { ItemInNs::Types(id) | ItemInNs::Values(id) => id.module(db).map(|m| m.krate), ItemInNs::Macros(id) => Some(id.module(db).krate), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 382afbcb1dd4f..9acf98e62cd5c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -44,7 +44,7 @@ use std::{ }; use ast::{AstNode, StructKind}; -use base_db::CrateId; +use base_db::Crate; use either::Either; use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile}; use intern::{Interned, Symbol}; @@ -202,7 +202,7 @@ impl ItemTree { } /// Returns the inner attributes of the source file. - pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs { + pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs { Attrs::filter( db, krate, @@ -214,7 +214,7 @@ impl ItemTree { self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY) } - pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs { + pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: Crate, of: AttrOwner) -> Attrs { Attrs::filter(db, krate, self.raw_attrs(of).clone()) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 59f51db9f7401..70c28009f4b99 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; use triomphe::Arc; use crate::{ - db::DefDatabase, path::Path, AdtId, AssocItemId, AttrDefId, CrateId, EnumId, EnumVariantId, + db::DefDatabase, path::Path, AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId, FunctionId, ImplId, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, UnionId, }; @@ -96,7 +96,7 @@ impl LangItems { /// Salsa query. This will look for lang items in a specific crate. pub(crate) fn crate_lang_items_query( db: &dyn DefDatabase, - krate: CrateId, + krate: Crate, ) -> Option> { let _p = tracing::info_span!("crate_lang_items_query").entered(); @@ -175,7 +175,7 @@ impl LangItems { /// traversing its dependencies. pub(crate) fn lang_item_query( db: &dyn DefDatabase, - start_crate: CrateId, + start_crate: Crate, item: LangItem, ) -> Option { let _p = tracing::info_span!("lang_item_query").entered(); @@ -184,10 +184,7 @@ impl LangItems { { return Some(target); } - db.crate_graph()[start_crate] - .dependencies - .iter() - .find_map(|dep| db.lang_item(dep.crate_id, item)) + start_crate.data(db).dependencies.iter().find_map(|dep| db.lang_item(dep.crate_id, item)) } fn collect_lang_item( @@ -209,19 +206,14 @@ pub(crate) fn lang_attr(db: &dyn DefDatabase, item: AttrDefId) -> Option Arc<[Arc<[TraitId]>]> { +pub(crate) fn notable_traits_in_deps(db: &dyn DefDatabase, krate: Crate) -> Arc<[Arc<[TraitId]>]> { let _p = tracing::info_span!("notable_traits_in_deps", ?krate).entered(); - let crate_graph = db.crate_graph(); - Arc::from_iter( - crate_graph.transitive_deps(krate).filter_map(|krate| db.crate_notable_traits(krate)), + db.transitive_deps(krate).into_iter().filter_map(|krate| db.crate_notable_traits(krate)), ) } -pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: CrateId) -> Option> { +pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option> { let _p = tracing::info_span!("crate_notable_traits", ?krate).entered(); let mut traits = Vec::new(); @@ -290,17 +282,12 @@ impl LangItem { Self::from_symbol(name.symbol()) } - pub fn path(&self, db: &dyn DefDatabase, start_crate: CrateId) -> Option { + pub fn path(&self, db: &dyn DefDatabase, start_crate: Crate) -> Option { let t = db.lang_item(start_crate, *self)?; Some(Path::LangItem(t, None)) } - pub fn ty_rel_path( - &self, - db: &dyn DefDatabase, - start_crate: CrateId, - seg: Name, - ) -> Option { + pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -> Option { let t = db.lang_item(start_crate, *self)?; Some(Path::LangItem(t, Some(seg))) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 15ef8364ed215..fbbeb4beb99b9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -71,7 +71,7 @@ mod test_db; use std::hash::{Hash, Hasher}; -use base_db::{impl_intern_key, CrateId}; +use base_db::{impl_intern_key, Crate}; use hir_expand::{ builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander}, db::ExpandDatabase, @@ -99,10 +99,10 @@ use crate::{ Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant, }, + nameres::LocalDefMap, }; -type FxIndexMap = - indexmap::IndexMap>; +type FxIndexMap = indexmap::IndexMap; /// A wrapper around three booleans #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] pub struct ImportPathConfig { @@ -338,7 +338,7 @@ pub struct ConstBlockLoc { /// A `ModuleId` that is always a crate's root module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct CrateRootModuleId { - krate: CrateId, + krate: Crate, } impl CrateRootModuleId { @@ -346,7 +346,11 @@ impl CrateRootModuleId { db.crate_def_map(self.krate) } - pub fn krate(self) -> CrateId { + pub(crate) fn local_def_map(&self, db: &dyn DefDatabase) -> (Arc, Arc) { + db.crate_local_def_map(self.krate) + } + + pub fn krate(self) -> Crate { self.krate } } @@ -374,8 +378,8 @@ impl From for ModuleDefId { } } -impl From for CrateRootModuleId { - fn from(krate: CrateId) -> Self { +impl From for CrateRootModuleId { + fn from(krate: Crate) -> Self { CrateRootModuleId { krate } } } @@ -394,7 +398,7 @@ impl TryFrom for CrateRootModuleId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ModuleId { - krate: CrateId, + krate: Crate, /// If this `ModuleId` was derived from a `DefMap` for a block expression, this stores the /// `BlockId` of that block expression. If `None`, this module is part of the crate-level /// `DefMap` of `krate`. @@ -411,11 +415,22 @@ impl ModuleId { } } + pub(crate) fn local_def_map(self, db: &dyn DefDatabase) -> (Arc, Arc) { + match self.block { + Some(block) => (db.block_def_map(block), self.only_local_def_map(db)), + None => db.crate_local_def_map(self.krate), + } + } + + pub(crate) fn only_local_def_map(self, db: &dyn DefDatabase) -> Arc { + db.crate_local_def_map(self.krate).1 + } + pub fn crate_def_map(self, db: &dyn DefDatabase) -> Arc { db.crate_def_map(self.krate) } - pub fn krate(self) -> CrateId { + pub fn krate(self) -> Crate { self.krate } @@ -982,7 +997,7 @@ impl From for ModuleDefId { } impl CallableDefId { - pub fn krate(self, db: &dyn DefDatabase) -> CrateId { + pub fn krate(self, db: &dyn DefDatabase) -> Crate { match self { CallableDefId::FunctionId(f) => f.krate(db), CallableDefId::StructId(s) => s.krate(db), @@ -1119,7 +1134,7 @@ pub trait HasModule { /// Returns the crate this thing is defined within. #[inline] #[doc(alias = "crate")] - fn krate(&self, db: &dyn DefDatabase) -> CrateId { + fn krate(&self, db: &dyn DefDatabase) -> Crate { self.module(db).krate } } @@ -1367,7 +1382,7 @@ pub trait AsMacroCall { fn as_call_id( &self, db: &dyn ExpandDatabase, - krate: CrateId, + krate: Crate, resolver: impl Fn(&path::ModPath) -> Option + Copy, ) -> Option { self.as_call_id_with_errors(db, krate, resolver).ok()?.value @@ -1376,7 +1391,7 @@ pub trait AsMacroCall { fn as_call_id_with_errors( &self, db: &dyn ExpandDatabase, - krate: CrateId, + krate: Crate, resolver: impl Fn(&path::ModPath) -> Option + Copy, ) -> Result>, UnresolvedMacro>; } @@ -1385,7 +1400,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> { fn as_call_id_with_errors( &self, db: &dyn ExpandDatabase, - krate: CrateId, + krate: Crate, resolver: impl Fn(&path::ModPath) -> Option + Copy, ) -> Result>, UnresolvedMacro> { let expands_to = hir_expand::ExpandTo::from_call_site(self.value); @@ -1442,7 +1457,7 @@ fn macro_call_as_call_id( call: &AstIdWithPath, call_site: SyntaxContextId, expand_to: ExpandTo, - krate: CrateId, + krate: Crate, resolver: impl Fn(&path::ModPath) -> Option + Copy, ) -> Result, UnresolvedMacro> { macro_call_as_call_id_with_eager( @@ -1464,7 +1479,7 @@ fn macro_call_as_call_id_with_eager( path: &path::ModPath, call_site: SyntaxContextId, expand_to: ExpandTo, - krate: CrateId, + krate: Crate, resolver: impl FnOnce(&path::ModPath) -> Option, eager_resolver: impl Fn(&path::ModPath) -> Option, ) -> Result>, UnresolvedMacro> { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs index d0678a40652fd..70b512c014b94 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -376,4 +376,8 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander { panic!("got invalid macro input: {:?}", parse.errors()); } } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.as_any().type_id() == std::any::TypeId::of::() + } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index 5b3d75c4ee669..054c285fa2567 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -59,7 +59,7 @@ mod tests; use std::ops::Deref; -use base_db::CrateId; +use base_db::Crate; use hir_expand::{ name::Name, proc_macro::ProcMacroKind, ErasedAstId, HirFileId, InFile, MacroCallId, MacroDefId, }; @@ -69,7 +69,7 @@ use la_arena::Arena; use rustc_hash::{FxHashMap, FxHashSet}; use span::{Edition, EditionedFileId, FileAstId, FileId, ROOT_ERASED_FILE_AST_ID}; use stdx::format_to; -use syntax::{ast, AstNode, SmolStr, SyntaxNode}; +use syntax::{ast, AstNode, SmolStr, SyntaxNode, ToSmolStr}; use triomphe::Arc; use tt::TextRange; @@ -95,6 +95,39 @@ const PREDEFINED_TOOLS: &[SmolStr] = &[ SmolStr::new_static("rust_analyzer"), ]; +/// Parts of the def map that are only needed when analyzing code in the same crate. +/// +/// There are some data in the def map (e.g. extern prelude) that is only needed when analyzing +/// things in the same crate (and maybe in the IDE layer), e.g. the extern prelude. If we put +/// it in the DefMap dependant DefMaps will be invalidated when they change (e.g. when we add +/// a dependency to the crate). Instead we split them out of the DefMap into a LocalDefMap struct. +/// `crate_local_def_map()` returns both, and `crate_def_map()` returns only the external-relevant +/// DefMap. +#[derive(Debug, PartialEq, Eq, Default)] +pub struct LocalDefMap { + // FIXME: There are probably some other things that could be here, but this is less severe and you + // need to be careful with things that block def maps also have. + /// The extern prelude which contains all root modules of external crates that are in scope. + extern_prelude: FxIndexMap)>, +} + +impl LocalDefMap { + pub(crate) const EMPTY: &Self = + &Self { extern_prelude: FxIndexMap::with_hasher(rustc_hash::FxBuildHasher) }; + + fn shrink_to_fit(&mut self) { + let Self { extern_prelude } = self; + extern_prelude.shrink_to_fit(); + } + + pub(crate) fn extern_prelude( + &self, + ) -> impl DoubleEndedIterator))> + '_ + { + self.extern_prelude.iter().map(|(name, &def)| (name, def)) + } +} + /// Contains the results of (early) name resolution. /// /// A `DefMap` stores the module tree and the definitions that are in scope in every module after @@ -107,7 +140,7 @@ const PREDEFINED_TOOLS: &[SmolStr] = &[ #[derive(Debug, PartialEq, Eq)] pub struct DefMap { /// The crate this `DefMap` belongs to. - krate: CrateId, + krate: Crate, /// When this is a block def map, this will hold the block id of the block and module that /// contains this block. block: Option, @@ -141,9 +174,6 @@ pub struct DefMap { /// Data that belongs to a crate which is shared between a crate's def map and all its block def maps. #[derive(Clone, Debug, PartialEq, Eq)] struct DefMapCrateData { - /// The extern prelude which contains all root modules of external crates that are in scope. - extern_prelude: FxIndexMap)>, - /// Side table for resolving derive helpers. exported_derives: FxHashMap>, fn_proc_macro_mapping: FxHashMap, @@ -166,7 +196,6 @@ struct DefMapCrateData { impl DefMapCrateData { fn new(edition: Edition) -> Self { Self { - extern_prelude: FxIndexMap::default(), exported_derives: FxHashMap::default(), fn_proc_macro_mapping: FxHashMap::default(), registered_attrs: Vec::new(), @@ -182,7 +211,6 @@ impl DefMapCrateData { fn shrink_to_fit(&mut self) { let Self { - extern_prelude, exported_derives, fn_proc_macro_mapping, registered_attrs, @@ -194,7 +222,6 @@ impl DefMapCrateData { edition: _, recursion_limit: _, } = self; - extern_prelude.shrink_to_fit(); exported_derives.shrink_to_fit(); fn_proc_macro_mapping.shrink_to_fit(); registered_attrs.shrink_to_fit(); @@ -219,11 +246,11 @@ struct BlockRelativeModuleId { } impl BlockRelativeModuleId { - fn def_map(self, db: &dyn DefDatabase, krate: CrateId) -> Arc { + fn def_map(self, db: &dyn DefDatabase, krate: Crate) -> Arc { self.into_module(krate).def_map(db) } - fn into_module(self, krate: CrateId) -> ModuleId { + fn into_module(self, krate: Crate) -> ModuleId { ModuleId { krate, block: self.block, local_id: self.local_id } } @@ -337,11 +364,25 @@ impl DefMap { self.data.edition } - pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: CrateId) -> Arc { - let crate_graph = db.crate_graph(); - let krate = &crate_graph[crate_id]; - let name = krate.display_name.as_deref().map(Symbol::as_str).unwrap_or_default(); - let _p = tracing::info_span!("crate_def_map_query", ?name).entered(); + pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: Crate) -> Arc { + db.crate_local_def_map(crate_id).0 + } + + pub(crate) fn crate_local_def_map_query( + db: &dyn DefDatabase, + crate_id: Crate, + ) -> (Arc, Arc) { + let krate = crate_id.data(db); + let _p = tracing::info_span!( + "crate_def_map_query", + name=?crate_id + .extra_data(db) + .display_name + .as_ref() + .map(|it| it.crate_name().to_smolstr()) + .unwrap_or_default() + ) + .entered(); let module_data = ModuleData::new( ModuleOrigin::CrateRoot { definition: krate.root_file_id() }, @@ -354,10 +395,14 @@ impl DefMap { module_data, None, ); - let def_map = - collector::collect_defs(db, def_map, TreeId::new(krate.root_file_id().into(), None)); + let (def_map, local_def_map) = collector::collect_defs( + db, + def_map, + TreeId::new(krate.root_file_id().into(), None), + None, + ); - Arc::new(def_map) + (Arc::new(def_map), Arc::new(local_def_map)) } pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc { @@ -370,10 +415,10 @@ impl DefMap { let module_data = ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility); - let parent_map = module.def_map(db); + let (crate_map, crate_local_map) = db.crate_local_def_map(module.krate); let def_map = DefMap::empty( module.krate, - parent_map.data.clone(), + crate_map.data.clone(), module_data, Some(BlockInfo { block: block_id, @@ -381,13 +426,17 @@ impl DefMap { }), ); - let def_map = - collector::collect_defs(db, def_map, TreeId::new(ast_id.file_id, Some(block_id))); + let (def_map, _) = collector::collect_defs( + db, + def_map, + TreeId::new(ast_id.file_id, Some(block_id)), + Some(crate_local_map), + ); Arc::new(def_map) } fn empty( - krate: CrateId, + krate: Crate, crate_data: Arc, module_data: ModuleData, block: Option, @@ -479,7 +528,7 @@ impl DefMap { self.data.fn_proc_macro_mapping.get(&id).copied() } - pub fn krate(&self) -> CrateId { + pub fn krate(&self) -> Crate { self.krate } @@ -590,19 +639,13 @@ impl DefMap { self.prelude } - pub(crate) fn extern_prelude( - &self, - ) -> impl DoubleEndedIterator))> + '_ - { - self.data.extern_prelude.iter().map(|(name, &def)| (name, def)) - } - pub(crate) fn macro_use_prelude(&self) -> &FxHashMap)> { &self.macro_use_prelude } pub(crate) fn resolve_path( &self, + local_def_map: &LocalDefMap, db: &dyn DefDatabase, original_module: LocalModuleId, path: &ModPath, @@ -610,6 +653,7 @@ impl DefMap { expected_macro_subns: Option, ) -> (PerNs, Option) { let res = self.resolve_path_fp_with_macro( + local_def_map, db, ResolveMode::Other, original_module, @@ -624,12 +668,14 @@ impl DefMap { /// points at the unresolved segments. pub(crate) fn resolve_path_locally( &self, + local_def_map: &LocalDefMap, db: &dyn DefDatabase, original_module: LocalModuleId, path: &ModPath, shadow: BuiltinShadowMode, ) -> (PerNs, Option, ResolvePathResultPrefixInfo) { let res = self.resolve_path_fp_with_macro_single( + local_def_map, db, ResolveMode::Other, original_module, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs index d1f6ed023c2fa..289b9e2fb7e9f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs @@ -1,6 +1,6 @@ //! Post-nameres attribute resolution. -use base_db::CrateId; +use base_db::Crate; use hir_expand::{ attrs::{Attr, AttrId, AttrInput}, inert_attr_macro::find_builtin_attr_idx, @@ -13,7 +13,7 @@ use triomphe::Arc; use crate::{ db::DefDatabase, item_scope::BuiltinShadowMode, - nameres::path_resolution::ResolveMode, + nameres::{path_resolution::ResolveMode, LocalDefMap}, path::{self, ModPath, PathKind}, AstIdWithPath, LocalModuleId, MacroId, UnresolvedMacro, }; @@ -30,6 +30,7 @@ pub enum ResolvedAttr { impl DefMap { pub(crate) fn resolve_attr_macro( &self, + local_def_map: &LocalDefMap, db: &dyn DefDatabase, original_module: LocalModuleId, ast_id: AstIdWithPath, @@ -42,6 +43,7 @@ impl DefMap { } let resolved_res = self.resolve_path_fp_with_macro( + local_def_map, db, ResolveMode::Other, original_module, @@ -105,7 +107,7 @@ pub(super) fn attr_macro_as_call_id( db: &dyn DefDatabase, item_attr: &AstIdWithPath, macro_attr: &Attr, - krate: CrateId, + krate: Crate, def: MacroDefId, ) -> MacroCallId { let arg = match macro_attr.input.as_deref() { @@ -136,7 +138,7 @@ pub(super) fn derive_macro_as_call_id( derive_attr_index: AttrId, derive_pos: u32, call_site: SyntaxContextId, - krate: CrateId, + krate: Crate, resolver: impl Fn(&path::ModPath) -> Option<(MacroId, MacroDefId)>, derive_macro_id: MacroCallId, ) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index bf013c25ef5e3..371e99433469f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -5,7 +5,7 @@ use std::{cmp::Ordering, iter, mem, ops::Not}; -use base_db::{CrateId, CrateOrigin, Dependency, LangCrateOrigin}; +use base_db::{BuiltDependency, Crate, CrateOrigin, LangCrateOrigin}; use cfg::{CfgAtom, CfgExpr, CfgOptions}; use either::Either; use hir_expand::{ @@ -39,8 +39,8 @@ use crate::{ mod_resolution::ModDir, path_resolution::ReachedFixedPoint, proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind}, - sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin, - ResolveMode, + sub_namespace_match, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, + ModuleOrigin, ResolveMode, }, path::{ImportAlias, ModPath, PathKind}, per_ns::{Item, PerNs}, @@ -57,10 +57,14 @@ use crate::{ const GLOB_RECURSION_LIMIT: usize = 100; const FIXED_POINT_LIMIT: usize = 8192; -pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeId) -> DefMap { - let crate_graph = db.crate_graph(); - - let krate = &crate_graph[def_map.krate]; +pub(super) fn collect_defs( + db: &dyn DefDatabase, + def_map: DefMap, + tree_id: TreeId, + crate_local_def_map: Option>, +) -> (DefMap, LocalDefMap) { + let krate = &def_map.krate.data(db); + let cfg_options = def_map.krate.cfg_options(db); // populate external prelude and dependency list let mut deps = @@ -72,8 +76,10 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI } let proc_macros = if krate.is_proc_macro { - db.proc_macros() - .for_crate(def_map.krate, db.syntax_context(tree_id.file_id(), krate.edition)) + db.proc_macros_for_crate(def_map.krate) + .and_then(|proc_macros| { + proc_macros.list(db.syntax_context(tree_id.file_id(), krate.edition)) + }) .unwrap_or_default() } else { Default::default() @@ -82,13 +88,15 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI let mut collector = DefCollector { db, def_map, + local_def_map: LocalDefMap::default(), + crate_local_def_map, deps, glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), indeterminate_imports: Vec::new(), unresolved_macros: Vec::new(), mod_dirs: FxHashMap::default(), - cfg_options: &krate.cfg_options, + cfg_options, proc_macros, from_glob_import: Default::default(), skip_attrs: Default::default(), @@ -101,9 +109,10 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI collector.seed_with_top_level(); } collector.collect(); - let mut def_map = collector.finish(); + let (mut def_map, mut local_def_map) = collector.finish(); def_map.shrink_to_fit(); - def_map + local_def_map.shrink_to_fit(); + (def_map, local_def_map) } #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -205,8 +214,11 @@ enum MacroDirectiveKind { struct DefCollector<'a> { db: &'a dyn DefDatabase, def_map: DefMap, + local_def_map: LocalDefMap, + /// Set only in case of blocks. + crate_local_def_map: Option>, // The dependencies of the current crate, including optional deps like `test`. - deps: FxHashMap, + deps: FxHashMap, glob_imports: FxHashMap>, unresolved_imports: Vec, indeterminate_imports: Vec<(ImportDirective, PerNs)>, @@ -238,8 +250,7 @@ impl DefCollector<'_> { fn seed_with_top_level(&mut self) { let _p = tracing::info_span!("seed_with_top_level").entered(); - let crate_graph = self.db.crate_graph(); - let file_id = crate_graph[self.def_map.krate].root_file_id(); + let file_id = self.def_map.krate.data(self.db).root_file_id(); let item_tree = self.db.file_item_tree(file_id.into()); let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate); let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap(); @@ -310,20 +321,24 @@ impl DefCollector<'_> { // don't do pre-configured attribute resolution yet. // So here check if we are no_core / no_std and we are trying to add the // corresponding dep from the sysroot - let skip = match crate_graph[dep.crate_id].origin { - CrateOrigin::Lang(LangCrateOrigin::Core) => { - crate_data.no_core && dep.is_sysroot() - } - CrateOrigin::Lang(LangCrateOrigin::Std) => { - crate_data.no_std && dep.is_sysroot() - } - _ => false, - }; + + // Depending on the crate data of a dependency seems bad for incrementality, but + // we only do that for sysroot crates (this is why the order of the `&&` is important) + // - which are normally standard library crate, which realistically aren't going + // to have their crate ID invalidated, because they stay on the same root file and + // they're dependencies of everything else, so if some collision miraculously occurs + // we will resolve it by disambiguating the other crate. + let skip = dep.is_sysroot() + && match dep.crate_id.data(self.db).origin { + CrateOrigin::Lang(LangCrateOrigin::Core) => crate_data.no_core, + CrateOrigin::Lang(LangCrateOrigin::Std) => crate_data.no_std, + _ => false, + }; if skip { continue; } - crate_data + self.local_def_map .extern_prelude .insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None)); } @@ -494,7 +509,7 @@ impl DefCollector<'_> { let krate = if self.def_map.data.no_std { Name::new_symbol_root(sym::core.clone()) - } else if self.def_map.extern_prelude().any(|(name, _)| *name == sym::std.clone()) { + } else if self.local_def_map().extern_prelude().any(|(name, _)| *name == sym::std.clone()) { Name::new_symbol_root(sym::std.clone()) } else { // If `std` does not exist for some reason, fall back to core. This mostly helps @@ -518,8 +533,14 @@ impl DefCollector<'_> { [krate, Name::new_symbol_root(sym::prelude.clone()), edition], ); - let (per_ns, _) = - self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None); + let (per_ns, _) = self.def_map.resolve_path( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), + self.db, + DefMap::ROOT, + &path, + BuiltinShadowMode::Other, + None, + ); match per_ns.types { Some(Item { def: ModuleDefId::ModuleId(m), import, .. }) => { @@ -535,6 +556,10 @@ impl DefCollector<'_> { } } + fn local_def_map(&mut self) -> &LocalDefMap { + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map) + } + /// Adds a definition of procedural macro `name` to the root module. /// /// # Notes on procedural macro resolution @@ -660,7 +685,13 @@ impl DefCollector<'_> { ) { let vis = self .def_map - .resolve_visibility(self.db, module_id, vis, false) + .resolve_visibility( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), + self.db, + module_id, + vis, + false, + ) .unwrap_or(Visibility::Public); self.def_map.modules[module_id].scope.declare(macro_.into()); self.update( @@ -694,7 +725,7 @@ impl DefCollector<'_> { /// created by `use` in the root module, ignoring the visibility of `use`. fn import_macros_from_extern_crate( &mut self, - krate: CrateId, + krate: Crate, names: Option>, extern_crate: Option, ) { @@ -779,6 +810,7 @@ impl DefCollector<'_> { .entered(); tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition); let res = self.def_map.resolve_path_fp_with_macro( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), self.db, ResolveMode::Import, module_id, @@ -814,7 +846,13 @@ impl DefCollector<'_> { let mut def = directive.status.namespaces(); let vis = self .def_map - .resolve_visibility(self.db, module_id, &directive.import.visibility, false) + .resolve_visibility( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), + self.db, + module_id, + &directive.import.visibility, + false, + ) .unwrap_or(Visibility::Public); match import.source { @@ -1210,6 +1248,7 @@ impl DefCollector<'_> { }; let resolver = |path: &_| { let resolved_res = self.def_map.resolve_path_fp_with_macro( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), self.db, ResolveMode::Other, directive.module_id, @@ -1495,7 +1534,7 @@ impl DefCollector<'_> { .collect(item_tree.top_level_items(), container); } - fn finish(mut self) -> DefMap { + fn finish(mut self) -> (DefMap, LocalDefMap) { // Emit diagnostics for all remaining unexpanded macros. let _p = tracing::info_span!("DefCollector::finish").entered(); @@ -1511,6 +1550,7 @@ impl DefCollector<'_> { self.def_map.krate, |path| { let resolved_res = self.def_map.resolve_path_fp_with_macro( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), self.db, ResolveMode::Other, directive.module_id, @@ -1582,7 +1622,7 @@ impl DefCollector<'_> { )); } - self.def_map + (self.def_map, self.local_def_map) } } @@ -1635,9 +1675,9 @@ impl ModCollector<'_, '_> { None, ) }; - let resolve_vis = |def_map: &DefMap, visibility| { + let resolve_vis = |def_map: &DefMap, local_def_map: &LocalDefMap, visibility| { def_map - .resolve_visibility(db, module_id, visibility, false) + .resolve_visibility(local_def_map, db, module_id, visibility, false) .unwrap_or(Visibility::Public) }; @@ -1658,6 +1698,11 @@ impl ModCollector<'_, '_> { let module = self.def_collector.def_map.module_id(module_id); let def_map = &mut self.def_collector.def_map; + let local_def_map = self + .def_collector + .crate_local_def_map + .as_deref() + .unwrap_or(&self.def_collector.local_def_map); match item { ModItem::Mod(m) => self.collect_module(m, &attrs), @@ -1711,13 +1756,13 @@ impl ModCollector<'_, '_> { }; if let Some(resolved) = resolved { - let vis = resolve_vis(def_map, &self.item_tree[*visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[*visibility]); if is_crate_root { // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 if let Some(name) = name { - Arc::get_mut(&mut def_map.data) - .unwrap() + self.def_collector + .local_def_map .extern_prelude .insert(name.clone(), (resolved, Some(id))); } @@ -1784,7 +1829,7 @@ impl ModCollector<'_, '_> { let fn_id = FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db); - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); if self.def_collector.def_map.block.is_none() && self.def_collector.is_proc_macro @@ -1804,7 +1849,7 @@ impl ModCollector<'_, '_> { ModItem::Struct(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } @@ -1818,7 +1863,7 @@ impl ModCollector<'_, '_> { ModItem::Union(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } @@ -1835,7 +1880,7 @@ impl ModCollector<'_, '_> { EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } .intern(db); - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def(self.def_collector, enum_.into(), &it.name, vis, false); let mut index = 0; @@ -1878,7 +1923,8 @@ impl ModCollector<'_, '_> { match &it.name { Some(name) => { - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = + resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def(self.def_collector, const_id.into(), name, vis, false); } None => { @@ -1892,7 +1938,7 @@ impl ModCollector<'_, '_> { ModItem::Static(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) } @@ -1906,7 +1952,7 @@ impl ModCollector<'_, '_> { ModItem::Trait(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } @@ -1920,7 +1966,7 @@ impl ModCollector<'_, '_> { ModItem::TraitAlias(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, TraitAliasLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } @@ -1934,7 +1980,7 @@ impl ModCollector<'_, '_> { ModItem::TypeAlias(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) } @@ -1971,7 +2017,7 @@ impl ModCollector<'_, '_> { &mut self, extern_crate_id: ExternCrateId, macro_use_attrs: impl Iterator, - target_crate: CrateId, + target_crate: Crate, ) { cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); let mut single_imports = Vec::new(); @@ -2115,7 +2161,16 @@ impl ModCollector<'_, '_> { ) -> LocalModuleId { let def_map = &mut self.def_collector.def_map; let vis = def_map - .resolve_visibility(self.def_collector.db, self.module_id, visibility, false) + .resolve_visibility( + self.def_collector + .crate_local_def_map + .as_deref() + .unwrap_or(&self.def_collector.local_def_map), + self.def_collector.db, + self.module_id, + visibility, + false, + ) .unwrap_or(Visibility::Public); let origin = match definition { None => ModuleOrigin::Inline { @@ -2417,6 +2472,10 @@ impl ModCollector<'_, '_> { }, |path| { let resolved_res = self.def_collector.def_map.resolve_path_fp_with_macro( + self.def_collector + .crate_local_def_map + .as_deref() + .unwrap_or(&self.def_collector.local_def_map), db, ResolveMode::Other, self.module_id, @@ -2517,7 +2576,6 @@ impl ModCollector<'_, '_> { #[cfg(test)] mod tests { - use base_db::RootQueryDb; use test_fixture::WithFixture; use crate::{nameres::DefMapCrateData, test_db::TestDB}; @@ -2528,6 +2586,8 @@ mod tests { let mut collector = DefCollector { db, def_map, + local_def_map: LocalDefMap::default(), + crate_local_def_map: None, deps: FxHashMap::default(), glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), @@ -2550,7 +2610,7 @@ mod tests { let (db, file_id) = TestDB::with_single_file(not_ra_fixture); let krate = db.test_crate(); - let edition = db.crate_graph()[krate].edition; + let edition = krate.data(&db).edition; let module_origin = ModuleOrigin::CrateRoot { definition: file_id }; let def_map = DefMap::empty( krate, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs index 47c08d3d1dc67..977bc16adf7ee 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs @@ -19,7 +19,7 @@ use crate::{ db::DefDatabase, item_scope::{ImportOrExternCrate, BUILTIN_SCOPE}, item_tree::FieldsShape, - nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs}, + nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs}, path::{ModPath, PathKind}, per_ns::PerNs, visibility::{RawVisibility, Visibility}, @@ -91,6 +91,7 @@ impl PerNs { impl DefMap { pub(crate) fn resolve_visibility( &self, + local_def_map: &LocalDefMap, db: &dyn DefDatabase, // module to import to original_module: LocalModuleId, @@ -101,8 +102,14 @@ impl DefMap { ) -> Option { let mut vis = match visibility { RawVisibility::Module(path, explicitness) => { - let (result, remaining) = - self.resolve_path(db, original_module, path, BuiltinShadowMode::Module, None); + let (result, remaining) = self.resolve_path( + local_def_map, + db, + original_module, + path, + BuiltinShadowMode::Module, + None, + ); if remaining.is_some() { return None; } @@ -137,6 +144,7 @@ impl DefMap { // the result. pub(super) fn resolve_path_fp_with_macro( &self, + local_def_map: &LocalDefMap, db: &dyn DefDatabase, mode: ResolveMode, // module to import to @@ -148,6 +156,7 @@ impl DefMap { expected_macro_subns: Option, ) -> ResolvePathResult { let mut result = self.resolve_path_fp_with_macro_single( + local_def_map, db, mode, original_module, @@ -196,6 +205,7 @@ impl DefMap { current_map = &arc; let new = current_map.resolve_path_fp_in_all_preludes( + local_def_map, db, mode, original_module, @@ -210,6 +220,7 @@ impl DefMap { } let new = current_map.resolve_path_fp_with_macro_single( + local_def_map, db, mode, original_module, @@ -224,6 +235,7 @@ impl DefMap { pub(super) fn resolve_path_fp_with_macro_single( &self, + local_def_map: &LocalDefMap, db: &dyn DefDatabase, mode: ResolveMode, original_module: LocalModuleId, @@ -258,7 +270,12 @@ impl DefMap { None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; tracing::debug!("resolving {:?} in crate root (+ extern prelude)", segment); - self.resolve_name_in_crate_root_or_extern_prelude(db, original_module, segment) + self.resolve_name_in_crate_root_or_extern_prelude( + local_def_map, + db, + original_module, + segment, + ) } PathKind::Plain => { let (_, segment) = match segments.next() { @@ -276,6 +293,7 @@ impl DefMap { tracing::debug!("resolving {:?} in module", segment); self.resolve_name_in_module( + local_def_map, db, original_module, segment, @@ -321,7 +339,9 @@ impl DefMap { // with), resolve the remaining path segments in that `DefMap`. let path = ModPath::from_segments(PathKind::SELF, path.segments().iter().cloned()); + // This is the same crate, so the local def map is the same. return def_map.resolve_path_fp_with_macro( + local_def_map, db, mode, local_id, @@ -333,7 +353,7 @@ impl DefMap { PerNs::types(module.into(), Visibility::Public, None) } - PathKind::Abs => match self.resolve_path_abs(&mut segments, path) { + PathKind::Abs => match self.resolve_path_abs(local_def_map, &mut segments, path) { Either::Left(it) => it, Either::Right(reached_fixed_point) => { return ResolvePathResult::empty(reached_fixed_point) @@ -347,6 +367,7 @@ impl DefMap { /// Resolves a path only in the preludes, without accounting for item scopes. pub(super) fn resolve_path_fp_in_all_preludes( &self, + local_def_map: &LocalDefMap, db: &dyn DefDatabase, mode: ResolveMode, original_module: LocalModuleId, @@ -368,7 +389,7 @@ impl DefMap { None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; tracing::debug!("resolving {:?} in crate root (+ extern prelude)", segment); - self.resolve_name_in_extern_prelude(segment) + self.resolve_name_in_extern_prelude(local_def_map, segment) } PathKind::Plain => { let (_, segment) = match segments.next() { @@ -376,9 +397,9 @@ impl DefMap { None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; tracing::debug!("resolving {:?} in module", segment); - self.resolve_name_in_all_preludes(db, segment) + self.resolve_name_in_all_preludes(local_def_map, db, segment) } - PathKind::Abs => match self.resolve_path_abs(&mut segments, path) { + PathKind::Abs => match self.resolve_path_abs(local_def_map, &mut segments, path) { Either::Left(it) => it, Either::Right(reached_fixed_point) => { return ResolvePathResult::empty(reached_fixed_point) @@ -395,6 +416,7 @@ impl DefMap { /// 2018-style absolute path -- only extern prelude fn resolve_path_abs<'a>( &self, + local_def_map: &LocalDefMap, segments: &mut impl Iterator, path: &ModPath, ) -> Either { @@ -402,7 +424,7 @@ impl DefMap { Some((_, segment)) => segment, None => return Either::Right(ReachedFixedPoint::Yes), }; - if let Some(&(def, extern_crate)) = self.data.extern_prelude.get(segment) { + if let Some(&(def, extern_crate)) = local_def_map.extern_prelude.get(segment) { tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def); Either::Left(PerNs::types( def.into(), @@ -451,6 +473,7 @@ impl DefMap { // this point, we know we're resolving a multi-segment path so macro kind // expectation is discarded. let resolution = defp_map.resolve_path_fp_with_macro( + LocalDefMap::EMPTY, db, ResolveMode::Other, module.local_id, @@ -568,6 +591,7 @@ impl DefMap { fn resolve_name_in_module( &self, + local_def_map: &LocalDefMap, db: &dyn DefDatabase, module: LocalModuleId, name: &Name, @@ -611,7 +635,7 @@ impl DefMap { // they might been shadowed by local names. return PerNs::none(); } - self.resolve_name_in_extern_prelude(name) + self.resolve_name_in_extern_prelude(local_def_map, name) }; let macro_use_prelude = || self.resolve_in_macro_use_prelude(name); let prelude = || { @@ -628,19 +652,24 @@ impl DefMap { .or_else(prelude) } - fn resolve_name_in_all_preludes(&self, db: &dyn DefDatabase, name: &Name) -> PerNs { + fn resolve_name_in_all_preludes( + &self, + local_def_map: &LocalDefMap, + db: &dyn DefDatabase, + name: &Name, + ) -> PerNs { // Resolve in: // - extern prelude / macro_use prelude // - std prelude - let extern_prelude = self.resolve_name_in_extern_prelude(name); + let extern_prelude = self.resolve_name_in_extern_prelude(local_def_map, name); let macro_use_prelude = || self.resolve_in_macro_use_prelude(name); let prelude = || self.resolve_in_prelude(db, name); extern_prelude.or_else(macro_use_prelude).or_else(prelude) } - fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { - self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| { + fn resolve_name_in_extern_prelude(&self, local_def_map: &LocalDefMap, name: &Name) -> PerNs { + local_def_map.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| { PerNs::types( it.into(), Visibility::Public, @@ -662,6 +691,7 @@ impl DefMap { fn resolve_name_in_crate_root_or_extern_prelude( &self, + local_def_map: &LocalDefMap, db: &dyn DefDatabase, module: LocalModuleId, name: &Name, @@ -678,7 +708,7 @@ impl DefMap { // Don't resolve extern prelude in pseudo-module of a block. return PerNs::none(); } - self.resolve_name_in_extern_prelude(name) + self.resolve_name_in_extern_prelude(local_def_map, name) }; from_crate_root.or_else(from_extern_prelude) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs index cd590205766da..9a601e0f01384 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs @@ -1,5 +1,11 @@ -use base_db::SourceDatabase; +use base_db::{ + CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData, + DependencyBuilder, Env, RootQueryDb, SourceDatabase, +}; +use intern::Symbol; +use span::Edition; use test_fixture::WithFixture; +use triomphe::Arc; use crate::{db::DefDatabase, nameres::tests::TestDB, AdtId, ModuleDefId}; @@ -22,6 +28,73 @@ fn check_def_map_is_not_recomputed(ra_fixture_initial: &str, ra_fixture_change: } } +#[test] +fn crate_metadata_changes_should_not_invalidate_unrelated_def_maps() { + let (mut db, files) = TestDB::with_many_files( + r#" +//- /a.rs crate:a +pub fn foo() {} + +//- /b.rs crate:b +pub struct Bar; + +//- /c.rs crate:c deps:b +pub const BAZ: u32 = 0; + "#, + ); + + for &krate in db.all_crates().iter() { + db.crate_def_map(krate); + } + + let all_crates_before = db.all_crates(); + + { + // Add a dependency a -> b. + let mut new_crate_graph = CrateGraphBuilder::default(); + let mut add_crate = |crate_name, root_file_idx: usize| { + new_crate_graph.add_crate_root( + files[root_file_idx].file_id(), + Edition::CURRENT, + Some(CrateDisplayName::from_canonical_name(crate_name)), + None, + Arc::default(), + None, + Env::default(), + CrateOrigin::Local { repo: None, name: Some(Symbol::intern(crate_name)) }, + false, + None, + Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None }), + ) + }; + let a = add_crate("a", 0); + let b = add_crate("b", 1); + let c = add_crate("c", 2); + new_crate_graph + .add_dep(c, DependencyBuilder::new(CrateName::new("b").unwrap(), b)) + .unwrap(); + new_crate_graph + .add_dep(b, DependencyBuilder::new(CrateName::new("a").unwrap(), a)) + .unwrap(); + new_crate_graph.set_in_db(&mut db); + } + + let all_crates_after = db.all_crates(); + assert!( + Arc::ptr_eq(&all_crates_before, &all_crates_after), + "the all_crates list should not have been invalidated" + ); + + let events = db.log_executed(|| { + for &krate in db.all_crates().iter() { + db.crate_def_map(krate); + } + }); + let invalidated_def_maps = + events.iter().filter(|event| event.contains("crate_def_map")).count(); + assert_eq!(invalidated_def_maps, 1, "{events:#?}") +} + #[test] fn typing_inside_a_function_should_not_invalidate_def_map() { check_def_map_is_not_recomputed( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs index 610886d55f40f..0348a7076a8d0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs @@ -1095,7 +1095,7 @@ pub fn derive_macro_2(_item: TokenStream) -> TokenStream { } "#, ); - let krate = db.crate_graph().iter().next().unwrap(); + let krate = *db.all_crates().last().unwrap(); let def_map = db.crate_def_map(krate); assert_eq!(def_map.data.exported_derives.len(), 1); @@ -1445,7 +1445,7 @@ struct TokenStream; fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a } "#, ); - let krate = db.crate_graph().iter().next().unwrap(); + let krate = *db.all_crates().last().unwrap(); let def_map = db.crate_def_map(krate); let root_module = &def_map[DefMap::ROOT].scope; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs index eb9488feaa914..c431b45dc79cd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs @@ -80,7 +80,16 @@ pub(crate) fn print_path( } PathKind::Crate => write!(buf, "crate")?, PathKind::Abs => {} - PathKind::DollarCrate(_) => write!(buf, "$crate")?, + PathKind::DollarCrate(krate) => write!( + buf, + "{}", + krate + .extra_data(db) + .display_name + .as_ref() + .map(|it| it.crate_name().symbol().as_str()) + .unwrap_or("$crate") + )?, }, } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index f4773de08555b..72723499fc973 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -1,7 +1,7 @@ //! Name resolution façade. use std::{fmt, iter, mem}; -use base_db::CrateId; +use base_db::Crate; use hir_expand::{name::Name, MacroDefId}; use intern::{sym, Symbol}; use itertools::Itertools as _; @@ -22,7 +22,7 @@ use crate::{ hir::{BindingId, ExprId, LabelId}, item_scope::{BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, BUILTIN_SCOPE}, lang_item::LangItemTarget, - nameres::{DefMap, MacroSubNs, ResolvePathResultPrefixInfo}, + nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo}, path::{ModPath, Path, PathKind}, per_ns::PerNs, type_ref::{LifetimeRef, TypesMap}, @@ -47,6 +47,7 @@ pub struct Resolver { #[derive(Clone)] struct ModuleItemMap { def_map: Arc, + local_def_map: Arc, module_id: LocalModuleId, } @@ -278,8 +279,8 @@ impl Resolver { let within_impl = self.scopes().any(|scope| matches!(scope, Scope::ImplDefScope(_))); match visibility { RawVisibility::Module(_, _) => { - let (item_map, module) = self.item_scope(); - item_map.resolve_visibility(db, module, visibility, within_impl) + let (item_map, item_local_map, module) = self.item_scope(); + item_map.resolve_visibility(item_local_map, db, module, visibility, within_impl) } RawVisibility::Public => Some(Visibility::Public), } @@ -474,9 +475,16 @@ impl Resolver { path: &ModPath, expected_macro_kind: Option, ) -> Option<(MacroId, Option)> { - let (item_map, module) = self.item_scope(); + let (item_map, item_local_map, module) = self.item_scope(); item_map - .resolve_path(db, module, path, BuiltinShadowMode::Other, expected_macro_kind) + .resolve_path( + item_local_map, + db, + module, + path, + BuiltinShadowMode::Other, + expected_macro_kind, + ) .0 .take_macros_import() } @@ -550,7 +558,7 @@ impl Resolver { for scope in self.scopes() { scope.process_names(&mut res, db); } - let ModuleItemMap { ref def_map, module_id } = self.module_scope; + let ModuleItemMap { ref def_map, module_id, ref local_def_map } = self.module_scope; // FIXME: should we provide `self` here? // f( // Name::self_param(), @@ -572,7 +580,7 @@ impl Resolver { res.add(name, ScopeDef::ModuleDef(def.into())); }, ); - def_map.extern_prelude().for_each(|(name, (def, _extern_crate))| { + local_def_map.extern_prelude().for_each(|(name, (def, _extern_crate))| { res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def.into()))); }); BUILTIN_SCOPE.iter().for_each(|(name, &def)| { @@ -599,7 +607,7 @@ impl Resolver { pub fn extern_crates_in_scope(&self) -> impl Iterator + '_ { self.module_scope - .def_map + .local_def_map .extern_prelude() .map(|(name, module_id)| (name.clone(), module_id.0.into())) } @@ -647,11 +655,11 @@ impl Resolver { } pub fn module(&self) -> ModuleId { - let (def_map, local_id) = self.item_scope(); + let (def_map, _, local_id) = self.item_scope(); def_map.module_id(local_id) } - pub fn krate(&self) -> CrateId { + pub fn krate(&self) -> Crate { self.module_scope.def_map.krate() } @@ -844,9 +852,12 @@ impl Resolver { })); if let Some(block) = expr_scopes.block(scope_id) { let def_map = db.block_def_map(block); - resolver - .scopes - .push(Scope::BlockScope(ModuleItemMap { def_map, module_id: DefMap::ROOT })); + let local_def_map = block.lookup(db).module.only_local_def_map(db); + resolver.scopes.push(Scope::BlockScope(ModuleItemMap { + def_map, + local_def_map, + module_id: DefMap::ROOT, + })); // FIXME: This adds as many module scopes as there are blocks, but resolving in each // already traverses all parents, so this is O(n²). I think we could only store the // innermost module scope instead? @@ -933,9 +944,10 @@ impl Resolver { path: &ModPath, shadow: BuiltinShadowMode, ) -> PerNs { - let (item_map, module) = self.item_scope(); + let (item_map, item_local_map, module) = self.item_scope(); // This method resolves `path` just like import paths, so no expected macro subns is given. - let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow, None); + let (module_res, segment_index) = + item_map.resolve_path(item_local_map, db, module, path, shadow, None); if segment_index.is_some() { return PerNs::none(); } @@ -943,13 +955,17 @@ impl Resolver { } /// The innermost block scope that contains items or the module scope that contains this resolver. - fn item_scope(&self) -> (&DefMap, LocalModuleId) { + fn item_scope(&self) -> (&DefMap, &LocalDefMap, LocalModuleId) { self.scopes() .find_map(|scope| match scope { - Scope::BlockScope(m) => Some((&*m.def_map, m.module_id)), + Scope::BlockScope(m) => Some((&*m.def_map, &*m.local_def_map, m.module_id)), _ => None, }) - .unwrap_or((&self.module_scope.def_map, self.module_scope.module_id)) + .unwrap_or(( + &self.module_scope.def_map, + &self.module_scope.local_def_map, + self.module_scope.module_id, + )) } } @@ -1050,7 +1066,8 @@ fn resolver_for_scope_( for scope in scope_chain.into_iter().rev() { if let Some(block) = scopes.block(scope) { let def_map = db.block_def_map(block); - r = r.push_block_scope(def_map); + let local_def_map = block.lookup(db).module.only_local_def_map(db); + r = r.push_block_scope(def_map, local_def_map); // FIXME: This adds as many module scopes as there are blocks, but resolving in each // already traverses all parents, so this is O(n²). I think we could only store the // innermost module scope instead? @@ -1079,9 +1096,12 @@ impl Resolver { self.push_scope(Scope::ImplDefScope(impl_def)) } - fn push_block_scope(self, def_map: Arc) -> Resolver { - debug_assert!(def_map.block_id().is_some()); - self.push_scope(Scope::BlockScope(ModuleItemMap { def_map, module_id: DefMap::ROOT })) + fn push_block_scope(self, def_map: Arc, local_def_map: Arc) -> Resolver { + self.push_scope(Scope::BlockScope(ModuleItemMap { + def_map, + local_def_map, + module_id: DefMap::ROOT, + })) } fn push_expr_scope( @@ -1100,8 +1120,13 @@ impl ModuleItemMap { db: &dyn DefDatabase, path: &ModPath, ) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo)> { - let (module_def, unresolved_idx, prefix_info) = - self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); + let (module_def, unresolved_idx, prefix_info) = self.def_map.resolve_path_locally( + &self.local_def_map, + db, + self.module_id, + path, + BuiltinShadowMode::Other, + ); match unresolved_idx { None => { let (value, import) = to_value_ns(module_def)?; @@ -1134,8 +1159,13 @@ impl ModuleItemMap { path: &ModPath, ) -> Option<(TypeNs, Option, Option, ResolvePathResultPrefixInfo)> { - let (module_def, idx, prefix_info) = - self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); + let (module_def, idx, prefix_info) = self.def_map.resolve_path_locally( + &self.local_def_map, + db, + self.module_id, + path, + BuiltinShadowMode::Other, + ); let (res, import) = to_type_ns(module_def)?; Some((res, idx, import, prefix_info)) } @@ -1230,11 +1260,14 @@ pub trait HasResolver: Copy { impl HasResolver for ModuleId { fn resolver(self, db: &dyn DefDatabase) -> Resolver { - let mut def_map = self.def_map(db); + let (mut def_map, local_def_map) = self.local_def_map(db); let mut module_id = self.local_id; if !self.is_block_module() { - return Resolver { scopes: vec![], module_scope: ModuleItemMap { def_map, module_id } }; + return Resolver { + scopes: vec![], + module_scope: ModuleItemMap { def_map, local_def_map, module_id }, + }; } let mut modules: SmallVec<[_; 1]> = smallvec![]; @@ -1248,10 +1281,14 @@ impl HasResolver for ModuleId { } let mut resolver = Resolver { scopes: Vec::with_capacity(modules.len()), - module_scope: ModuleItemMap { def_map, module_id }, + module_scope: ModuleItemMap { + def_map, + local_def_map: local_def_map.clone(), + module_id, + }, }; for def_map in modules.into_iter().rev() { - resolver = resolver.push_block_scope(def_map); + resolver = resolver.push_block_scope(def_map, local_def_map.clone()); } resolver } @@ -1259,9 +1296,10 @@ impl HasResolver for ModuleId { impl HasResolver for CrateRootModuleId { fn resolver(self, db: &dyn DefDatabase) -> Resolver { + let (def_map, local_def_map) = self.local_def_map(db); Resolver { scopes: vec![], - module_scope: ModuleItemMap { def_map: self.def_map(db), module_id: DefMap::ROOT }, + module_scope: ModuleItemMap { def_map, local_def_map, module_id: DefMap::ROOT }, } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/src.rs b/src/tools/rust-analyzer/crates/hir-def/src/src.rs index c7ebfeecf5141..43d31aa503ce0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/src.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/src.rs @@ -158,7 +158,7 @@ impl HasChildSource for VariantId { let mut map = ArenaMap::new(); match &src.value { ast::StructKind::Tuple(fl) => { - let cfg_options = &db.crate_graph()[container.krate].cfg_options; + let cfg_options = container.krate.cfg_options(db); let mut idx = 0; for (i, fd) in fl.fields().enumerate() { let attrs = item_tree.attrs( @@ -177,7 +177,7 @@ impl HasChildSource for VariantId { } } ast::StructKind::Record(fl) => { - let cfg_options = &db.crate_graph()[container.krate].cfg_options; + let cfg_options = container.krate.cfg_options(db); let mut idx = 0; for (i, fd) in fl.fields().enumerate() { let attrs = item_tree.attrs( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs index b6f08c0cafdbb..0b97e6c9ce5b9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs @@ -3,8 +3,8 @@ use std::{fmt, panic, sync::Mutex}; use base_db::{ - CrateId, FileSourceRootInput, FileText, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId, - SourceRootInput, Upcast, + Crate, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, RootQueryDb, + SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, Upcast, }; use hir_expand::{db::ExpandDatabase, files::FilePosition, InFile}; use salsa::{AsDynDatabase, Durability}; @@ -24,6 +24,7 @@ use crate::{ pub(crate) struct TestDB { storage: salsa::Storage, files: Arc, + crates_map: Arc, events: Arc>>>, } @@ -33,8 +34,12 @@ impl Default for TestDB { storage: Default::default(), events: Default::default(), files: Default::default(), + crates_map: Default::default(), }; this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); + // This needs to be here otherwise `CrateGraphBuilder` panics. + this.set_all_crates(Arc::new(Box::new([]))); + CrateGraphBuilder::default().set_in_db(&mut this); this } } @@ -133,20 +138,23 @@ impl SourceDatabase for TestDB { let files = Arc::clone(&self.files); files.set_file_source_root_with_durability(self, id, source_root_id, durability); } + + fn crates_map(&self) -> Arc { + self.crates_map.clone() + } } impl TestDB { - pub(crate) fn fetch_test_crate(&self) -> CrateId { - let crate_graph = self.crate_graph(); - let it = crate_graph + pub(crate) fn fetch_test_crate(&self) -> Crate { + let all_crates = self.all_crates(); + all_crates .iter() - .find(|&idx| { - crate_graph[idx].display_name.as_ref().map(|it| it.canonical_name().as_str()) + .copied() + .find(|&krate| { + krate.extra_data(self).display_name.as_ref().map(|it| it.canonical_name().as_str()) == Some("ra_test_fixture") }) - .or_else(|| crate_graph.iter().next()) - .unwrap(); - it + .unwrap_or(*all_crates.last().unwrap()) } pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index c9c793d54f26c..64b9b49b3e472 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -1,7 +1,7 @@ //! A higher level attributes based on TokenTree, with also some shortcuts. use std::{borrow::Cow, fmt, ops}; -use base_db::CrateId; +use base_db::Crate; use cfg::CfgExpr; use either::Either; use intern::{sym, Interned, Symbol}; @@ -119,7 +119,7 @@ impl RawAttrs { /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`. // FIXME: This should return a different type, signaling it was filtered? - pub fn filter(self, db: &dyn ExpandDatabase, krate: CrateId) -> RawAttrs { + pub fn filter(self, db: &dyn ExpandDatabase, krate: Crate) -> RawAttrs { let has_cfg_attrs = self .iter() .any(|attr| attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr.clone())); @@ -127,7 +127,7 @@ impl RawAttrs { return self; } - let crate_graph = db.crate_graph(); + let cfg_options = krate.cfg_options(db); let new_attrs = self.iter() .flat_map(|attr| -> SmallVec<[_; 1]> { @@ -151,7 +151,6 @@ impl RawAttrs { |(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)), ); - let cfg_options = &crate_graph[krate].cfg_options; let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg); let cfg = CfgExpr::parse(&cfg); if cfg_options.check(&cfg) == Some(false) { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs index d8b3f40e8f413..b56ec3d04c07e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs @@ -231,7 +231,7 @@ fn assert_expand( let cond = expect_fragment( &mut iter, parser::PrefixEntryPoint::Expr, - db.crate_graph()[id.lookup(db).krate].edition, + id.lookup(db).krate.data(db).edition, tt.top_subtree().delimiter.delim_span(), ); _ = iter.expect_char(','); @@ -333,7 +333,7 @@ fn cfg_expand( ) -> ExpandResult { let loc = db.lookup_intern_macro_call(id); let expr = CfgExpr::parse(tt); - let enabled = db.crate_graph()[loc.krate].cfg_options.check(&expr) != Some(false); + let enabled = loc.krate.cfg_options(db).check(&expr) != Some(false); let expanded = if enabled { quote!(span=>true) } else { quote!(span=>false) }; ExpandResult::ok(expanded) } @@ -669,7 +669,7 @@ fn relative_file( if res == call_site && !allow_recursion { Err(ExpandError::other(err_span, format!("recursive inclusion of `{path_str}`"))) } else { - Ok(EditionedFileId::new(res, db.crate_graph()[lookup.krate].edition)) + Ok(EditionedFileId::new(res, lookup.krate.data(db).edition)) } } @@ -812,7 +812,7 @@ fn include_str_expand( fn get_env_inner(db: &dyn ExpandDatabase, arg_id: MacroCallId, key: &Symbol) -> Option { let krate = db.lookup_intern_macro_call(arg_id).krate; - db.crate_graph()[krate].env.get(key.as_str()) + krate.env(db).get(key.as_str()) } fn env_expand( diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs index 626a82ae08eab..0ceab3c890217 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs @@ -1,7 +1,7 @@ //! Processes out #[cfg] and #[cfg_attr] attributes from the input for the derive macro use std::iter::Peekable; -use base_db::CrateId; +use base_db::Crate; use cfg::{CfgAtom, CfgExpr}; use intern::{sym, Symbol}; use rustc_hash::FxHashSet; @@ -13,16 +13,16 @@ use tracing::{debug, warn}; use crate::{db::ExpandDatabase, proc_macro::ProcMacroKind, MacroCallLoc, MacroDefKind}; -fn check_cfg(db: &dyn ExpandDatabase, attr: &Attr, krate: CrateId) -> Option { +fn check_cfg(db: &dyn ExpandDatabase, attr: &Attr, krate: Crate) -> Option { if !attr.simple_name().as_deref().map(|v| v == "cfg")? { return None; } let cfg = parse_from_attr_token_tree(&attr.meta()?.token_tree()?)?; - let enabled = db.crate_graph()[krate].cfg_options.check(&cfg) != Some(false); + let enabled = krate.cfg_options(db).check(&cfg) != Some(false); Some(enabled) } -fn check_cfg_attr(db: &dyn ExpandDatabase, attr: &Attr, krate: CrateId) -> Option { +fn check_cfg_attr(db: &dyn ExpandDatabase, attr: &Attr, krate: Crate) -> Option { if !attr.simple_name().as_deref().map(|v| v == "cfg_attr")? { return None; } @@ -32,17 +32,17 @@ fn check_cfg_attr(db: &dyn ExpandDatabase, attr: &Attr, krate: CrateId) -> Optio pub fn check_cfg_attr_value( db: &dyn ExpandDatabase, attr: &TokenTree, - krate: CrateId, + krate: Crate, ) -> Option { let cfg_expr = parse_from_attr_token_tree(attr)?; - let enabled = db.crate_graph()[krate].cfg_options.check(&cfg_expr) != Some(false); + let enabled = krate.cfg_options(db).check(&cfg_expr) != Some(false); Some(enabled) } fn process_has_attrs_with_possible_comma( db: &dyn ExpandDatabase, items: impl Iterator, - krate: CrateId, + krate: Crate, remove: &mut FxHashSet, ) -> Option<()> { for item in items { @@ -144,7 +144,7 @@ fn remove_possible_comma(item: &impl AstNode, res: &mut FxHashSet fn process_enum( db: &dyn ExpandDatabase, variants: VariantList, - krate: CrateId, + krate: Crate, remove: &mut FxHashSet, ) -> Option<()> { 'variant: for variant in variants.variants() { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs index 7a42d6626010b..3f5b8fdc9bd5e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs @@ -1,17 +1,16 @@ //! Defines a unit of change that can applied to the database to get the next //! state. Changes are transactional. -use base_db::{CrateGraph, CrateId, CrateWorkspaceData, FileChange, SourceRoot}; -use rustc_hash::FxHashMap; +use base_db::{CrateGraphBuilder, FileChange, SourceRoot}; use salsa::Durability; use span::FileId; use triomphe::Arc; -use crate::{db::ExpandDatabase, proc_macro::ProcMacros}; +use crate::{db::ExpandDatabase, proc_macro::ProcMacrosBuilder}; #[derive(Debug, Default)] pub struct ChangeWithProcMacros { pub source_change: FileChange, - pub proc_macros: Option, + pub proc_macros: Option, } impl ChangeWithProcMacros { @@ -20,8 +19,13 @@ impl ChangeWithProcMacros { } pub fn apply(self, db: &mut impl ExpandDatabase) { - self.source_change.apply(db); + let crates_id_map = self.source_change.apply(db); if let Some(proc_macros) = self.proc_macros { + let proc_macros = proc_macros.build( + crates_id_map + .as_ref() + .expect("cannot set proc macros without setting the crate graph too"), + ); db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH); } } @@ -30,16 +34,11 @@ impl ChangeWithProcMacros { self.source_change.change_file(file_id, new_text) } - pub fn set_crate_graph( - &mut self, - graph: CrateGraph, - ws_data: FxHashMap>, - ) { + pub fn set_crate_graph(&mut self, graph: CrateGraphBuilder) { self.source_change.set_crate_graph(graph); - self.source_change.set_ws_data(ws_data); } - pub fn set_proc_macros(&mut self, proc_macros: ProcMacros) { + pub fn set_proc_macros(&mut self, proc_macros: ProcMacrosBuilder) { self.proc_macros = Some(proc_macros); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 2f97cceab554a..112327f11e1a8 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -1,6 +1,6 @@ //! Defines database & queries for macro expansion. -use base_db::{CrateId, RootQueryDb}; +use base_db::{Crate, RootQueryDb}; use either::Either; use mbe::MatchedArmIndex; use rustc_hash::FxHashSet; @@ -23,7 +23,7 @@ use crate::{ span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt, SyntaxContextExt as _, }, - proc_macro::{CustomProcMacroExpander, ProcMacros}, + proc_macro::{CrateProcMacros, CustomProcMacroExpander, ProcMacros}, span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef}, tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, EagerExpander, ExpandError, ExpandResult, ExpandTo, MacroCallKind, MacroCallLoc, MacroDefId, @@ -57,10 +57,13 @@ pub enum TokenExpander { #[query_group::query_group] pub trait ExpandDatabase: RootQueryDb { - /// The proc macros. + /// The proc macros. Do not use this! Use `proc_macros_for_crate()` instead. #[salsa::input] fn proc_macros(&self) -> Arc; + #[salsa::invoke_actual(crate::proc_macro::proc_macros_for_crate)] + fn proc_macros_for_crate(&self, krate: Crate) -> Option>; + fn ast_id_map(&self, file_id: HirFileId) -> Arc; #[salsa::transparent] @@ -120,7 +123,7 @@ pub trait ExpandDatabase: RootQueryDb { #[salsa::invoke(DeclarativeMacroExpander::expander)] fn decl_macro_expander( &self, - def_crate: CrateId, + def_crate: Crate, id: AstId, ) -> Arc; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs index 91cbbc373649c..fbce320756645 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs @@ -1,6 +1,6 @@ //! Compiled declarative macro expanders (`macro_rules!` and `macro`) -use base_db::CrateId; +use base_db::Crate; use intern::sym; use span::{Edition, HirFileIdRepr, MacroCallId, Span, SyntaxContextId}; use stdx::TupleExt; @@ -70,7 +70,7 @@ impl DeclarativeMacroExpander { pub(crate) fn expander( db: &dyn ExpandDatabase, - def_crate: CrateId, + def_crate: Crate, id: AstId, ) -> Arc { let (root, map) = crate::db::parse_with_map(db, id.file_id); @@ -101,14 +101,12 @@ impl DeclarativeMacroExpander { } }; let ctx_edition = |ctx: SyntaxContextId| { - let crate_graph = db.crate_graph(); - if ctx.is_root() { - crate_graph[def_crate].edition + def_crate.data(db).edition } else { // UNWRAP-SAFETY: Only the root context has no outer expansion let krate = db.lookup_intern_macro_call(ctx.outer_expn(db).unwrap()).def.krate; - crate_graph[krate].edition + krate.data(db).edition } }; let (mac, transparency) = match id.to_ptr(db).to_node(&root) { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs index 4a98b455cab83..02dc75a4a6d87 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs @@ -18,7 +18,7 @@ //! //! //! See the full discussion : -use base_db::CrateId; +use base_db::Crate; use span::SyntaxContextId; use syntax::{ted, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent}; use syntax_bridge::DocCommentDesugarMode; @@ -34,7 +34,7 @@ use crate::{ pub fn expand_eager_macro_input( db: &dyn ExpandDatabase, - krate: CrateId, + krate: Crate, macro_call: &ast::MacroCall, ast_id: AstId, def: MacroDefId, @@ -115,7 +115,7 @@ fn lazy_expand( def: &MacroDefId, macro_call: &ast::MacroCall, ast_id: AstId, - krate: CrateId, + krate: Crate, call_site: SyntaxContextId, ) -> ExpandResult<(InFile>, Arc)> { let expand_to = ExpandTo::from_call_site(macro_call); @@ -137,7 +137,7 @@ fn eager_macro_recur( expanded_map: &mut ExpansionSpanMap, mut offset: TextSize, curr: InFile, - krate: CrateId, + krate: Crate, call_site: SyntaxContextId, macro_resolver: &dyn Fn(&ModPath) -> Option, ) -> ExpandResult> { @@ -176,7 +176,7 @@ fn eager_macro_recur( Some(path) => match macro_resolver(&path) { Some(def) => def, None => { - let edition = db.crate_graph()[krate].edition; + let edition = krate.data(db).edition; error = Some(ExpandError::other( span_map.span_at(call.syntax().text_range().start()), format!("unresolved macro {}", path.display(db, edition)), diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index f8c83dce55ac6..a1e484c08bcbf 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -33,7 +33,7 @@ use triomphe::Arc; use core::fmt; use std::hash::Hash; -use base_db::CrateId; +use base_db::Crate; use either::Either; use span::{ Edition, EditionedFileId, ErasedFileAstId, FileAstId, HirFileIdRepr, Span, SpanAnchor, @@ -157,7 +157,7 @@ impl ExpandError { pub enum ExpandErrorKind { /// Attribute macro expansion is disabled. ProcMacroAttrExpansionDisabled, - MissingProcMacroExpander(CrateId), + MissingProcMacroExpander(Crate), /// The macro for this call is disabled. MacroDisabled, /// The macro definition has errors. @@ -200,7 +200,7 @@ impl ExpandErrorKind { kind: RenderedExpandError::DISABLED, }, &ExpandErrorKind::MissingProcMacroExpander(def_crate) => { - match db.proc_macros().get_error_for_crate(def_crate) { + match db.proc_macros_for_crate(def_crate).as_ref().and_then(|it| it.get_error()) { Some((e, hard_err)) => RenderedExpandError { message: e.to_owned(), error: hard_err, @@ -250,14 +250,14 @@ impl From for ExpandError { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroCallLoc { pub def: MacroDefId, - pub krate: CrateId, + pub krate: Crate, pub kind: MacroCallKind, pub ctxt: SyntaxContextId, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroDefId { - pub krate: CrateId, + pub krate: Crate, pub edition: Edition, pub kind: MacroDefKind, pub local_inner: bool, @@ -525,7 +525,7 @@ impl MacroDefId { pub fn make_call( self, db: &dyn ExpandDatabase, - krate: CrateId, + krate: Crate, kind: MacroCallKind, ctxt: SyntaxContextId, ) -> MacroCallId { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs index 6f6f41f322abf..40b10cb4380af 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs @@ -11,7 +11,7 @@ use crate::{ name::{AsName, Name}, tt, }; -use base_db::CrateId; +use base_db::Crate; use intern::sym; use smallvec::SmallVec; use span::{Edition, SyntaxContextId}; @@ -33,7 +33,7 @@ pub enum PathKind { Abs, // FIXME: Can we remove this somehow? /// `$crate` from macro expansion - DollarCrate(CrateId), + DollarCrate(Crate), } impl PathKind { @@ -333,7 +333,7 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: tt::TokenTreesView<'_>) -> Optio Some(ModPath { kind, segments }) } -pub fn resolve_crate_root(db: &dyn ExpandDatabase, mut ctxt: SyntaxContextId) -> Option { +pub fn resolve_crate_root(db: &dyn ExpandDatabase, mut ctxt: SyntaxContextId) -> Option { // When resolving `$crate` from a `macro_rules!` invoked in a `macro`, // we don't want to pretend that the `macro_rules!` definition is in the `macro` // as described in `SyntaxContextId::apply_mark`, so we ignore prepended opaque marks. diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index 0758bd4515ef2..51721effa355d 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -260,7 +260,7 @@ impl AsName for ast::FieldKind { } } -impl AsName for base_db::Dependency { +impl AsName for base_db::BuiltDependency { fn as_name(&self) -> Name { Name::new_symbol_root((*self.name).clone()) } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs index 944341ec3f2cd..f398b070f791b 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs @@ -1,6 +1,6 @@ //! Pretty printing of macros output. -use base_db::CrateId; +use base_db::Crate; use rustc_hash::FxHashMap; use syntax::NodeOrToken; use syntax::{ast::make, SyntaxNode}; @@ -13,13 +13,12 @@ pub fn prettify_macro_expansion( db: &dyn ExpandDatabase, syn: SyntaxNode, span_map: &ExpansionSpanMap, - target_crate_id: CrateId, + target_crate_id: Crate, ) -> SyntaxNode { // Because `syntax_bridge::prettify_macro_expansion::prettify_macro_expansion()` clones subtree for `syn`, // that means it will be offsetted to the beginning. let span_offset = syn.text_range().start(); - let crate_graph = db.crate_graph(); - let target_crate = &crate_graph[target_crate_id]; + let target_crate = target_crate_id.data(db); let mut syntax_ctx_id_to_dollar_crate_replacement = FxHashMap::default(); syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(syn, &mut |dollar_crate| { let ctx = span_map.span_at(dollar_crate.text_range().start() + span_offset).ctx; @@ -41,7 +40,7 @@ pub fn prettify_macro_expansion( target_crate.dependencies.iter().find(|dep| dep.crate_id == macro_def_crate) { make::tokens::ident(dep.name.as_str()) - } else if let Some(crate_name) = &crate_graph[macro_def_crate].display_name { + } else if let Some(crate_name) = ¯o_def_crate.extra_data(db).display_name { make::tokens::ident(crate_name.crate_name().as_str()) } else { return dollar_crate.clone(); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs index 3dc3dcd760cd3..cdf63e92a89b5 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs @@ -1,24 +1,36 @@ //! Proc Macro Expander stuff use core::fmt; +use std::any::Any; use std::{panic::RefUnwindSafe, sync}; -use base_db::{CrateId, Env}; +use base_db::{Crate, CrateBuilderId, CratesIdMap, Env}; use intern::Symbol; use rustc_hash::FxHashMap; use span::Span; +use triomphe::Arc; use crate::{db::ExpandDatabase, tt, ExpandError, ExpandErrorKind, ExpandResult}; -#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug, Hash)] pub enum ProcMacroKind { CustomDerive, Bang, Attr, } +pub trait AsAny: Any { + fn as_any(&self) -> &dyn Any; +} + +impl AsAny for T { + fn as_any(&self) -> &dyn Any { + self + } +} + /// A proc-macro expander implementation. -pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe { +pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe + AsAny { /// Run the expander with the given input subtree, optional attribute input subtree (for /// [`ProcMacroKind::Attr`]), environment variables, and span information. fn expand( @@ -31,8 +43,18 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe { mixed_site: Span, current_dir: Option, ) -> Result; + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool; } +impl PartialEq for dyn ProcMacroExpander { + fn eq(&self, other: &Self) -> bool { + self.eq_dyn(other) + } +} + +impl Eq for dyn ProcMacroExpander {} + #[derive(Debug)] pub enum ProcMacroExpansionError { /// The proc-macro panicked. @@ -45,41 +67,68 @@ pub type ProcMacroLoadResult = Result, (String, bool)>; type StoredProcMacroLoadResult = Result, (Box, bool)>; #[derive(Default, Debug)] -pub struct ProcMacrosBuilder(FxHashMap); +pub struct ProcMacrosBuilder(FxHashMap>); + impl ProcMacrosBuilder { - pub fn insert(&mut self, proc_macros_crate: CrateId, proc_macro: ProcMacroLoadResult) { + pub fn insert( + &mut self, + proc_macros_crate: CrateBuilderId, + mut proc_macro: ProcMacroLoadResult, + ) { + if let Ok(proc_macros) = &mut proc_macro { + // Sort proc macros to improve incrementality when only their order has changed (ideally the build system + // will not change their order, but just to be sure). + proc_macros + .sort_unstable_by_key(|proc_macro| (proc_macro.name.clone(), proc_macro.kind)); + } self.0.insert( proc_macros_crate, match proc_macro { - Ok(it) => Ok(it.into_boxed_slice()), - Err((e, hard_err)) => Err((e.into_boxed_str(), hard_err)), + Ok(it) => Arc::new(CrateProcMacros(Ok(it.into_boxed_slice()))), + Err((e, hard_err)) => { + Arc::new(CrateProcMacros(Err((e.into_boxed_str(), hard_err)))) + } }, ); } - pub fn build(mut self) -> ProcMacros { - self.0.shrink_to_fit(); - ProcMacros(self.0) + + pub(crate) fn build(self, crates_id_map: &CratesIdMap) -> ProcMacros { + let mut map = self + .0 + .into_iter() + .map(|(krate, proc_macro)| (crates_id_map[&krate], proc_macro)) + .collect::>(); + map.shrink_to_fit(); + ProcMacros(map) } } -#[derive(Default, Debug)] -pub struct ProcMacros(FxHashMap); - -impl FromIterator<(CrateId, ProcMacroLoadResult)> for ProcMacros { - fn from_iter>(iter: T) -> Self { +impl FromIterator<(CrateBuilderId, ProcMacroLoadResult)> for ProcMacrosBuilder { + fn from_iter>(iter: T) -> Self { let mut builder = ProcMacrosBuilder::default(); for (k, v) in iter { builder.insert(k, v); } - builder.build() + builder } } +#[derive(Debug, PartialEq, Eq)] +pub struct CrateProcMacros(StoredProcMacroLoadResult); + +#[derive(Default, Debug)] +pub struct ProcMacros(FxHashMap>); impl ProcMacros { - fn get(&self, krate: CrateId, idx: u32, err_span: Span) -> Result<&ProcMacro, ExpandError> { - let proc_macros = match self.0.get(&krate) { - Some(Ok(proc_macros)) => proc_macros, - Some(Err(_)) | None => { + fn get(&self, krate: Crate) -> Option> { + self.0.get(&krate).cloned() + } +} + +impl CrateProcMacros { + fn get(&self, idx: u32, err_span: Span) -> Result<&ProcMacro, ExpandError> { + let proc_macros = match &self.0 { + Ok(proc_macros) => proc_macros, + Err(_) => { return Err(ExpandError::other( err_span, "internal error: no proc macros for crate", @@ -98,18 +147,17 @@ impl ProcMacros { ) } - pub fn get_error_for_crate(&self, krate: CrateId) -> Option<(&str, bool)> { - self.0.get(&krate).and_then(|it| it.as_ref().err()).map(|(e, hard_err)| (&**e, *hard_err)) + pub fn get_error(&self) -> Option<(&str, bool)> { + self.0.as_ref().err().map(|(e, hard_err)| (&**e, *hard_err)) } /// Fetch the [`CustomProcMacroExpander`]s and their corresponding names for the given crate. - pub fn for_crate( + pub fn list( &self, - krate: CrateId, def_site_ctx: span::SyntaxContextId, ) -> Option> { - match self.0.get(&krate) { - Some(Ok(proc_macros)) => Some({ + match &self.0 { + Ok(proc_macros) => Some( proc_macros .iter() .enumerate() @@ -117,15 +165,15 @@ impl ProcMacros { let name = crate::name::Name::new_symbol(it.name.clone(), def_site_ctx); (name, CustomProcMacroExpander::new(idx as u32), it.disabled) }) - .collect() - }), + .collect(), + ), _ => None, } } } /// A loaded proc-macro. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq)] pub struct ProcMacro { /// The name of the proc macro. pub name: Symbol, @@ -137,6 +185,23 @@ pub struct ProcMacro { pub disabled: bool, } +// `#[derive(PartialEq)]` generates a strange "cannot move" error. +impl PartialEq for ProcMacro { + fn eq(&self, other: &Self) -> bool { + let Self { name, kind, expander, disabled } = self; + let Self { + name: other_name, + kind: other_kind, + expander: other_expander, + disabled: other_disabled, + } = other; + name == other_name + && kind == other_kind + && expander == other_expander + && disabled == other_disabled + } +} + /// A custom proc-macro expander handle. This handle together with its crate resolves to a [`ProcMacro`] #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub struct CustomProcMacroExpander { @@ -187,7 +252,7 @@ impl CustomProcMacroExpander { } /// The macro is explicitly disabled due to proc-macro attribute expansion being disabled. - pub fn as_expand_error(&self, def_crate: CrateId) -> Option { + pub fn as_expand_error(&self, def_crate: Crate) -> Option { match self.proc_macro_id { Self::PROC_MACRO_ATTR_DISABLED => Some(ExpandErrorKind::ProcMacroAttrExpansionDisabled), Self::DISABLED_ID => Some(ExpandErrorKind::MacroDisabled), @@ -199,8 +264,8 @@ impl CustomProcMacroExpander { pub fn expand( self, db: &dyn ExpandDatabase, - def_crate: CrateId, - calling_crate: CrateId, + def_crate: Crate, + calling_crate: Crate, tt: &tt::TopSubtree, attr_arg: Option<&tt::TopSubtree>, def_site: Span, @@ -221,8 +286,22 @@ impl CustomProcMacroExpander { ExpandError::new(call_site, ExpandErrorKind::MacroDisabled), ), id => { - let proc_macros = db.proc_macros(); - let proc_macro = match proc_macros.get(def_crate, id, call_site) { + let proc_macros = match db.proc_macros_for_crate(def_crate) { + Some(it) => it, + None => { + return ExpandResult::new( + tt::TopSubtree::empty(tt::DelimSpan { + open: call_site, + close: call_site, + }), + ExpandError::other( + call_site, + "internal error: no proc macros for crate", + ), + ) + } + }; + let proc_macro = match proc_macros.get(id, call_site) { Ok(proc_macro) => proc_macro, Err(e) => { return ExpandResult::new( @@ -235,11 +314,10 @@ impl CustomProcMacroExpander { } }; - let krate_graph = db.crate_graph(); // Proc macros have access to the environment variables of the invoking crate. - let env = &krate_graph[calling_crate].env; + let env = calling_crate.env(db); let current_dir = - krate_graph[calling_crate].proc_macro_cwd.as_deref().map(ToString::to_string); + calling_crate.data(db).proc_macro_cwd.as_deref().map(ToString::to_string); match proc_macro.expander.expand( tt, @@ -278,3 +356,10 @@ impl CustomProcMacroExpander { } } } + +pub(crate) fn proc_macros_for_crate( + db: &dyn ExpandDatabase, + krate: Crate, +) -> Option> { + db.proc_macros().get(krate) +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 2be321733075b..84eb964d564bd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -11,7 +11,7 @@ use tracing::debug; use chalk_ir::{cast::Caster, fold::shift::Shift, CanonicalVarKinds}; use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; -use base_db::CrateId; +use base_db::Crate; use hir_def::{ data::{adt::StructFlags, TraitFlags}, hir::Movability, @@ -523,7 +523,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { impl ChalkContext<'_> { fn edition(&self) -> Edition { - self.db.crate_graph()[self.krate].edition + self.krate.data(self.db).edition } fn for_trait_impls( @@ -593,7 +593,7 @@ impl chalk_ir::UnificationDatabase for &dyn HirDatabase { pub(crate) fn program_clauses_for_chalk_env_query( db: &dyn HirDatabase, - krate: CrateId, + krate: Crate, block: Option, environment: chalk_ir::Environment, ) -> chalk_ir::ProgramClauses { @@ -665,7 +665,7 @@ pub(crate) fn associated_ty_data_query( pub(crate) fn trait_datum_query( db: &dyn HirDatabase, - krate: CrateId, + krate: Crate, trait_id: TraitId, ) -> Arc { debug!("trait_datum {:?}", trait_id); @@ -750,7 +750,7 @@ fn lang_item_from_well_known_trait(trait_: WellKnownTrait) -> LangItem { pub(crate) fn adt_datum_query( db: &dyn HirDatabase, - krate: CrateId, + krate: Crate, chalk_ir::AdtId(adt_id): AdtId, ) -> Arc { debug!("adt_datum {:?}", adt_id); @@ -824,7 +824,7 @@ pub(crate) fn adt_datum_query( pub(crate) fn impl_datum_query( db: &dyn HirDatabase, - krate: CrateId, + krate: Crate, impl_id: ImplId, ) -> Arc { let _p = tracing::info_span!("impl_datum_query").entered(); @@ -833,11 +833,7 @@ pub(crate) fn impl_datum_query( impl_def_datum(db, krate, impl_) } -fn impl_def_datum( - db: &dyn HirDatabase, - krate: CrateId, - impl_id: hir_def::ImplId, -) -> Arc { +fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId) -> Arc { let trait_ref = db .impl_trait(impl_id) // ImplIds for impls where the trait ref can't be resolved should never reach Chalk @@ -887,7 +883,7 @@ fn impl_def_datum( pub(crate) fn associated_ty_value_query( db: &dyn HirDatabase, - krate: CrateId, + krate: Crate, id: AssociatedTyValueId, ) -> Arc { let type_alias: TypeAliasAsValue = from_chalk(db, id); @@ -896,7 +892,7 @@ pub(crate) fn associated_ty_value_query( fn type_alias_associated_ty_value( db: &dyn HirDatabase, - _krate: CrateId, + _krate: Crate, type_alias: TypeAliasId, ) -> Arc { let type_alias_data = db.type_alias_data(type_alias); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index b3c604015a0c1..525672bc39951 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -1,6 +1,6 @@ //! Constant evaluation details -use base_db::CrateId; +use base_db::Crate; use chalk_ir::{cast::Cast, BoundVar, DebruijnIndex}; use hir_def::{ expr_store::{Body, HygieneId}, @@ -162,7 +162,7 @@ pub fn intern_const_ref( db: &dyn HirDatabase, value: &LiteralConstRef, ty: Ty, - krate: CrateId, + krate: Crate, ) -> Const { let layout = db.layout_of_ty(ty.clone(), TraitEnvironment::empty(krate)); let bytes = match value { @@ -185,7 +185,7 @@ pub fn intern_const_ref( } /// Interns a possibly-unknown target usize -pub fn usize_const(db: &dyn HirDatabase, value: Option, krate: CrateId) -> Const { +pub fn usize_const(db: &dyn HirDatabase, value: Option, krate: Crate) -> Const { intern_const_ref( db, &value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index f2673dc58fa41..37e7df6f4b46e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -101,10 +101,7 @@ fn check_answer( fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String { let mut err = String::new(); let span_formatter = |file, range| format!("{file:?} {range:?}"); - let display_target = DisplayTarget::from_crate( - &db, - *db.crate_graph().crates_in_topological_order().last().unwrap(), - ); + let display_target = DisplayTarget::from_crate(&db, *db.all_crates().last().unwrap()); match e { ConstEvalError::MirLowerError(e) => { e.pretty_print(&mut err, &db, span_formatter, display_target) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index 5817ed2ef20cd..8f48cfc4327ff 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -3,7 +3,7 @@ use std::sync; -use base_db::{impl_intern_key, CrateId, Upcast}; +use base_db::{impl_intern_key, Crate, Upcast}; use hir_def::{ db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId, @@ -103,8 +103,8 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { #[salsa::cycle(crate::layout::layout_of_ty_recover)] fn layout_of_ty(&self, ty: Ty, env: Arc) -> Result, LayoutError>; - #[salsa::invoke(crate::layout::target_data_layout_query)] - fn target_data_layout(&self, krate: CrateId) -> Result, Arc>; + #[salsa::invoke_actual(crate::layout::target_data_layout_query)] + fn target_data_layout(&self, krate: Crate) -> Result, Arc>; #[salsa::invoke_actual(crate::dyn_compatibility::dyn_compatibility_of_trait_query)] fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option; @@ -196,8 +196,8 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { #[salsa::invoke_actual(crate::lower::generic_defaults_query)] fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults; - #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)] - fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc; + #[salsa::invoke_actual(InherentImpls::inherent_impls_in_crate_query)] + fn inherent_impls_in_crate(&self, krate: Crate) -> Arc; #[salsa::invoke_actual(InherentImpls::inherent_impls_in_block_query)] fn inherent_impls_in_block(&self, block: BlockId) -> Option>; @@ -209,18 +209,18 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { #[salsa::invoke(crate::method_resolution::incoherent_inherent_impl_crates)] fn incoherent_inherent_impl_crates( &self, - krate: CrateId, + krate: Crate, fp: TyFingerprint, - ) -> SmallVec<[CrateId; 2]>; + ) -> SmallVec<[Crate; 2]>; - #[salsa::invoke(TraitImpls::trait_impls_in_crate_query)] - fn trait_impls_in_crate(&self, krate: CrateId) -> Arc; + #[salsa::invoke_actual(TraitImpls::trait_impls_in_crate_query)] + fn trait_impls_in_crate(&self, krate: Crate) -> Arc; #[salsa::invoke_actual(TraitImpls::trait_impls_in_block_query)] fn trait_impls_in_block(&self, block: BlockId) -> Option>; - #[salsa::invoke(TraitImpls::trait_impls_in_deps_query)] - fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<[Arc]>; + #[salsa::invoke_actual(TraitImpls::trait_impls_in_deps_query)] + fn trait_impls_in_deps(&self, krate: Crate) -> Arc<[Arc]>; // Interned IDs for Chalk integration #[salsa::interned] @@ -253,23 +253,16 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { #[salsa::invoke(chalk_db::trait_datum_query)] fn trait_datum( &self, - krate: CrateId, + krate: Crate, trait_id: chalk_db::TraitId, ) -> sync::Arc; #[salsa::invoke(chalk_db::adt_datum_query)] - fn adt_datum( - &self, - krate: CrateId, - struct_id: chalk_db::AdtId, - ) -> sync::Arc; + fn adt_datum(&self, krate: Crate, struct_id: chalk_db::AdtId) -> sync::Arc; #[salsa::invoke(chalk_db::impl_datum_query)] - fn impl_datum( - &self, - krate: CrateId, - impl_id: chalk_db::ImplId, - ) -> sync::Arc; + fn impl_datum(&self, krate: Crate, impl_id: chalk_db::ImplId) + -> sync::Arc; #[salsa::invoke(chalk_db::fn_def_datum_query)] fn fn_def_datum(&self, fn_def_id: FnDefId) -> sync::Arc; @@ -287,7 +280,7 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { #[salsa::invoke(chalk_db::associated_ty_value_query)] fn associated_ty_value( &self, - krate: CrateId, + krate: Crate, id: chalk_db::AssociatedTyValueId, ) -> sync::Arc; @@ -302,7 +295,7 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { #[salsa::invoke(crate::traits::trait_solve_query)] fn trait_solve( &self, - krate: CrateId, + krate: Crate, block: Option, goal: crate::Canonical>, ) -> Option; @@ -310,7 +303,7 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)] fn program_clauses_for_chalk_env( &self, - krate: CrateId, + krate: Crate, block: Option, env: chalk_ir::Environment, ) -> chalk_ir::ProgramClauses; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index eed74e1eee358..a0b1fe32ce52d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -288,7 +288,7 @@ impl<'a> DeclValidator<'a> { fn edition(&self, id: impl HasModule) -> span::Edition { let krate = id.krate(self.db.upcast()); - self.db.crate_graph()[krate].edition + krate.data(self.db).edition } fn validate_struct(&mut self, struct_id: StructId) { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 975143b29f2f9..053d1cd41e9f1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -4,7 +4,7 @@ use std::fmt; -use base_db::CrateId; +use base_db::Crate; use chalk_solve::rust_ir::AdtKind; use either::Either; use hir_def::{ @@ -630,7 +630,7 @@ fn missing_match_arms<'p>( scrut_ty: &Ty, witnesses: Vec>, arms_is_empty: bool, - krate: CrateId, + krate: Crate, ) -> String { struct DisplayWitness<'a, 'p>(&'a WitnessPat<'p>, &'a MatchCheckCtx<'p>, DisplayTarget); impl fmt::Display for DisplayWitness<'_, '_> { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs index d2b908839c42e..84dd4be67fe8d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -160,7 +160,7 @@ impl<'a> UnsafeVisitor<'a> { DefWithBodyId::FunctionId(func) => TargetFeatures::from_attrs(&db.attrs(func.into())), _ => TargetFeatures::default(), }; - let edition = db.crate_graph()[resolver.module().krate()].edition; + let edition = resolver.module().krate().data(db).edition; Self { db, infer, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 95ce36390d33d..2ae7e746ba203 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -7,7 +7,7 @@ use std::{ mem, }; -use base_db::CrateId; +use base_db::Crate; use chalk_ir::{BoundVar, Safety, TyKind}; use either::Either; use hir_def::{ @@ -339,7 +339,7 @@ pub trait HirDisplay { } impl HirFormatter<'_> { - pub fn krate(&self) -> CrateId { + pub fn krate(&self) -> Crate { self.display_target.krate } @@ -408,13 +408,13 @@ impl HirFormatter<'_> { #[derive(Debug, Clone, Copy)] pub struct DisplayTarget { - krate: CrateId, + krate: Crate, pub edition: Edition, } impl DisplayTarget { - pub fn from_crate(db: &dyn HirDatabase, krate: CrateId) -> Self { - let edition = db.crate_graph()[krate].edition; + pub fn from_crate(db: &dyn HirDatabase, krate: Crate) -> Self { + let edition = krate.data(db).edition; Self { krate, edition } } } @@ -1711,7 +1711,7 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator String { let body = db.body(owner); let krate = owner.krate(db.upcast()); - let edition = db.crate_graph()[krate].edition; + let edition = krate.data(db).edition; let mut result = body[self.place.local].name.display(db.upcast(), edition).to_string(); for proj in &self.place.projections { match proj { @@ -368,7 +368,7 @@ impl CapturedItem { pub fn display_place(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String { let body = db.body(owner); let krate = owner.krate(db.upcast()); - let edition = db.crate_graph()[krate].edition; + let edition = krate.data(db).edition; let mut result = body[self.place.local].name.display(db.upcast(), edition).to_string(); let mut field_need_paren = false; for proj in &self.place.projections { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs index 7d77f6d0731a3..e1e1c44996cde 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs @@ -1,6 +1,6 @@ //! Target dependent parameters needed for layouts -use base_db::CrateId; +use base_db::Crate; use hir_def::layout::TargetDataLayout; use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors}; use triomphe::Arc; @@ -9,9 +9,9 @@ use crate::db::HirDatabase; pub fn target_data_layout_query( db: &dyn HirDatabase, - krate: CrateId, + krate: Crate, ) -> Result, Arc> { - match &db.crate_workspace_data()[&krate].data_layout { + match &krate.workspace_data(db).data_layout { Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it) { Ok(it) => Ok(Arc::new(it)), Err(e) => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index ff7f0349638cd..29ab0251f8360 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -14,7 +14,7 @@ use std::{ ops::{self, Not as _}, }; -use base_db::CrateId; +use base_db::Crate; use chalk_ir::{ cast::Cast, fold::{Shift, TypeFoldable}, @@ -801,7 +801,7 @@ impl<'a> TyLoweringContext<'a> { } } - fn lower_impl_trait(&mut self, bounds: &[TypeBound], krate: CrateId) -> ImplTrait { + fn lower_impl_trait(&mut self, bounds: &[TypeBound], krate: Crate) -> ImplTrait { cov_mark::hit!(lower_rpit); let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner); let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { @@ -1863,8 +1863,11 @@ pub(crate) fn const_or_path_to_chalk<'g>( .unwrap_or_else(|| unknown_const(expected_ty)) } &ConstRef::Complex(it) => { - let crate_data = &db.crate_graph()[resolver.krate()]; - if crate_data.env.get("__ra_is_test_fixture").is_none() && crate_data.origin.is_local() + let krate = resolver.krate(); + // Keep the `&&` this way, because it's better to access the crate data, as we access it for + // a bunch of other things nevertheless. + if krate.data(db).origin.is_local() + && krate.env(db).get("__ra_is_test_fixture").is_none() { // FIXME: current `InTypeConstId` is very unstable, so we only use it in non local crate // that are unlikely to be edited. diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index c5ad808accdf4..50b0fce62f76e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -5,7 +5,7 @@ use std::ops::ControlFlow; use arrayvec::ArrayVec; -use base_db::CrateId; +use base_db::Crate; use chalk_ir::{cast::Cast, UniverseIndex, WithKind}; use hir_def::{ data::{adt::StructFlags, ImplData, TraitFlags}, @@ -148,7 +148,7 @@ pub struct TraitImpls { } impl TraitImpls { - pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc { + pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: Crate) -> Arc { let _p = tracing::info_span!("trait_impls_in_crate_query", ?krate).entered(); let mut impls = FxHashMap::default(); @@ -175,13 +175,11 @@ impl TraitImpls { pub(crate) fn trait_impls_in_deps_query( db: &dyn HirDatabase, - krate: CrateId, + krate: Crate, ) -> Arc<[Arc]> { let _p = tracing::info_span!("trait_impls_in_deps_query", ?krate).entered(); - let crate_graph = db.crate_graph(); - Arc::from_iter( - crate_graph.transitive_deps(krate).map(|krate| db.trait_impls_in_crate(krate)), + db.transitive_deps(krate).into_iter().map(|krate| db.trait_impls_in_crate(krate)), ) } @@ -282,7 +280,7 @@ pub struct InherentImpls { } impl InherentImpls { - pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc { + pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: Crate) -> Arc { let _p = tracing::info_span!("inherent_impls_in_crate_query", ?krate).entered(); let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() }; @@ -367,16 +365,15 @@ impl InherentImpls { pub(crate) fn incoherent_inherent_impl_crates( db: &dyn HirDatabase, - krate: CrateId, + krate: Crate, fp: TyFingerprint, -) -> SmallVec<[CrateId; 2]> { +) -> SmallVec<[Crate; 2]> { let _p = tracing::info_span!("incoherent_inherent_impl_crates").entered(); let mut res = SmallVec::new(); - let crate_graph = db.crate_graph(); // should pass crate for finger print and do reverse deps - for krate in crate_graph.transitive_deps(krate) { + for krate in db.transitive_deps(krate) { let impls = db.inherent_impls_in_crate(krate); if impls.map.get(&fp).is_some_and(|v| !v.is_empty()) { res.push(krate); @@ -386,11 +383,7 @@ pub(crate) fn incoherent_inherent_impl_crates( res } -pub fn def_crates( - db: &dyn HirDatabase, - ty: &Ty, - cur_crate: CrateId, -) -> Option> { +pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option> { match ty.kind(Interner) { &TyKind::Adt(AdtId(def_id), _) => { let rustc_has_incoherent_inherent_impls = match def_id { @@ -1226,7 +1219,7 @@ fn iterate_trait_method_candidates( { // FIXME: this should really be using the edition of the method name's span, in case it // comes from a macro - if !db.crate_graph()[krate].edition.at_least_2021() { + if !krate.data(db).edition.at_least_2021() { continue; } } @@ -1239,7 +1232,7 @@ fn iterate_trait_method_candidates( { // FIXME: this should really be using the edition of the method name's span, in case it // comes from a macro - if !db.crate_graph()[krate].edition.at_least_2024() { + if !krate.data(db).edition.at_least_2024() { continue; } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index ae454fbe528a5..7faa23f818b8f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -12,7 +12,7 @@ use crate::{ CallableDefId, ClosureId, Const, ConstScalar, InferenceResult, Interner, MemoryMap, Substitution, TraitEnvironment, Ty, TyExt, TyKind, }; -use base_db::CrateId; +use base_db::Crate; use chalk_ir::Mutability; use either::Either; use hir_def::{ @@ -143,7 +143,7 @@ impl ProjectionElem { mut base: Ty, db: &dyn HirDatabase, closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty, - krate: CrateId, + krate: Crate, ) -> Ty { // we only bail on mir building when there are type mismatches // but error types may pop up resulting in us still attempting to build the mir diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index c9d62f566c1a6..597e6a3ef0bf1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range}; -use base_db::CrateId; +use base_db::Crate; use chalk_ir::{cast::Cast, Mutability}; use either::Either; use hir_def::{ @@ -186,7 +186,7 @@ pub struct Evaluator<'a> { cached_fn_trait_func: Option, cached_fn_mut_trait_func: Option, cached_fn_once_trait_func: Option, - crate_id: CrateId, + crate_id: Crate, // FIXME: This is a workaround, see the comment on `interpret_mir` assert_placeholder_ty_is_unused: bool, /// A general limit on execution, to prevent non terminating programs from breaking r-a main process @@ -2785,7 +2785,7 @@ impl Evaluator<'_> { let db = self.db.upcast(); let loc = variant.lookup(db); let enum_loc = loc.parent.lookup(db); - let edition = self.db.crate_graph()[self.crate_id].edition; + let edition = self.crate_id.data(self.db).edition; let name = format!( "{}::{}", enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast(), edition), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index f61ecabb7e41d..346dea82526fb 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -569,7 +569,7 @@ impl Evaluator<'_> { } String::from_utf8_lossy(&name_buf) }; - let value = self.db.crate_graph()[self.crate_id].env.get(&name); + let value = self.crate_id.env(self.db).get(&name); match value { None => { // Write null as fail diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 17f1da0c9f378..57d4baa137cee 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -2,7 +2,7 @@ use std::{fmt::Write, iter, mem}; -use base_db::{salsa::Cycle, CrateId}; +use base_db::{salsa::Cycle, Crate}; use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind}; use hir_def::{ data::adt::{StructKind, VariantData}, @@ -1920,10 +1920,10 @@ impl<'ctx> MirLowerCtx<'ctx> { } fn edition(&self) -> Edition { - self.db.crate_graph()[self.krate()].edition + self.krate().data(self.db).edition } - fn krate(&self) -> CrateId { + fn krate(&self) -> Crate { self.owner.krate(self.db.upcast()) } @@ -2121,7 +2121,7 @@ pub fn mir_body_for_closure_query( pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result> { let krate = def.krate(db.upcast()); - let edition = db.crate_graph()[krate].edition; + let edition = krate.data(db).edition; let detail = match def { DefWithBodyId::FunctionId(it) => { db.function_data(it).name.display(db.upcast(), edition).to_string() diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs index b18a057ba0b9d..68d0c8cd5a312 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs @@ -3,8 +3,8 @@ use std::{fmt, panic, sync::Mutex}; use base_db::{ - FileSourceRootInput, FileText, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId, - SourceRootInput, Upcast, + CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, RootQueryDb, SourceDatabase, + SourceRoot, SourceRootId, SourceRootInput, Upcast, }; use hir_def::{db::DefDatabase, ModuleId}; @@ -21,6 +21,7 @@ use triomphe::Arc; pub(crate) struct TestDB { storage: salsa::Storage, files: Arc, + crates_map: Arc, events: Arc>>>, } @@ -30,8 +31,12 @@ impl Default for TestDB { storage: Default::default(), events: Default::default(), files: Default::default(), + crates_map: Default::default(), }; this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); + // This needs to be here otherwise `CrateGraphBuilder` panics. + this.set_all_crates(Arc::new(Box::new([]))); + CrateGraphBuilder::default().set_in_db(&mut this); this } } @@ -115,6 +120,10 @@ impl SourceDatabase for TestDB { let files = Arc::clone(&self.files); files.set_file_source_root_with_durability(self, id, source_root_id, durability); } + + fn crates_map(&self) -> Arc { + self.crates_map.clone() + } } #[salsa::db] @@ -151,8 +160,7 @@ impl TestDB { &self, ) -> FxHashMap> { let mut files = Vec::new(); - let crate_graph = self.crate_graph(); - for krate in crate_graph.iter() { + for &krate in self.all_crates().iter() { let crate_def_map = self.crate_def_map(krate); for (module_id, _) in crate_def_map.modules() { let file_id = crate_def_map[module_id].origin.file_id(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index 26229040582b8..cdb9e9edf8831 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -15,7 +15,7 @@ mod type_alias_impl_traits; use std::env; use std::sync::LazyLock; -use base_db::{CrateId, SourceDatabase}; +use base_db::{Crate, SourceDatabase}; use expect_test::Expect; use hir_def::{ db::DefDatabase, @@ -124,7 +124,7 @@ fn check_impl( } assert!(had_annotations || allow_none, "no `//^` annotations found"); - let mut defs: Vec<(DefWithBodyId, CrateId)> = Vec::new(); + let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new(); for file_id in files { let module = db.module_for_file_opt(file_id); let module = match module { @@ -302,7 +302,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { let mut infer_def = |inference_result: Arc, body: Arc, body_source_map: Arc, - krate: CrateId| { + krate: Crate| { let display_target = DisplayTarget::from_crate(&db, krate); let mut types: Vec<(InFile, &Ty)> = Vec::new(); let mut mismatches: Vec<(InFile, &TypeMismatch)> = Vec::new(); @@ -391,7 +391,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { let module = db.module_for_file(file_id); let def_map = module.def_map(&db); - let mut defs: Vec<(DefWithBodyId, CrateId)> = Vec::new(); + let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new(); visit_module(&db, &def_map, module.local_id, &mut |it| { let def = match it { ModuleDefId::FunctionId(it) => it.into(), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index 0135e0a409bbe..f8db6a8298f6b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -7,7 +7,7 @@ use chalk_ir::{fold::TypeFoldable, DebruijnIndex, GoalData}; use chalk_recursive::Cache; use chalk_solve::{logging_db::LoggingRustIrDatabase, rust_ir, Solver}; -use base_db::CrateId; +use base_db::Crate; use hir_def::{ lang_item::{LangItem, LangItemTarget}, BlockId, TraitId, @@ -30,7 +30,7 @@ const CHALK_SOLVER_FUEL: i32 = 1000; #[derive(Debug, Copy, Clone)] pub(crate) struct ChalkContext<'a> { pub(crate) db: &'a dyn HirDatabase, - pub(crate) krate: CrateId, + pub(crate) krate: Crate, pub(crate) block: Option, } @@ -48,7 +48,7 @@ fn create_chalk_solver() -> chalk_recursive::RecursiveSolver { /// we assume that `T: Default`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TraitEnvironment { - pub krate: CrateId, + pub krate: Crate, pub block: Option, // FIXME make this a BTreeMap traits_from_clauses: Box<[(Ty, TraitId)]>, @@ -56,7 +56,7 @@ pub struct TraitEnvironment { } impl TraitEnvironment { - pub fn empty(krate: CrateId) -> Arc { + pub fn empty(krate: Crate) -> Arc { Arc::new(TraitEnvironment { krate, block: None, @@ -66,7 +66,7 @@ impl TraitEnvironment { } pub fn new( - krate: CrateId, + krate: Crate, block: Option, traits_from_clauses: Box<[(Ty, TraitId)]>, env: chalk_ir::Environment, @@ -109,7 +109,7 @@ pub(crate) fn normalize_projection_query( /// Solve a trait goal using Chalk. pub(crate) fn trait_solve_query( db: &dyn HirDatabase, - krate: CrateId, + krate: Crate, block: Option, goal: Canonical>, ) -> Option { @@ -148,7 +148,7 @@ pub(crate) fn trait_solve_query( fn solve( db: &dyn HirDatabase, - krate: CrateId, + krate: Crate, block: Option, goal: &chalk_ir::UCanonical>>, ) -> Option> { @@ -294,7 +294,7 @@ impl FnTrait { } } - pub fn get_id(self, db: &dyn HirDatabase, krate: CrateId) -> Option { + pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option { let target = db.lang_item(krate, self.lang_item())?; match target { LangItemTarget::Trait(t) => Some(t), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 89d89fe2230af..b90f4e4d7faaa 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -3,7 +3,7 @@ use std::{hash::Hash, iter}; -use base_db::CrateId; +use base_db::Crate; use chalk_ir::{ fold::{FallibleTypeFolder, Shift}, DebruijnIndex, @@ -34,10 +34,7 @@ use crate::{ TraitRefExt, Ty, WhereClause, }; -pub(crate) fn fn_traits( - db: &dyn DefDatabase, - krate: CrateId, -) -> impl Iterator + '_ { +pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator + '_ { [LangItem::Fn, LangItem::FnMut, LangItem::FnOnce] .into_iter() .filter_map(move |lang| db.lang_item(krate, lang)) diff --git a/src/tools/rust-analyzer/crates/hir/src/from_id.rs b/src/tools/rust-analyzer/crates/hir/src/from_id.rs index 72df07ef8c0cc..891d2fd2ba5dc 100644 --- a/src/tools/rust-analyzer/crates/hir/src/from_id.rs +++ b/src/tools/rust-analyzer/crates/hir/src/from_id.rs @@ -30,7 +30,7 @@ macro_rules! from_id { } from_id![ - (base_db::CrateId, crate::Crate), + (base_db::Crate, crate::Crate), (hir_def::ModuleId, crate::Module), (hir_def::StructId, crate::Struct), (hir_def::UnionId, crate::Union), diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index dbe743e7e2f85..5da2b5ed09361 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -39,7 +39,7 @@ use std::{ }; use arrayvec::ArrayVec; -use base_db::{CrateDisplayName, CrateId, CrateOrigin, LangCrateOrigin}; +use base_db::{CrateDisplayName, CrateOrigin, LangCrateOrigin}; use either::Either; use hir_def::{ data::{adt::VariantData, TraitFlags}, @@ -176,7 +176,7 @@ use { /// root module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Crate { - pub(crate) id: CrateId, + pub(crate) id: base_db::Crate, } #[derive(Debug)] @@ -187,7 +187,7 @@ pub struct CrateDependency { impl Crate { pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin { - db.crate_graph()[self.id].origin.clone() + self.id.data(db).origin.clone() } pub fn is_builtin(self, db: &dyn HirDatabase) -> bool { @@ -195,7 +195,8 @@ impl Crate { } pub fn dependencies(self, db: &dyn HirDatabase) -> Vec { - db.crate_graph()[self.id] + self.id + .data(db) .dependencies .iter() .map(|dep| { @@ -207,12 +208,11 @@ impl Crate { } pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec { - let crate_graph = db.crate_graph(); - crate_graph + let all_crates = db.all_crates(); + all_crates .iter() - .filter(|&krate| { - crate_graph[krate].dependencies.iter().any(|it| it.crate_id == self.id) - }) + .copied() + .filter(|&krate| krate.data(db).dependencies.iter().any(|it| it.crate_id == self.id)) .map(|id| Crate { id }) .collect() } @@ -221,7 +221,7 @@ impl Crate { self, db: &dyn HirDatabase, ) -> impl Iterator { - db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id }) + db.transitive_rev_deps(self.id).into_iter().map(|id| Crate { id }) } pub fn root_module(self) -> Module { @@ -234,19 +234,19 @@ impl Crate { } pub fn root_file(self, db: &dyn HirDatabase) -> FileId { - db.crate_graph()[self.id].root_file_id + self.id.data(db).root_file_id } pub fn edition(self, db: &dyn HirDatabase) -> Edition { - db.crate_graph()[self.id].edition + self.id.data(db).edition } pub fn version(self, db: &dyn HirDatabase) -> Option { - db.crate_graph()[self.id].version.clone() + self.id.extra_data(db).version.clone() } pub fn display_name(self, db: &dyn HirDatabase) -> Option { - db.crate_graph()[self.id].display_name.clone() + self.id.extra_data(db).display_name.clone() } pub fn query_external_importables( @@ -264,7 +264,7 @@ impl Crate { } pub fn all(db: &dyn HirDatabase) -> Vec { - db.crate_graph().iter().map(|id| Crate { id }).collect() + db.all_crates().iter().map(|&id| Crate { id }).collect() } /// Try to get the root URL of the documentation of a crate. @@ -276,12 +276,12 @@ impl Crate { } pub fn cfg(&self, db: &dyn HirDatabase) -> Arc { - db.crate_graph()[self.id].cfg_options.clone() + Arc::clone(self.id.cfg_options(db)) } - pub fn potential_cfg(&self, db: &dyn HirDatabase) -> Arc { - let data = &db.crate_graph()[self.id]; - data.potential_cfg_options.clone().unwrap_or_else(|| data.cfg_options.clone()) + pub fn potential_cfg<'db>(&self, db: &'db dyn HirDatabase) -> &'db CfgOptions { + let data = self.id.extra_data(db); + data.potential_cfg_options.as_ref().unwrap_or_else(|| self.id.cfg_options(db)) } pub fn to_display_target(self, db: &dyn HirDatabase) -> DisplayTarget { @@ -289,11 +289,12 @@ impl Crate { } fn core(db: &dyn HirDatabase) -> Option { - let crate_graph = db.crate_graph(); - let result = crate_graph + let result = db + .all_crates() .iter() + .copied() .find(|&krate| { - matches!(crate_graph[krate].origin, CrateOrigin::Lang(LangCrateOrigin::Core)) + matches!(krate.data(db).origin, CrateOrigin::Lang(LangCrateOrigin::Core)) }) .map(Crate::from); result @@ -490,9 +491,7 @@ impl HasCrate for ModuleDef { fn krate(&self, db: &dyn HirDatabase) -> Crate { match self.module(db) { Some(module) => module.krate(), - None => Crate::core(db).unwrap_or_else(|| { - (*db.crate_graph().crates_in_topological_order().last().unwrap()).into() - }), + None => Crate::core(db).unwrap_or_else(|| db.all_crates()[0].into()), } } } @@ -611,7 +610,7 @@ impl Module { style_lints: bool, ) { let _p = tracing::info_span!("diagnostics", name = ?self.name(db)).entered(); - let edition = db.crate_graph()[self.id.krate()].edition; + let edition = self.id.krate().data(db).edition; let def_map = self.id.def_map(db.upcast()); for diag in def_map.diagnostics() { if diag.in_module != self.id.local_id { @@ -970,7 +969,7 @@ fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec return; }; let krate = HasModule::krate(&m.id, db.upcast()); - let edition = db.crate_graph()[krate].edition; + let edition = krate.data(db).edition; emit_def_diagnostic_( db, acc, @@ -3027,7 +3026,8 @@ impl BuiltinType { } pub fn ty(self, db: &dyn HirDatabase) -> Type { - Type::new_for_crate(db.crate_graph().iter().next().unwrap(), TyBuilder::builtin(self.inner)) + let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]); + Type::new_for_crate(core, TyBuilder::builtin(self.inner)) } pub fn name(self) -> Name { @@ -3968,7 +3968,7 @@ impl DeriveHelper { // FIXME: Wrong name? This is could also be a registered attribute #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct BuiltinAttr { - krate: Option, + krate: Option, idx: u32, } @@ -4014,7 +4014,7 @@ impl BuiltinAttr { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct ToolModule { - krate: CrateId, + krate: base_db::Crate, idx: u32, } @@ -4732,7 +4732,7 @@ impl Type { Type { env: environment, ty } } - pub(crate) fn new_for_crate(krate: CrateId, ty: Ty) -> Type { + pub(crate) fn new_for_crate(krate: base_db::Crate, ty: Ty) -> Type { Type { env: TraitEnvironment::empty(krate), ty } } @@ -4794,7 +4794,7 @@ impl Type { Type { env: ty.env, ty: TyBuilder::slice(ty.ty) } } - pub fn new_tuple(krate: CrateId, tys: &[Type]) -> Type { + pub fn new_tuple(krate: base_db::Crate, tys: &[Type]) -> Type { let tys = tys.iter().map(|it| it.ty.clone()); Type { env: TraitEnvironment::empty(krate), ty: TyBuilder::tuple_with(tys) } } @@ -4826,7 +4826,7 @@ impl Type { pub fn contains_reference(&self, db: &dyn HirDatabase) -> bool { return go(db, self.env.krate, &self.ty); - fn go(db: &dyn HirDatabase, krate: CrateId, ty: &Ty) -> bool { + fn go(db: &dyn HirDatabase, krate: base_db::Crate, ty: &Ty) -> bool { match ty.kind(Interner) { // Reference itself TyKind::Ref(_, _, _) => true, @@ -6209,7 +6209,7 @@ impl HasContainer for Module { let def_map = self.id.def_map(db.upcast()); match def_map[self.id.local_id].parent { Some(parent_id) => ItemContainer::Module(Module { id: def_map.module_id(parent_id) }), - None => ItemContainer::Crate(def_map.krate()), + None => ItemContainer::Crate(def_map.krate().into()), } } } @@ -6289,7 +6289,7 @@ pub enum ItemContainer { Impl(Impl), Module(Module), ExternBlock(ExternBlock), - Crate(CrateId), + Crate(Crate), } /// Subset of `ide_db::Definition` that doc links can resolve to. diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index aeeb3f9790986..6378eebd24fa0 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -318,7 +318,7 @@ impl<'db> SemanticsImpl<'db> { pub fn first_crate_or_default(&self, file: FileId) -> Crate { match self.file_to_module_defs(file).next() { Some(module) => module.krate(), - None => (*self.db.crate_graph().crates_in_topological_order().last().unwrap()).into(), + None => (*self.db.all_crates().last().unwrap()).into(), } } diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index fa8153ad2162d..cc8aa1f1a18ed 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -77,10 +77,7 @@ impl<'a> SymbolCollector<'a> { symbols: Default::default(), work: Default::default(), current_container_name: None, - display_target: DisplayTarget::from_crate( - db, - *db.crate_graph().crates_in_topological_order().last().unwrap(), - ), + display_target: DisplayTarget::from_crate(db, *db.all_crates().last().unwrap()), } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs index 9e09f198feb4a..5a791c58bfd52 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs @@ -7,7 +7,7 @@ use hir::{ sym, FileRange, PathResolution, Semantics, TypeInfo, }; use ide_db::{ - base_db::CrateId, + base_db::Crate, defs::Definition, imports::insert_use::remove_path_if_in_use_stmt, path_transform::PathTransform, @@ -251,11 +251,11 @@ struct CallInfo { node: ast::CallableExpr, arguments: Vec, generic_arg_list: Option, - krate: CrateId, + krate: Crate, } impl CallInfo { - fn from_name_ref(name_ref: ast::NameRef, krate: CrateId) -> Option { + fn from_name_ref(name_ref: ast::NameRef, krate: Crate) -> Option { let parent = name_ref.syntax().parent()?; if let Some(call) = ast::MethodCallExpr::cast(parent.clone()) { let receiver = call.receiver()?; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs index d8b265678278b..4c8940db95cc7 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs @@ -233,7 +233,13 @@ impl RootDatabase { // // SourceDatabase // base_db::ParseQuery // base_db::ParseErrorsQuery - // base_db::CrateGraphQuery + // base_db::AllCratesQuery + // base_db::InternUniqueCrateDataQuery + // base_db::InternUniqueCrateDataLookupQuery + // base_db::CrateDataQuery + // base_db::ExtraCrateDataQuery + // base_db::CrateCfgQuery + // base_db::CrateEnvQuery // base_db::CrateWorkspaceDataQuery // // SourceDatabaseExt diff --git a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs index af4c10f8ea6b5..fe4662785af11 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs @@ -1,6 +1,6 @@ //! See [`FamousDefs`]. -use base_db::{CrateOrigin, LangCrateOrigin, RootQueryDb as _}; +use base_db::{CrateOrigin, LangCrateOrigin}; use hir::{Crate, Enum, Function, Macro, Module, ScopeDef, Semantics, Trait}; use crate::RootDatabase; @@ -198,11 +198,10 @@ impl FamousDefs<'_, '_> { fn find_lang_crate(&self, origin: LangCrateOrigin) -> Option { let krate = self.1; let db = self.0.db; - let crate_graph = self.0.db.crate_graph(); let res = krate .dependencies(db) .into_iter() - .find(|dep| crate_graph[dep.krate.into()].origin == CrateOrigin::Lang(origin))? + .find(|dep| dep.krate.origin(db) == CrateOrigin::Lang(origin))? .krate; Some(res) } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs index 2516a9d0aa388..414cc6cd18fa9 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -51,9 +51,8 @@ use salsa::Durability; use std::{fmt, mem::ManuallyDrop}; use base_db::{ - query_group::{self}, - FileSourceRootInput, FileText, Files, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId, - SourceRootInput, Upcast, + query_group, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Files, RootQueryDb, + SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, Upcast, }; use hir::{ db::{DefDatabase, ExpandDatabase, HirDatabase}, @@ -85,6 +84,7 @@ pub struct RootDatabase { // compile times of all `ide_*` and downstream crates suffer greatly. storage: ManuallyDrop>, files: Arc, + crates_map: Arc, } impl std::panic::RefUnwindSafe for RootDatabase {} @@ -102,7 +102,11 @@ impl Drop for RootDatabase { impl Clone for RootDatabase { fn clone(&self) -> Self { - Self { storage: self.storage.clone(), files: self.files.clone() } + Self { + storage: self.storage.clone(), + files: self.files.clone(), + crates_map: self.crates_map.clone(), + } } } @@ -194,6 +198,10 @@ impl SourceDatabase for RootDatabase { let files = Arc::clone(&self.files); files.set_file_source_root_with_durability(self, id, source_root_id, durability); } + + fn crates_map(&self) -> Arc { + self.crates_map.clone() + } } impl Default for RootDatabase { @@ -207,8 +215,11 @@ impl RootDatabase { let mut db = RootDatabase { storage: ManuallyDrop::new(salsa::Storage::default()), files: Default::default(), + crates_map: Default::default(), }; - db.set_crate_graph_with_durability(Default::default(), Durability::HIGH); + // This needs to be here otherwise `CrateGraphBuilder` will panic. + db.set_all_crates(Arc::new(Box::new([]))); + CrateGraphBuilder::default().set_in_db(&mut db); db.set_proc_macros_with_durability(Default::default(), Durability::HIGH); db.set_local_roots_with_durability(Default::default(), Durability::HIGH); db.set_library_roots_with_durability(Default::default(), Durability::HIGH); @@ -258,7 +269,11 @@ impl RootDatabase { } pub fn snapshot(&self) -> Self { - Self { storage: self.storage.clone(), files: self.files.clone() } + Self { + storage: self.storage.clone(), + files: self.files.clone(), + crates_map: self.crates_map.clone(), + } } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs index 74d79cd69557f..cd3099fe93819 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs @@ -11,7 +11,7 @@ use itertools::Itertools; use salsa::{Cancelled, Database}; use crate::{ - base_db::{CrateId, RootQueryDb}, + base_db::{Crate, RootQueryDb}, symbol_index::SymbolsDatabase, FxIndexMap, RootDatabase, }; @@ -35,20 +35,22 @@ pub fn parallel_prime_caches( ) { let _p = tracing::info_span!("parallel_prime_caches").entered(); - let graph = db.crate_graph(); let mut crates_to_prime = { + // FIXME: We already have the crate list topologically sorted (but without the things + // `TopologicalSortIter` gives us). Maybe there is a way to avoid using it and rip it out + // of the codebase? let mut builder = topologic_sort::TopologicalSortIter::builder(); - for crate_id in graph.iter() { - builder.add(crate_id, graph[crate_id].dependencies.iter().map(|d| d.crate_id)); + for &crate_id in db.all_crates().iter() { + builder.add(crate_id, crate_id.data(db).dependencies.iter().map(|d| d.crate_id)); } builder.build() }; enum ParallelPrimeCacheWorkerProgress { - BeginCrate { crate_id: CrateId, crate_name: Symbol }, - EndCrate { crate_id: CrateId }, + BeginCrate { crate_id: Crate, crate_name: Symbol }, + EndCrate { crate_id: Crate }, } // We split off def map computation from other work, @@ -108,16 +110,14 @@ pub fn parallel_prime_caches( while crates_done < crates_total { db.unwind_if_revision_cancelled(); - for crate_id in &mut crates_to_prime { - let krate = &graph[crate_id]; - let name = krate - .display_name - .as_deref() - .cloned() - .unwrap_or_else(|| Symbol::integer(crate_id.into_raw().into_u32() as usize)); - if krate.origin.is_lang() { - additional_phases.push((crate_id, name.clone(), PrimingPhase::ImportMap)); - } else if krate.origin.is_local() { + for krate in &mut crates_to_prime { + let name = krate.extra_data(db).display_name.as_deref().cloned().unwrap_or_else(|| { + Symbol::integer(salsa::plumbing::AsId::as_id(&krate).as_u32() as usize) + }); + let origin = &krate.data(db).origin; + if origin.is_lang() { + additional_phases.push((krate, name.clone(), PrimingPhase::ImportMap)); + } else if origin.is_local() { // Compute the symbol search index. // This primes the cache for `ide_db::symbol_index::world_symbols()`. // @@ -127,10 +127,10 @@ pub fn parallel_prime_caches( // FIXME: We should do it unconditionally if the configuration is set to default to // searching dependencies (rust-analyzer.workspace.symbol.search.scope), but we // would need to pipe that configuration information down here. - additional_phases.push((crate_id, name.clone(), PrimingPhase::CrateSymbols)); + additional_phases.push((krate, name.clone(), PrimingPhase::CrateSymbols)); } - work_sender.send((crate_id, name, PrimingPhase::DefMap)).ok(); + work_sender.send((krate, name, PrimingPhase::DefMap)).ok(); } // recv_timeout is somewhat a hack, we need a way to from this thread check to see if the current salsa revision diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index 81df0c0f0f88b..4f9ef05b20e79 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -162,13 +162,13 @@ impl SearchScope { fn crate_graph(db: &RootDatabase) -> SearchScope { let mut entries = FxHashMap::default(); - let graph = db.crate_graph(); - for krate in graph.iter() { - let root_file = graph[krate].root_file_id; - let source_root = db.file_source_root(root_file).source_root_id(db); + let all_crates = db.all_crates(); + for &krate in all_crates.iter() { + let crate_data = krate.data(db); + let source_root = db.file_source_root(crate_data.root_file_id).source_root_id(db); let source_root = db.source_root(source_root).source_root(db); entries.extend( - source_root.iter().map(|id| (EditionedFileId::new(id, graph[krate].edition), None)), + source_root.iter().map(|id| (EditionedFileId::new(id, crate_data.edition), None)), ); } SearchScope { entries } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt index 0cae7f367c205..1e2d4f1ab94fc 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt @@ -2,7 +2,9 @@ ( Module { id: ModuleId { - krate: Idx::(0), + krate: Crate { + [salsa id]: Id(2c00), + }, block: None, local_id: Idx::(0), }, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt index 48de1fb837a20..1a77052b18d46 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt @@ -2,7 +2,9 @@ ( Module { id: ModuleId { - krate: Idx::(0), + krate: Crate { + [salsa id]: Id(2c00), + }, block: None, local_id: Idx::(0), }, @@ -532,7 +534,9 @@ def: Module( Module { id: ModuleId { - krate: Idx::(0), + krate: Crate { + [salsa id]: Id(2c00), + }, block: None, local_id: Idx::(1), }, @@ -565,7 +569,9 @@ def: Module( Module { id: ModuleId { - krate: Idx::(0), + krate: Crate { + [salsa id]: Id(2c00), + }, block: None, local_id: Idx::(2), }, @@ -827,7 +833,9 @@ ( Module { id: ModuleId { - krate: Idx::(0), + krate: Crate { + [salsa id]: Id(2c00), + }, block: None, local_id: Idx::(1), }, @@ -871,7 +879,9 @@ ( Module { id: ModuleId { - krate: Idx::(0), + krate: Crate { + [salsa id]: Id(2c00), + }, block: None, local_id: Idx::(2), }, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index 5ce3336eb41f6..f4ced736b3df8 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -389,9 +389,9 @@ pub fn semantic_diagnostics( module.and_then(|m| db.toolchain_channel(m.krate().into())), Some(ReleaseChannel::Nightly) | None ); - let krate = module.map(|module| module.krate()).unwrap_or_else(|| { - (*db.crate_graph().crates_in_topological_order().last().unwrap()).into() - }); + let krate = module + .map(|module| module.krate()) + .unwrap_or_else(|| (*db.all_crates().last().unwrap()).into()); let display_target = krate.to_display_target(db); let ctx = DiagnosticsContext { config, sema, resolve, edition, is_nightly, display_target }; diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs index d32ba06f1eb4f..48d2431a11fbf 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs @@ -626,11 +626,11 @@ impl<'db, 'sema> Matcher<'db, 'sema> { match_error!("Failed to get receiver type for `{}`", expr.syntax().text()) })? .original; - let krate = self.sema.scope(expr.syntax()).map(|it| it.krate()).unwrap_or_else(|| { - hir::Crate::from( - *self.sema.db.crate_graph().crates_in_topological_order().last().unwrap(), - ) - }); + let krate = self + .sema + .scope(expr.syntax()) + .map(|it| it.krate()) + .unwrap_or_else(|| hir::Crate::from(*self.sema.db.all_crates().last().unwrap())); let res = code_type .autoderef(self.sema.db) .enumerate() diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index 0acb129e93986..9bdc2e7d13337 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -504,9 +504,7 @@ fn get_doc_base_urls( let Some(krate) = krate else { return Default::default() }; let Some(display_name) = krate.display_name(db) else { return Default::default() }; - let crate_data = &db.crate_graph()[krate.into()]; - - let (web_base, local_base) = match &crate_data.origin { + let (web_base, local_base) = match krate.origin(db) { // std and co do not specify `html_root_url` any longer so we gotta handwrite this ourself. // FIXME: Use the toolchains channel instead of nightly CrateOrigin::Lang( diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index 2347e2e8a36d8..3771efc17b69d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -1,8 +1,8 @@ use hir::db::ExpandDatabase; use hir::{ExpandResult, InFile, MacroFileIdExt, Semantics}; -use ide_db::base_db::CrateId; use ide_db::{ - helpers::pick_best_token, syntax_helpers::prettify_macro_expansion, FileId, RootDatabase, + base_db::Crate, helpers::pick_best_token, syntax_helpers::prettify_macro_expansion, FileId, + RootDatabase, }; use span::{Edition, SpanMap, SyntaxContextId, TextRange, TextSize}; use stdx::format_to; @@ -208,7 +208,7 @@ fn format( file_id: FileId, expanded: SyntaxNode, span_map: &SpanMap, - krate: CrateId, + krate: Crate, ) -> String { let expansion = prettify_macro_expansion(db, expanded, span_map, krate).to_string(); @@ -249,7 +249,7 @@ fn _format( let upcast_db = ide_db::base_db::Upcast::::upcast(db); let &crate_id = upcast_db.relevant_crates(file_id).iter().next()?; - let edition = upcast_db.crate_graph()[crate_id].edition; + let edition = crate_id.data(upcast_db).edition; #[allow(clippy::disallowed_methods)] let mut cmd = std::process::Command::new(toolchain::Tool::Rustfmt.path()); diff --git a/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs b/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs index 0e5bb89b6b717..b682c4bc0f791 100644 --- a/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs +++ b/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs @@ -20,21 +20,24 @@ pub struct CrateInfo { // // ![Show Dependency Tree](https://user-images.githubusercontent.com/5748995/229394139-2625beab-f4c9-484b-84ed-ad5dee0b1e1a.png) pub(crate) fn fetch_crates(db: &RootDatabase) -> FxIndexSet { - let crate_graph = db.crate_graph(); - crate_graph + db.all_crates() .iter() - .map(|crate_id| &crate_graph[crate_id]) - .filter(|&data| !matches!(data.origin, CrateOrigin::Local { .. })) - .map(crate_info) + .copied() + .map(|crate_id| (crate_id.data(db), crate_id.extra_data(db))) + .filter(|(data, _)| !matches!(data.origin, CrateOrigin::Local { .. })) + .map(|(data, extra_data)| crate_info(data, extra_data)) .collect() } -fn crate_info(data: &ide_db::base_db::CrateData) -> CrateInfo { - let crate_name = crate_name(data); - let version = data.version.clone(); +fn crate_info( + data: &ide_db::base_db::BuiltCrateData, + extra_data: &ide_db::base_db::ExtraCrateData, +) -> CrateInfo { + let crate_name = crate_name(extra_data); + let version = extra_data.version.clone(); CrateInfo { name: crate_name, version, root_file_id: data.root_file_id } } -fn crate_name(data: &ide_db::base_db::CrateData) -> Option { +fn crate_name(data: &ide_db::base_db::ExtraCrateData) -> Option { data.display_name.as_ref().map(|it| it.canonical_name().as_str().to_owned()) } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index 5d888ceb5edb9..1d807fb14c7bf 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -8,7 +8,6 @@ use hir::{ MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef, }; use ide_db::{ - base_db::RootQueryDb, defs::Definition, documentation::HasDocs, famous_defs::FamousDefs, @@ -466,8 +465,7 @@ pub(super) fn path( item_name: Option, edition: Edition, ) -> String { - let crate_name = - db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string()); + let crate_name = module.krate().display_name(db).as_ref().map(|it| it.to_string()); let module_path = module .path_to_root(db) .into_iter() diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 736d355ef2276..afddeb6deaa62 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -9252,7 +9252,7 @@ fn main() { S ``` ___ - Implements notable traits: Notable, Future, Iterator"#]], + Implements notable traits: Future, Iterator, Notable"#]], ); } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs index 592c8603964da..aab8a3f873994 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs @@ -868,15 +868,15 @@ fn main() { //- minicore: fn fn main() { let x = || 2; - //^ {closure#26624} + //^ {closure#25600} let y = |t: i32| x() + t; - //^ {closure#26625} + //^ {closure#25601} let mut t = 5; //^ i32 let z = |k: i32| { t += k; }; - //^ {closure#26626} + //^ {closure#25602} let p = (y, z); - //^ ({closure#26625}, {closure#26626}) + //^ ({closure#25601}, {closure#25602}) } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index dcb170f3f7b63..79863f4680d80 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -57,7 +57,7 @@ mod view_memory_layout; mod view_mir; mod view_syntax_tree; -use std::{iter, panic::UnwindSafe}; +use std::panic::UnwindSafe; use cfg::CfgOptions; use fetch_crates::CrateInfo; @@ -125,7 +125,7 @@ pub use ide_completion::{ }; pub use ide_db::text_edit::{Indel, TextEdit}; pub use ide_db::{ - base_db::{CrateGraph, CrateId, FileChange, SourceRoot, SourceRootId}, + base_db::{Crate, CrateGraphBuilder, FileChange, SourceRoot, SourceRootId}, documentation::Documentation, label::Label, line_index::{LineCol, LineIndex}, @@ -239,7 +239,7 @@ impl Analysis { let mut change = ChangeWithProcMacros::new(); change.set_roots(vec![source_root]); - let mut crate_graph = CrateGraph::default(); + let mut crate_graph = CrateGraphBuilder::default(); // FIXME: cfg options // Default to enable test for single file. let mut cfg_options = CfgOptions::default(); @@ -255,16 +255,13 @@ impl Analysis { CrateOrigin::Local { repo: None, name: None }, false, None, - ); - change.change_file(file_id, Some(text)); - let ws_data = crate_graph - .iter() - .zip(iter::repeat(Arc::new(CrateWorkspaceData { + Arc::new(CrateWorkspaceData { data_layout: Err("fixture has no layout".into()), toolchain: None, - }))) - .collect(); - change.set_crate_graph(crate_graph, ws_data); + }), + ); + change.change_file(file_id, Some(text)); + change.set_crate_graph(crate_graph); host.apply_change(change); (host.analysis(), file_id) @@ -372,7 +369,7 @@ impl Analysis { self.with_db(|db| test_explorer::discover_tests_in_crate_by_test_id(db, crate_id)) } - pub fn discover_tests_in_crate(&self, crate_id: CrateId) -> Cancellable> { + pub fn discover_tests_in_crate(&self, crate_id: Crate) -> Cancellable> { self.with_db(|db| test_explorer::discover_tests_in_crate(db, crate_id)) } @@ -602,17 +599,17 @@ impl Analysis { } /// Returns crates that this file belongs to. - pub fn crates_for(&self, file_id: FileId) -> Cancellable> { + pub fn crates_for(&self, file_id: FileId) -> Cancellable> { self.with_db(|db| parent_module::crates_for(db, file_id)) } /// Returns crates that this file belongs to. - pub fn transitive_rev_deps(&self, crate_id: CrateId) -> Cancellable> { - self.with_db(|db| db.crate_graph().transitive_rev_deps(crate_id).collect()) + pub fn transitive_rev_deps(&self, crate_id: Crate) -> Cancellable> { + self.with_db(|db| Vec::from_iter(db.transitive_rev_deps(crate_id))) } /// Returns crates that this file *might* belong to. - pub fn relevant_crates_for(&self, file_id: FileId) -> Cancellable> { + pub fn relevant_crates_for(&self, file_id: FileId) -> Cancellable> { self.with_db(|db| { let db = Upcast::::upcast(db); db.relevant_crates(file_id).iter().copied().collect() @@ -620,18 +617,23 @@ impl Analysis { } /// Returns the edition of the given crate. - pub fn crate_edition(&self, crate_id: CrateId) -> Cancellable { - self.with_db(|db| db.crate_graph()[crate_id].edition) + pub fn crate_edition(&self, crate_id: Crate) -> Cancellable { + self.with_db(|db| crate_id.data(db).edition) + } + + /// Returns whether the given crate is a proc macro. + pub fn is_proc_macro_crate(&self, crate_id: Crate) -> Cancellable { + self.with_db(|db| crate_id.data(db).is_proc_macro) } /// Returns true if this crate has `no_std` or `no_core` specified. - pub fn is_crate_no_std(&self, crate_id: CrateId) -> Cancellable { + pub fn is_crate_no_std(&self, crate_id: Crate) -> Cancellable { self.with_db(|db| hir::db::DefDatabase::crate_def_map(db, crate_id).is_no_std()) } /// Returns the root file of the given crate. - pub fn crate_root(&self, crate_id: CrateId) -> Cancellable { - self.with_db(|db| db.crate_graph()[crate_id].root_file_id) + pub fn crate_root(&self, crate_id: Crate) -> Cancellable { + self.with_db(|db| crate_id.data(db).root_file_id) } /// Returns the set of possible targets to run for the current file. diff --git a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs index 90cccca5e80f4..06ab4750ac5b9 100644 --- a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs +++ b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs @@ -1,6 +1,6 @@ use hir::{db::DefDatabase, Semantics}; use ide_db::{ - base_db::{CrateId, RootQueryDb, Upcast}, + base_db::{Crate, RootQueryDb, Upcast}, FileId, FilePosition, RootDatabase, }; use itertools::Itertools; @@ -53,7 +53,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec Vec { +pub(crate) fn crates_for(db: &RootDatabase, file_id: FileId) -> Vec { let root_db = Upcast::::upcast(db); root_db .relevant_crates(file_id) diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index 33eef6d75c21a..baa7ee6897352 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -498,9 +498,8 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option { }; let krate = def.krate(db); let edition = krate.map(|it| it.edition(db)).unwrap_or(Edition::CURRENT); - let display_target = krate - .unwrap_or_else(|| (*db.crate_graph().crates_in_topological_order().last().unwrap()).into()) - .to_display_target(db); + let display_target = + krate.unwrap_or_else(|| (*db.all_crates().last().unwrap()).into()).to_display_target(db); if !has_runnable_doc_test(&attrs) { return None; } diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs index ceea34b721373..5a2b09b513774 100644 --- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs +++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs @@ -119,9 +119,7 @@ fn documentation_for_definition( sema.db, famous_defs.as_ref(), def.krate(sema.db) - .unwrap_or_else(|| { - (*sema.db.crate_graph().crates_in_topological_order().last().unwrap()).into() - }) + .unwrap_or_else(|| (*sema.db.all_crates().last().unwrap()).into()) .to_display_target(sema.db), ) } diff --git a/src/tools/rust-analyzer/crates/ide/src/status.rs b/src/tools/rust-analyzer/crates/ide/src/status.rs index 47ac4ebf20e3b..52d38041ec125 100644 --- a/src/tools/rust-analyzer/crates/ide/src/status.rs +++ b/src/tools/rust-analyzer/crates/ide/src/status.rs @@ -1,4 +1,4 @@ -use ide_db::base_db::{CrateData, RootQueryDb, Upcast}; +use ide_db::base_db::{BuiltCrateData, ExtraCrateData}; use ide_db::RootDatabase; use itertools::Itertools; use span::FileId; @@ -34,28 +34,25 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option) -> String { if crates.is_empty() { format_to!(buf, "Does not belong to any crate"); } - - let crate_graph = Upcast::::upcast(db).crate_graph(); for crate_id in crates { - let CrateData { + let BuiltCrateData { root_file_id, edition, - version, - display_name, - cfg_options, - potential_cfg_options, - env, dependencies, origin, is_proc_macro, proc_macro_cwd, - } = &crate_graph[crate_id]; + } = crate_id.data(db); + let ExtraCrateData { version, display_name, potential_cfg_options } = + crate_id.extra_data(db); + let cfg_options = crate_id.cfg_options(db); + let env = crate_id.env(db); format_to!( buf, "Crate: {}\n", match display_name { - Some(it) => format!("{it}({})", crate_id.into_raw()), - None => format!("{}", crate_id.into_raw()), + Some(it) => format!("{it}({:?})", crate_id), + None => format!("{:?}", crate_id), } ); format_to!(buf, " Root module file id: {}\n", root_file_id.index()); @@ -69,7 +66,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option) -> String { format_to!(buf, " Proc macro cwd: {:?}\n", proc_macro_cwd); let deps = dependencies .iter() - .map(|dep| format!("{}={}", dep.name, dep.crate_id.into_raw())) + .map(|dep| format!("{}={:?}", dep.name, dep.crate_id)) .format(", "); format_to!(buf, " Dependencies: {}\n", deps); } diff --git a/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs index 68f5c72d20531..d22133c856587 100644 --- a/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs +++ b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs @@ -1,17 +1,15 @@ //! Discovers tests use hir::{Crate, Module, ModuleDef, Semantics}; -use ide_db::{ - base_db::{CrateGraph, CrateId, RootQueryDb}, - FileId, RootDatabase, -}; +use ide_db::base_db; +use ide_db::{base_db::RootQueryDb, FileId, RootDatabase}; use syntax::TextRange; use crate::{runnables::runnable_fn, NavigationTarget, Runnable, TryToNav}; #[derive(Debug)] pub enum TestItemKind { - Crate(CrateId), + Crate(base_db::Crate), Module, Function, } @@ -28,12 +26,12 @@ pub struct TestItem { } pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec { - let crate_graph = db.crate_graph(); - crate_graph + db.all_crates() .iter() - .filter(|&id| crate_graph[id].origin.is_local()) + .copied() + .filter(|&id| id.data(db).origin.is_local()) .filter_map(|id| { - let test_id = crate_graph[id].display_name.as_ref()?.to_string(); + let test_id = id.extra_data(db).display_name.as_ref()?.to_string(); Some(TestItem { kind: TestItemKind::Crate(id), label: test_id.clone(), @@ -47,12 +45,12 @@ pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec { .collect() } -fn find_crate_by_id(crate_graph: &CrateGraph, crate_id: &str) -> Option { +fn find_crate_by_id(db: &RootDatabase, crate_id: &str) -> Option { // here, we use display_name as the crate id. This is not super ideal, but it works since we // only show tests for the local crates. - crate_graph.iter().find(|&id| { - crate_graph[id].origin.is_local() - && crate_graph[id].display_name.as_ref().is_some_and(|x| x.to_string() == crate_id) + db.all_crates().iter().copied().find(|&id| { + id.data(db).origin.is_local() + && id.extra_data(db).display_name.as_ref().is_some_and(|x| x.to_string() == crate_id) }) } @@ -115,8 +113,7 @@ pub(crate) fn discover_tests_in_crate_by_test_id( db: &RootDatabase, crate_test_id: &str, ) -> Vec { - let crate_graph = db.crate_graph(); - let Some(crate_id) = find_crate_by_id(&crate_graph, crate_test_id) else { + let Some(crate_id) = find_crate_by_id(db, crate_test_id) else { return vec![]; }; discover_tests_in_crate(db, crate_id) @@ -171,12 +168,14 @@ fn find_module_id_and_test_parents( Some((r, id)) } -pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> Vec { - let crate_graph = db.crate_graph(); - if !crate_graph[crate_id].origin.is_local() { +pub(crate) fn discover_tests_in_crate( + db: &RootDatabase, + crate_id: base_db::Crate, +) -> Vec { + if !crate_id.data(db).origin.is_local() { return vec![]; } - let Some(crate_test_id) = &crate_graph[crate_id].display_name else { + let Some(crate_test_id) = &crate_id.extra_data(db).display_name else { return vec![]; }; let kind = TestItemKind::Crate(crate_id); diff --git a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs index eeb65ac038932..09f21ecfe41cc 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs @@ -1,9 +1,10 @@ use dot::{Id, LabelText}; use ide_db::{ - base_db::{CrateGraph, CrateId, Dependency, RootQueryDb, SourceDatabase, Upcast}, - FxHashSet, RootDatabase, + base_db::{ + BuiltCrateData, BuiltDependency, Crate, ExtraCrateData, RootQueryDb, SourceDatabase, + }, + FxHashMap, RootDatabase, }; -use triomphe::Arc; // Feature: View Crate Graph // @@ -16,77 +17,80 @@ use triomphe::Arc; // |---------|-------------| // | VS Code | **rust-analyzer: View Crate Graph** | pub(crate) fn view_crate_graph(db: &RootDatabase, full: bool) -> Result { - let crate_graph = Upcast::::upcast(db).crate_graph(); - let crates_to_render = crate_graph + let all_crates = db.all_crates(); + let crates_to_render = all_crates .iter() - .filter(|krate| { + .copied() + .map(|krate| (krate, (krate.data(db), krate.extra_data(db)))) + .filter(|(_, (crate_data, _))| { if full { true } else { // Only render workspace crates - let root_id = - db.file_source_root(crate_graph[*krate].root_file_id).source_root_id(db); + let root_id = db.file_source_root(crate_data.root_file_id).source_root_id(db); !db.source_root(root_id).source_root(db).is_library } }) .collect(); - let graph = DotCrateGraph { graph: crate_graph, crates_to_render }; + let graph = DotCrateGraph { crates_to_render }; let mut dot = Vec::new(); dot::render(&graph, &mut dot).unwrap(); Ok(String::from_utf8(dot).unwrap()) } -struct DotCrateGraph { - graph: Arc, - crates_to_render: FxHashSet, +struct DotCrateGraph<'db> { + crates_to_render: FxHashMap, } -type Edge<'a> = (CrateId, &'a Dependency); +type Edge<'a> = (Crate, &'a BuiltDependency); -impl<'a> dot::GraphWalk<'a, CrateId, Edge<'a>> for DotCrateGraph { - fn nodes(&'a self) -> dot::Nodes<'a, CrateId> { - self.crates_to_render.iter().copied().collect() +impl<'a> dot::GraphWalk<'a, Crate, Edge<'a>> for DotCrateGraph<'_> { + fn nodes(&'a self) -> dot::Nodes<'a, Crate> { + self.crates_to_render.keys().copied().collect() } fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { self.crates_to_render .iter() - .flat_map(|krate| { - self.graph[*krate] + .flat_map(|(krate, (crate_data, _))| { + crate_data .dependencies .iter() - .filter(|dep| self.crates_to_render.contains(&dep.crate_id)) + .filter(|dep| self.crates_to_render.contains_key(&dep.crate_id)) .map(move |dep| (*krate, dep)) }) .collect() } - fn source(&'a self, edge: &Edge<'a>) -> CrateId { + fn source(&'a self, edge: &Edge<'a>) -> Crate { edge.0 } - fn target(&'a self, edge: &Edge<'a>) -> CrateId { + fn target(&'a self, edge: &Edge<'a>) -> Crate { edge.1.crate_id } } -impl<'a> dot::Labeller<'a, CrateId, Edge<'a>> for DotCrateGraph { +impl<'a> dot::Labeller<'a, Crate, Edge<'a>> for DotCrateGraph<'_> { fn graph_id(&'a self) -> Id<'a> { Id::new("rust_analyzer_crate_graph").unwrap() } - fn node_id(&'a self, n: &CrateId) -> Id<'a> { - Id::new(format!("_{}", u32::from(n.into_raw()))).unwrap() + fn node_id(&'a self, n: &Crate) -> Id<'a> { + Id::new(format!("_{:?}", n)).unwrap() } - fn node_shape(&'a self, _node: &CrateId) -> Option> { + fn node_shape(&'a self, _node: &Crate) -> Option> { Some(LabelText::LabelStr("box".into())) } - fn node_label(&'a self, n: &CrateId) -> LabelText<'a> { - let name = - self.graph[*n].display_name.as_ref().map_or("(unnamed crate)", |name| name.as_str()); + fn node_label(&'a self, n: &Crate) -> LabelText<'a> { + let name = self.crates_to_render[n] + .1 + .display_name + .as_ref() + .map_or("(unnamed crate)", |name| name.as_str()); LabelText::LabelStr(name.into()) } } diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index 0fa6701ca3fa3..f6a74d97416ef 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -42,6 +42,18 @@ struct TaggedArcPtr { unsafe impl Send for TaggedArcPtr {} unsafe impl Sync for TaggedArcPtr {} +impl Ord for TaggedArcPtr { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.as_str().cmp(other.as_str()) + } +} + +impl PartialOrd for TaggedArcPtr { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + impl TaggedArcPtr { const BOOL_BITS: usize = true as usize; @@ -113,7 +125,7 @@ impl TaggedArcPtr { } } -#[derive(PartialEq, Eq, Hash)] +#[derive(PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Symbol { repr: TaggedArcPtr, } diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index fbb0043ad2d21..01d29d88df4a2 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -2,15 +2,15 @@ //! for incorporating changes. // Note, don't remove any public api from this. This API is consumed by external tools // to run rust-analyzer as a library. -use std::{collections::hash_map::Entry, iter, mem, path::Path, sync}; +use std::{collections::hash_map::Entry, mem, path::Path, sync}; use crossbeam_channel::{unbounded, Receiver}; use hir_expand::proc_macro::{ ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacroLoadResult, - ProcMacros, + ProcMacrosBuilder, }; use ide_db::{ - base_db::{CrateGraph, CrateWorkspaceData, Env, SourceRoot, SourceRootId}, + base_db::{CrateGraphBuilder, Env, SourceRoot, SourceRootId}, prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase, }; use itertools::Itertools; @@ -139,7 +139,6 @@ pub fn load_workspace( }); let db = load_crate_graph( - &ws, crate_graph, proc_macros, project_folders.source_root_config, @@ -418,15 +417,12 @@ pub fn load_proc_macro( } fn load_crate_graph( - ws: &ProjectWorkspace, - crate_graph: CrateGraph, - proc_macros: ProcMacros, + crate_graph: CrateGraphBuilder, + proc_macros: ProcMacrosBuilder, source_root_config: SourceRootConfig, vfs: &mut vfs::Vfs, receiver: &Receiver, ) -> RootDatabase { - let ProjectWorkspace { toolchain, target_layout, .. } = ws; - let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::().ok()); let mut db = RootDatabase::new(lru_cap); let mut analysis_change = ChangeWithProcMacros::new(); @@ -461,14 +457,7 @@ fn load_crate_graph( let source_roots = source_root_config.partition(vfs); analysis_change.set_roots(source_roots); - let ws_data = crate_graph - .iter() - .zip(iter::repeat(From::from(CrateWorkspaceData { - data_layout: target_layout.clone(), - toolchain: toolchain.clone(), - }))) - .collect(); - analysis_change.set_crate_graph(crate_graph, ws_data); + analysis_change.set_crate_graph(crate_graph); analysis_change.set_proc_macros(proc_macros); db.apply_change(analysis_change); @@ -494,7 +483,7 @@ fn expander_to_proc_macro( } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] struct Expander(proc_macro_api::ProcMacro); impl ProcMacroExpander for Expander { @@ -522,6 +511,10 @@ impl ProcMacroExpander for Expander { Err(err) => Err(ProcMacroExpansionError::System(err.to_string())), } } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.as_any().downcast_ref::().is_some_and(|other| self == other) + } } #[cfg(test)] @@ -543,7 +536,7 @@ mod tests { let (db, _vfs, _proc_macro) = load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {}).unwrap(); - let n_crates = db.crate_graph().iter().count(); + let n_crates = db.all_crates().len(); // RA has quite a few crates, but the exact count doesn't matter assert!(n_crates > 20); } diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs index dc3328ebcda48..571ceaabe62cd 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs @@ -13,7 +13,7 @@ mod process; use paths::{AbsPath, AbsPathBuf}; use span::Span; -use std::{fmt, io, sync::Arc}; +use std::{fmt, io, sync::Arc, time::SystemTime}; use crate::{ legacy_protocol::msg::{ @@ -66,6 +66,7 @@ pub struct ProcMacro { dylib_path: Arc, name: Box, kind: ProcMacroKind, + dylib_last_modified: Option, } impl Eq for ProcMacro {} @@ -73,7 +74,8 @@ impl PartialEq for ProcMacro { fn eq(&self, other: &Self) -> bool { self.name == other.name && self.kind == other.kind - && Arc::ptr_eq(&self.dylib_path, &other.dylib_path) + && self.dylib_path == other.dylib_path + && self.dylib_last_modified == other.dylib_last_modified && Arc::ptr_eq(&self.process, &other.process) } } @@ -116,6 +118,9 @@ impl ProcMacroClient { let macros = self.process.find_proc_macros(&dylib.path)?; let dylib_path = Arc::new(dylib.path); + let dylib_last_modified = std::fs::metadata(dylib_path.as_path()) + .ok() + .and_then(|metadata| metadata.modified().ok()); match macros { Ok(macros) => Ok(macros .into_iter() @@ -124,6 +129,7 @@ impl ProcMacroClient { name: name.into(), kind, dylib_path: dylib_path.clone(), + dylib_last_modified, }) .collect()), Err(message) => Err(ServerError { message, io: None }), diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs index 15de88ea656d0..716d351271efa 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs @@ -12,7 +12,7 @@ fn test_derive_empty() { "DeriveEmpty", r#"struct S;"#, expect!["SUBTREE $$ 1 1"], - expect!["SUBTREE $$ 42:2@0..100#2 42:2@0..100#2"], + expect!["SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037"], ); } @@ -29,12 +29,12 @@ fn test_derive_error() { LITERAL Str #[derive(DeriveError)] struct S ; 1 PUNCH ; [alone] 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 - IDENT compile_error 42:2@0..100#2 - PUNCH ! [alone] 42:2@0..100#2 - SUBTREE () 42:2@0..100#2 42:2@0..100#2 - LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#2 - PUNCH ; [alone] 42:2@0..100#2"#]], + SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037 + IDENT compile_error 42:2@0..100#4294967037 + PUNCH ! [alone] 42:2@0..100#4294967037 + SUBTREE () 42:2@0..100#4294967037 42:2@0..100#4294967037 + LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#4294967037 + PUNCH ; [alone] 42:2@0..100#4294967037"#]], ); } @@ -53,14 +53,14 @@ fn test_fn_like_macro_noop() { PUNCH , [alone] 1 SUBTREE [] 1 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 - IDENT ident 42:2@0..5#2 - PUNCH , [alone] 42:2@5..6#2 - LITERAL Integer 0 42:2@7..8#2 - PUNCH , [alone] 42:2@8..9#2 - LITERAL Integer 1 42:2@10..11#2 - PUNCH , [alone] 42:2@11..12#2 - SUBTREE [] 42:2@13..14#2 42:2@14..15#2"#]], + SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037 + IDENT ident 42:2@0..5#4294967037 + PUNCH , [alone] 42:2@5..6#4294967037 + LITERAL Integer 0 42:2@7..8#4294967037 + PUNCH , [alone] 42:2@8..9#4294967037 + LITERAL Integer 1 42:2@10..11#4294967037 + PUNCH , [alone] 42:2@11..12#4294967037 + SUBTREE [] 42:2@13..14#4294967037 42:2@14..15#4294967037"#]], ); } @@ -75,10 +75,10 @@ fn test_fn_like_macro_clone_ident_subtree() { PUNCH , [alone] 1 SUBTREE [] 1 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 - IDENT ident 42:2@0..5#2 - PUNCH , [alone] 42:2@5..6#2 - SUBTREE [] 42:2@7..8#2 42:2@7..8#2"#]], + SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037 + IDENT ident 42:2@0..5#4294967037 + PUNCH , [alone] 42:2@5..6#4294967037 + SUBTREE [] 42:2@7..8#4294967037 42:2@7..8#4294967037"#]], ); } @@ -91,8 +91,8 @@ fn test_fn_like_macro_clone_raw_ident() { SUBTREE $$ 1 1 IDENT r#async 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 - IDENT r#async 42:2@0..7#2"#]], + SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037 + IDENT r#async 42:2@0..7#4294967037"#]], ); } @@ -105,8 +105,8 @@ fn test_fn_like_fn_like_span_join() { SUBTREE $$ 1 1 IDENT r#joined 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 - IDENT r#joined 42:2@0..11#2"#]], + SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037 + IDENT r#joined 42:2@0..11#4294967037"#]], ); } @@ -121,10 +121,10 @@ fn test_fn_like_fn_like_span_ops() { IDENT resolved_at_def_site 1 IDENT start_span 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 - IDENT set_def_site 41:1@0..150#2 - IDENT resolved_at_def_site 42:2@13..33#2 - IDENT start_span 42:2@34..34#2"#]], + SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037 + IDENT set_def_site 41:1@0..150#4294967037 + IDENT resolved_at_def_site 42:2@13..33#4294967037 + IDENT start_span 42:2@34..34#4294967037"#]], ); } @@ -143,14 +143,14 @@ fn test_fn_like_mk_literals() { LITERAL Integer 123i64 1 LITERAL Integer 123 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 - LITERAL ByteStr byte_string 42:2@0..100#2 - LITERAL Char c 42:2@0..100#2 - LITERAL Str string 42:2@0..100#2 - LITERAL Float 3.14f64 42:2@0..100#2 - LITERAL Float 3.14 42:2@0..100#2 - LITERAL Integer 123i64 42:2@0..100#2 - LITERAL Integer 123 42:2@0..100#2"#]], + SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037 + LITERAL ByteStr byte_string 42:2@0..100#4294967037 + LITERAL Char c 42:2@0..100#4294967037 + LITERAL Str string 42:2@0..100#4294967037 + LITERAL Float 3.14f64 42:2@0..100#4294967037 + LITERAL Float 3.14 42:2@0..100#4294967037 + LITERAL Integer 123i64 42:2@0..100#4294967037 + LITERAL Integer 123 42:2@0..100#4294967037"#]], ); } @@ -164,9 +164,9 @@ fn test_fn_like_mk_idents() { IDENT standard 1 IDENT r#raw 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 - IDENT standard 42:2@0..100#2 - IDENT r#raw 42:2@0..100#2"#]], + SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037 + IDENT standard 42:2@0..100#4294967037 + IDENT r#raw 42:2@0..100#4294967037"#]], ); } @@ -198,27 +198,27 @@ fn test_fn_like_macro_clone_literals() { PUNCH , [alone] 1 LITERAL CStr null 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 - LITERAL Integer 1u16 42:2@0..4#2 - PUNCH , [alone] 42:2@4..5#2 - LITERAL Integer 2_u32 42:2@6..11#2 - PUNCH , [alone] 42:2@11..12#2 - PUNCH - [alone] 42:2@13..14#2 - LITERAL Integer 4i64 42:2@14..18#2 - PUNCH , [alone] 42:2@18..19#2 - LITERAL Float 3.14f32 42:2@20..27#2 - PUNCH , [alone] 42:2@27..28#2 - LITERAL Str hello bridge 42:2@29..43#2 - PUNCH , [alone] 42:2@43..44#2 - LITERAL Str suffixedsuffix 42:2@45..61#2 - PUNCH , [alone] 42:2@61..62#2 - LITERAL StrRaw(2) raw 42:2@63..73#2 - PUNCH , [alone] 42:2@73..74#2 - LITERAL Char a 42:2@75..78#2 - PUNCH , [alone] 42:2@78..79#2 - LITERAL Byte b 42:2@80..84#2 - PUNCH , [alone] 42:2@84..85#2 - LITERAL CStr null 42:2@86..93#2"#]], + SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037 + LITERAL Integer 1u16 42:2@0..4#4294967037 + PUNCH , [alone] 42:2@4..5#4294967037 + LITERAL Integer 2_u32 42:2@6..11#4294967037 + PUNCH , [alone] 42:2@11..12#4294967037 + PUNCH - [alone] 42:2@13..14#4294967037 + LITERAL Integer 4i64 42:2@14..18#4294967037 + PUNCH , [alone] 42:2@18..19#4294967037 + LITERAL Float 3.14f32 42:2@20..27#4294967037 + PUNCH , [alone] 42:2@27..28#4294967037 + LITERAL Str hello bridge 42:2@29..43#4294967037 + PUNCH , [alone] 42:2@43..44#4294967037 + LITERAL Str suffixedsuffix 42:2@45..61#4294967037 + PUNCH , [alone] 42:2@61..62#4294967037 + LITERAL StrRaw(2) raw 42:2@63..73#4294967037 + PUNCH , [alone] 42:2@73..74#4294967037 + LITERAL Char a 42:2@75..78#4294967037 + PUNCH , [alone] 42:2@78..79#4294967037 + LITERAL Byte b 42:2@80..84#4294967037 + PUNCH , [alone] 42:2@84..85#4294967037 + LITERAL CStr null 42:2@86..93#4294967037"#]], ); } @@ -239,12 +239,12 @@ fn test_attr_macro() { LITERAL Str #[attr_error(some arguments)] mod m {} 1 PUNCH ; [alone] 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 - IDENT compile_error 42:2@0..100#2 - PUNCH ! [alone] 42:2@0..100#2 - SUBTREE () 42:2@0..100#2 42:2@0..100#2 - LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#2 - PUNCH ; [alone] 42:2@0..100#2"#]], + SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037 + IDENT compile_error 42:2@0..100#4294967037 + PUNCH ! [alone] 42:2@0..100#4294967037 + SUBTREE () 42:2@0..100#4294967037 42:2@0..100#4294967037 + LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#4294967037 + PUNCH ; [alone] 42:2@0..100#4294967037"#]], ); } diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs index b2df8e4703ab3..3c14e6e627771 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs @@ -452,7 +452,7 @@ pub enum TargetKindData { } /// Identifies a crate by position in the crates array. /// -/// This will differ from `CrateId` when multiple `ProjectJson` +/// This will differ from `Crate` when multiple `ProjectJson` /// workspaces are loaded. #[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, PartialEq, Hash)] #[serde(transparent)] diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index 837406227323e..d4c93b0e9bc9a 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -1,4 +1,4 @@ -use base_db::{CrateGraph, ProcMacroPaths}; +use base_db::{CrateGraphBuilder, ProcMacroPaths}; use cargo_metadata::Metadata; use cfg::{CfgAtom, CfgDiff}; use expect_test::{expect_file, ExpectFile}; @@ -15,7 +15,7 @@ use crate::{ Sysroot, WorkspaceBuildScripts, }; -fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) { +fn load_cargo(file: &str) -> (CrateGraphBuilder, ProcMacroPaths) { let project_workspace = load_workspace_from_metadata(file); to_crate_graph(project_workspace, &mut Default::default()) } @@ -23,7 +23,7 @@ fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) { fn load_cargo_with_overrides( file: &str, cfg_overrides: CfgOverrides, -) -> (CrateGraph, ProcMacroPaths) { +) -> (CrateGraphBuilder, ProcMacroPaths) { let project_workspace = ProjectWorkspace { cfg_overrides, ..load_workspace_from_metadata(file) }; to_crate_graph(project_workspace, &mut Default::default()) @@ -51,7 +51,7 @@ fn load_workspace_from_metadata(file: &str) -> ProjectWorkspace { } } -fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) { +fn load_rust_project(file: &str) -> (CrateGraphBuilder, ProcMacroPaths) { let data = get_test_json_file(file); let project = rooted_project_json(data); let sysroot = get_fake_sysroot(); @@ -142,7 +142,7 @@ fn rooted_project_json(data: ProjectJsonData) -> ProjectJson { fn to_crate_graph( project_workspace: ProjectWorkspace, file_map: &mut FxHashMap, -) -> (CrateGraph, ProcMacroPaths) { +) -> (CrateGraphBuilder, ProcMacroPaths) { project_workspace.to_crate_graph( &mut { |path| { @@ -154,7 +154,7 @@ fn to_crate_graph( ) } -fn check_crate_graph(crate_graph: CrateGraph, expect: ExpectFile) { +fn check_crate_graph(crate_graph: CrateGraphBuilder, expect: ExpectFile) { let mut crate_graph = format!("{crate_graph:#?}"); replace_root(&mut crate_graph, false); diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 62c13c7d9ec8d..114c2551e1c13 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -6,8 +6,9 @@ use std::{collections::VecDeque, fmt, fs, iter, ops::Deref, sync, thread}; use anyhow::Context; use base_db::{ - CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, - LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult, + CrateBuilderId, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, + CrateWorkspaceData, DependencyBuilder, Env, LangCrateOrigin, ProcMacroPaths, + TargetLayoutLoadResult, }; use cfg::{CfgAtom, CfgDiff, CfgOptions}; use intern::{sym, Symbol}; @@ -848,10 +849,14 @@ impl ProjectWorkspace { &self, load: FileLoader<'_>, extra_env: &FxHashMap, - ) -> (CrateGraph, ProcMacroPaths) { + ) -> (CrateGraphBuilder, ProcMacroPaths) { let _p = tracing::info_span!("ProjectWorkspace::to_crate_graph").entered(); let Self { kind, sysroot, cfg_overrides, rustc_cfg, .. } = self; + let crate_ws_data = Arc::new(CrateWorkspaceData { + toolchain: self.toolchain.clone(), + data_layout: self.target_layout.clone(), + }); let (crate_graph, proc_macros) = match kind { ProjectWorkspaceKind::Json(project) => project_json_to_crate_graph( rustc_cfg.clone(), @@ -861,6 +866,7 @@ impl ProjectWorkspace { extra_env, cfg_overrides, self.set_test, + crate_ws_data, ), ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _ } => { cargo_to_crate_graph( @@ -872,6 +878,7 @@ impl ProjectWorkspace { cfg_overrides, build_scripts, self.set_test, + crate_ws_data, ) } ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => { @@ -885,6 +892,7 @@ impl ProjectWorkspace { cfg_overrides, build_scripts, self.set_test, + crate_ws_data, ) } else { detached_file_to_crate_graph( @@ -894,6 +902,7 @@ impl ProjectWorkspace { sysroot, cfg_overrides, self.set_test, + crate_ws_data, ) } } @@ -959,15 +968,22 @@ fn project_json_to_crate_graph( extra_env: &FxHashMap, override_cfg: &CfgOverrides, set_test: bool, -) -> (CrateGraph, ProcMacroPaths) { - let mut res = (CrateGraph::default(), ProcMacroPaths::default()); + crate_ws_data: Arc, +) -> (CrateGraphBuilder, ProcMacroPaths) { + let mut res = (CrateGraphBuilder::default(), ProcMacroPaths::default()); let (crate_graph, proc_macros) = &mut res; - let (public_deps, libproc_macro) = - sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load); + let (public_deps, libproc_macro) = sysroot_to_crate_graph( + crate_graph, + sysroot, + rustc_cfg.clone(), + load, + // FIXME: This looks incorrect but I don't think this matters. + crate_ws_data.clone(), + ); let mut cfg_cache: FxHashMap<&str, Vec> = FxHashMap::default(); - let idx_to_crate_id: FxHashMap = project + let idx_to_crate_id: FxHashMap = project .crates() .filter_map(|(idx, krate)| Some((idx, krate, load(&krate.root_module)?))) .map( @@ -1042,6 +1058,7 @@ fn project_json_to_crate_graph( }, *is_proc_macro, proc_macro_cwd.clone(), + crate_ws_data.clone(), ); debug!( ?crate_graph_crate_id, @@ -1092,12 +1109,19 @@ fn cargo_to_crate_graph( override_cfg: &CfgOverrides, build_scripts: &WorkspaceBuildScripts, set_test: bool, -) -> (CrateGraph, ProcMacroPaths) { + crate_ws_data: Arc, +) -> (CrateGraphBuilder, ProcMacroPaths) { let _p = tracing::info_span!("cargo_to_crate_graph").entered(); - let mut res = (CrateGraph::default(), ProcMacroPaths::default()); + let mut res = (CrateGraphBuilder::default(), ProcMacroPaths::default()); let (crate_graph, proc_macros) = &mut res; - let (public_deps, libproc_macro) = - sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load); + let (public_deps, libproc_macro) = sysroot_to_crate_graph( + crate_graph, + sysroot, + rustc_cfg.clone(), + load, + // FIXME: This looks incorrect but I don't think this causes problems. + crate_ws_data.clone(), + ); let cfg_options = CfgOptions::from_iter(rustc_cfg); @@ -1163,6 +1187,7 @@ fn cargo_to_crate_graph( name: Symbol::intern(&pkg_data.name), } }, + crate_ws_data.clone(), ); if let TargetKind::Lib { .. } = kind { lib_tgt = Some((crate_id, name.clone())); @@ -1267,6 +1292,8 @@ fn cargo_to_crate_graph( } else { rustc_build_scripts }, + // FIXME: This looks incorrect but I don't think this causes problems. + crate_ws_data, ); } } @@ -1280,11 +1307,18 @@ fn detached_file_to_crate_graph( sysroot: &Sysroot, override_cfg: &CfgOverrides, set_test: bool, -) -> (CrateGraph, ProcMacroPaths) { + crate_ws_data: Arc, +) -> (CrateGraphBuilder, ProcMacroPaths) { let _p = tracing::info_span!("detached_file_to_crate_graph").entered(); - let mut crate_graph = CrateGraph::default(); - let (public_deps, _libproc_macro) = - sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load); + let mut crate_graph = CrateGraphBuilder::default(); + let (public_deps, _libproc_macro) = sysroot_to_crate_graph( + &mut crate_graph, + sysroot, + rustc_cfg.clone(), + load, + // FIXME: This looks incorrect but I don't think this causes problems. + crate_ws_data.clone(), + ); let mut cfg_options = CfgOptions::from_iter(rustc_cfg); if set_test { @@ -1316,6 +1350,7 @@ fn detached_file_to_crate_graph( }, false, None, + crate_ws_data, ); public_deps.add_to_crate_graph(&mut crate_graph, detached_file_crate); @@ -1323,18 +1358,19 @@ fn detached_file_to_crate_graph( } fn handle_rustc_crates( - crate_graph: &mut CrateGraph, + crate_graph: &mut CrateGraphBuilder, proc_macros: &mut ProcMacroPaths, - pkg_to_lib_crate: &mut FxHashMap, + pkg_to_lib_crate: &mut FxHashMap, load: FileLoader<'_>, rustc_workspace: &CargoWorkspace, cargo: &CargoWorkspace, public_deps: &SysrootPublicDeps, - libproc_macro: Option, - pkg_crates: &FxHashMap>, + libproc_macro: Option, + pkg_crates: &FxHashMap>, cfg_options: &CfgOptions, override_cfg: &CfgOverrides, build_scripts: &WorkspaceBuildScripts, + crate_ws_data: Arc, ) { let mut rustc_pkg_crates = FxHashMap::default(); // The root package of the rustc-dev component is rustc_driver, so we match that @@ -1377,6 +1413,7 @@ fn handle_rustc_crates( &rustc_workspace[tgt].name, kind, CrateOrigin::Rustc { name: Symbol::intern(&rustc_workspace[pkg].name) }, + crate_ws_data.clone(), ); pkg_to_lib_crate.insert(pkg, crate_id); // Add dependencies on core / std / alloc for this crate @@ -1417,7 +1454,7 @@ fn handle_rustc_crates( // This avoids the situation where `from` depends on e.g. `arrayvec`, but // `rust_analyzer` thinks that it should use the one from the `rustc_source` // instead of the one from `crates.io` - if !crate_graph[*from].dependencies.iter().any(|d| d.name == name) { + if !crate_graph[*from].basic.dependencies.iter().any(|d| d.name == name) { add_dep(crate_graph, *from, name.clone(), to); } } @@ -1427,7 +1464,7 @@ fn handle_rustc_crates( } fn add_target_crate_root( - crate_graph: &mut CrateGraph, + crate_graph: &mut CrateGraphBuilder, proc_macros: &mut ProcMacroPaths, cargo: &CargoWorkspace, pkg: &PackageData, @@ -1437,7 +1474,8 @@ fn add_target_crate_root( cargo_name: &str, kind: TargetKind, origin: CrateOrigin, -) -> CrateId { + crate_ws_data: Arc, +) -> CrateBuilderId { let edition = pkg.edition; let potential_cfg_options = if pkg.features.is_empty() { None @@ -1474,7 +1512,7 @@ fn add_target_crate_root( Some(CrateDisplayName::from_canonical_name(cargo_name)), Some(pkg.version.to_string()), Arc::new(cfg_options), - potential_cfg_options.map(Arc::new), + potential_cfg_options, env, origin, matches!(kind, TargetKind::Lib { is_proc_macro: true }), @@ -1483,6 +1521,7 @@ fn add_target_crate_root( } else { pkg.manifest.parent().to_path_buf() }), + crate_ws_data, ); if let TargetKind::Lib { is_proc_macro: true } = kind { let proc_macro = match build_data { @@ -1503,12 +1542,12 @@ fn add_target_crate_root( #[derive(Default, Debug)] struct SysrootPublicDeps { - deps: Vec<(CrateName, CrateId, bool)>, + deps: Vec<(CrateName, CrateBuilderId, bool)>, } impl SysrootPublicDeps { /// Makes `from` depend on the public sysroot crates. - fn add_to_crate_graph(&self, crate_graph: &mut CrateGraph, from: CrateId) { + fn add_to_crate_graph(&self, crate_graph: &mut CrateGraphBuilder, from: CrateBuilderId) { for (name, krate, prelude) in &self.deps { add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude, true); } @@ -1516,10 +1555,10 @@ impl SysrootPublicDeps { } fn extend_crate_graph_with_sysroot( - crate_graph: &mut CrateGraph, - mut sysroot_crate_graph: CrateGraph, + crate_graph: &mut CrateGraphBuilder, + mut sysroot_crate_graph: CrateGraphBuilder, mut sysroot_proc_macros: ProcMacroPaths, -) -> (SysrootPublicDeps, Option) { +) -> (SysrootPublicDeps, Option) { let mut pub_deps = vec![]; let mut libproc_macro = None; let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]); @@ -1527,11 +1566,11 @@ fn extend_crate_graph_with_sysroot( // uninject `test` flag so `core` keeps working. Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone()); // patch the origin - if c.origin.is_local() { + if c.basic.origin.is_local() { let lang_crate = LangCrateOrigin::from( - c.display_name.as_ref().map_or("", |it| it.canonical_name().as_str()), + c.extra.display_name.as_ref().map_or("", |it| it.canonical_name().as_str()), ); - c.origin = CrateOrigin::Lang(lang_crate); + c.basic.origin = CrateOrigin::Lang(lang_crate); match lang_crate { LangCrateOrigin::Test | LangCrateOrigin::Alloc @@ -1579,11 +1618,12 @@ fn extend_crate_graph_with_sysroot( } fn sysroot_to_crate_graph( - crate_graph: &mut CrateGraph, + crate_graph: &mut CrateGraphBuilder, sysroot: &Sysroot, rustc_cfg: Vec, load: FileLoader<'_>, -) -> (SysrootPublicDeps, Option) { + crate_ws_data: Arc, +) -> (SysrootPublicDeps, Option) { let _p = tracing::info_span!("sysroot_to_crate_graph").entered(); match sysroot.workspace() { RustLibSrcWorkspace::Workspace(cargo) => { @@ -1605,6 +1645,7 @@ fn sysroot_to_crate_graph( }, &WorkspaceBuildScripts::default(), false, + crate_ws_data, ); extend_crate_graph_with_sysroot(crate_graph, cg, pm) @@ -1627,6 +1668,7 @@ fn sysroot_to_crate_graph( ..Default::default() }, false, + crate_ws_data, ); extend_crate_graph_with_sysroot(crate_graph, cg, pm) @@ -1639,29 +1681,31 @@ fn sysroot_to_crate_graph( cfg_options.insert_atom(sym::miri.clone()); cfg_options }); - let sysroot_crates: FxHashMap = - stitched - .crates() - .filter_map(|krate| { - let file_id = load(&stitched[krate].root)?; - - let display_name = - CrateDisplayName::from_canonical_name(&stitched[krate].name); - let crate_id = crate_graph.add_crate_root( - file_id, - Edition::CURRENT_FIXME, - Some(display_name), - None, - cfg_options.clone(), - None, - Env::default(), - CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)), - false, - None, - ); - Some((krate, crate_id)) - }) - .collect(); + let sysroot_crates: FxHashMap< + crate::sysroot::stitched::RustLibSrcCrate, + CrateBuilderId, + > = stitched + .crates() + .filter_map(|krate| { + let file_id = load(&stitched[krate].root)?; + + let display_name = CrateDisplayName::from_canonical_name(&stitched[krate].name); + let crate_id = crate_graph.add_crate_root( + file_id, + Edition::CURRENT_FIXME, + Some(display_name), + None, + cfg_options.clone(), + None, + Env::default(), + CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)), + false, + None, + crate_ws_data.clone(), + ); + Some((krate, crate_id)) + }) + .collect(); for from in stitched.crates() { for &to in stitched[from].deps.iter() { @@ -1691,22 +1735,32 @@ fn sysroot_to_crate_graph( } } -fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) { - add_dep_inner(graph, from, Dependency::new(name, to)) +fn add_dep( + graph: &mut CrateGraphBuilder, + from: CrateBuilderId, + name: CrateName, + to: CrateBuilderId, +) { + add_dep_inner(graph, from, DependencyBuilder::new(name, to)) } fn add_dep_with_prelude( - graph: &mut CrateGraph, - from: CrateId, + graph: &mut CrateGraphBuilder, + from: CrateBuilderId, name: CrateName, - to: CrateId, + to: CrateBuilderId, prelude: bool, sysroot: bool, ) { - add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude, sysroot)) + add_dep_inner(graph, from, DependencyBuilder::with_prelude(name, to, prelude, sysroot)) } -fn add_proc_macro_dep(crate_graph: &mut CrateGraph, from: CrateId, to: CrateId, prelude: bool) { +fn add_proc_macro_dep( + crate_graph: &mut CrateGraphBuilder, + from: CrateBuilderId, + to: CrateBuilderId, + prelude: bool, +) { add_dep_with_prelude( crate_graph, from, @@ -1717,7 +1771,7 @@ fn add_proc_macro_dep(crate_graph: &mut CrateGraph, from: CrateId, to: CrateId, ); } -fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) { +fn add_dep_inner(graph: &mut CrateGraphBuilder, from: CrateBuilderId, dep: DependencyBuilder) { if let Err(err) = graph.add_dep(from, dep) { tracing::warn!("{}", err) } diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt index fae0b6fcca4dd..ae842bf704d30 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt @@ -1,20 +1,47 @@ { - 0: CrateData { - root_file_id: FileId( - 1, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "hello_world", + 0: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 1, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - canonical_name: "hello-world", }, - ), + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", + ), + ), + }, + extra: ExtraCrateData { + version: Some( + "0.1.0", + ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "hello_world", + ), + canonical_name: "hello-world", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", @@ -22,7 +49,6 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -44,45 +70,64 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", - ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", ), + toolchain: None, }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", - ), - ), }, - 1: CrateData { - root_file_id: FileId( - 2, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "hello_world", + 1: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 2, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "hello_world", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - canonical_name: "hello-world", }, - ), + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", + ), + ), + }, + extra: ExtraCrateData { + version: Some( + "0.1.0", + ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "hello_world", + ), + canonical_name: "hello-world", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", @@ -90,7 +135,6 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -112,53 +156,64 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(0), - name: CrateName( - "hello_world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", + ), + toolchain: None, + }, + }, + 2: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 3, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "hello_world", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - prelude: true, - sysroot: false, }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", ), }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", + extra: ExtraCrateData { + version: Some( + "0.1.0", ), - ), - }, - 2: CrateData { - root_file_id: FileId( - 3, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "an_example", - ), - canonical_name: "an-example", - }, - ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "an_example", + ), + canonical_name: "an-example", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", @@ -166,7 +221,6 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -188,53 +242,64 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(0), - name: CrateName( - "hello_world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", + ), + toolchain: None, + }, + }, + 3: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 4, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "hello_world", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - prelude: true, - sysroot: false, }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", ), }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", + extra: ExtraCrateData { + version: Some( + "0.1.0", ), - ), - }, - 3: CrateData { - root_file_id: FileId( - 4, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "it", - ), - canonical_name: "it", - }, - ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "it", + ), + canonical_name: "it", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", @@ -242,7 +307,6 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -264,53 +328,60 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(0), - name: CrateName( - "hello_world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", + ), + toolchain: None, + }, + }, + 4: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 5, + ), + edition: Edition2015, + dependencies: [], + origin: Library { + repo: Some( + "https://github.com/rust-lang/libc", ), - prelude: true, - sysroot: false, + name: "libc", }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98", ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", ), }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", + extra: ExtraCrateData { + version: Some( + "0.2.98", ), - ), - }, - 4: CrateData { - root_file_id: FileId( - 5, - ), - edition: Edition2015, - version: Some( - "0.2.98", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "libc", + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "libc", + ), + canonical_name: "libc", + }, + ), + potential_cfg_options: Some( + CfgOptions( + [ + "feature=align", + "feature=const-extern-fn", + "feature=default", + "feature=extra_traits", + "feature=rustc-dep-of-std", + "feature=std", + "feature=use_std", + "true", + ], ), - canonical_name: "libc", - }, - ), + ), + }, cfg_options: CfgOptions( [ "feature=default", @@ -318,20 +389,6 @@ "true", ], ), - potential_cfg_options: Some( - CfgOptions( - [ - "feature=align", - "feature=const-extern-fn", - "feature=default", - "feature=extra_traits", - "feature=rustc-dep-of-std", - "feature=std", - "feature=use_std", - "true", - ], - ), - ), env: Env { entries: { "CARGO": "$CARGO$", @@ -353,18 +410,11 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [], - origin: Library { - repo: Some( - "https://github.com/rust-lang/libc", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", ), - name: "libc", + toolchain: None, }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98", - ), - ), }, } \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt index fae0b6fcca4dd..ae842bf704d30 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt @@ -1,20 +1,47 @@ { - 0: CrateData { - root_file_id: FileId( - 1, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "hello_world", + 0: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 1, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - canonical_name: "hello-world", }, - ), + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", + ), + ), + }, + extra: ExtraCrateData { + version: Some( + "0.1.0", + ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "hello_world", + ), + canonical_name: "hello-world", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", @@ -22,7 +49,6 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -44,45 +70,64 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", - ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", ), + toolchain: None, }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", - ), - ), }, - 1: CrateData { - root_file_id: FileId( - 2, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "hello_world", + 1: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 2, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "hello_world", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - canonical_name: "hello-world", }, - ), + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", + ), + ), + }, + extra: ExtraCrateData { + version: Some( + "0.1.0", + ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "hello_world", + ), + canonical_name: "hello-world", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", @@ -90,7 +135,6 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -112,53 +156,64 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(0), - name: CrateName( - "hello_world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", + ), + toolchain: None, + }, + }, + 2: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 3, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "hello_world", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - prelude: true, - sysroot: false, }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", ), }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", + extra: ExtraCrateData { + version: Some( + "0.1.0", ), - ), - }, - 2: CrateData { - root_file_id: FileId( - 3, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "an_example", - ), - canonical_name: "an-example", - }, - ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "an_example", + ), + canonical_name: "an-example", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", @@ -166,7 +221,6 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -188,53 +242,64 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(0), - name: CrateName( - "hello_world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", + ), + toolchain: None, + }, + }, + 3: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 4, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "hello_world", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - prelude: true, - sysroot: false, }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", ), }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", + extra: ExtraCrateData { + version: Some( + "0.1.0", ), - ), - }, - 3: CrateData { - root_file_id: FileId( - 4, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "it", - ), - canonical_name: "it", - }, - ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "it", + ), + canonical_name: "it", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", @@ -242,7 +307,6 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -264,53 +328,60 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(0), - name: CrateName( - "hello_world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", + ), + toolchain: None, + }, + }, + 4: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 5, + ), + edition: Edition2015, + dependencies: [], + origin: Library { + repo: Some( + "https://github.com/rust-lang/libc", ), - prelude: true, - sysroot: false, + name: "libc", }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98", ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", ), }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", + extra: ExtraCrateData { + version: Some( + "0.2.98", ), - ), - }, - 4: CrateData { - root_file_id: FileId( - 5, - ), - edition: Edition2015, - version: Some( - "0.2.98", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "libc", + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "libc", + ), + canonical_name: "libc", + }, + ), + potential_cfg_options: Some( + CfgOptions( + [ + "feature=align", + "feature=const-extern-fn", + "feature=default", + "feature=extra_traits", + "feature=rustc-dep-of-std", + "feature=std", + "feature=use_std", + "true", + ], ), - canonical_name: "libc", - }, - ), + ), + }, cfg_options: CfgOptions( [ "feature=default", @@ -318,20 +389,6 @@ "true", ], ), - potential_cfg_options: Some( - CfgOptions( - [ - "feature=align", - "feature=const-extern-fn", - "feature=default", - "feature=extra_traits", - "feature=rustc-dep-of-std", - "feature=std", - "feature=use_std", - "true", - ], - ), - ), env: Env { entries: { "CARGO": "$CARGO$", @@ -353,18 +410,11 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [], - origin: Library { - repo: Some( - "https://github.com/rust-lang/libc", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", ), - name: "libc", + toolchain: None, }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98", - ), - ), }, } \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt index 566174882ddac..272cd69cb140b 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt @@ -1,27 +1,53 @@ { - 0: CrateData { - root_file_id: FileId( - 1, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "hello_world", + 0: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 1, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - canonical_name: "hello-world", }, - ), + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", + ), + ), + }, + extra: ExtraCrateData { + version: Some( + "0.1.0", + ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "hello_world", + ), + canonical_name: "hello-world", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -43,52 +69,70 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", - ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", ), + toolchain: None, }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", - ), - ), }, - 1: CrateData { - root_file_id: FileId( - 2, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "hello_world", + 1: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 2, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "hello_world", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - canonical_name: "hello-world", }, - ), + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", + ), + ), + }, + extra: ExtraCrateData { + version: Some( + "0.1.0", + ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "hello_world", + ), + canonical_name: "hello-world", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -110,60 +154,70 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(0), - name: CrateName( - "hello_world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", + ), + toolchain: None, + }, + }, + 2: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 3, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "hello_world", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - prelude: true, - sysroot: false, }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", ), }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", + extra: ExtraCrateData { + version: Some( + "0.1.0", ), - ), - }, - 2: CrateData { - root_file_id: FileId( - 3, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "an_example", - ), - canonical_name: "an-example", - }, - ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "an_example", + ), + canonical_name: "an-example", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -185,60 +239,70 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(0), - name: CrateName( - "hello_world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", + ), + toolchain: None, + }, + }, + 3: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 4, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "hello_world", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "libc", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Local { + repo: None, + name: Some( + "hello-world", ), - prelude: true, - sysroot: false, }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$hello-world", ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", ), }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", + extra: ExtraCrateData { + version: Some( + "0.1.0", ), - ), - }, - 3: CrateData { - root_file_id: FileId( - 4, - ), - edition: Edition2018, - version: Some( - "0.1.0", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "it", - ), - canonical_name: "it", - }, - ), + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "it", + ), + canonical_name: "it", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", "true", ], ), - potential_cfg_options: None, env: Env { entries: { "CARGO": "$CARGO$", @@ -260,53 +324,60 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [ - Dependency { - crate_id: Idx::(0), - name: CrateName( - "hello_world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", + ), + toolchain: None, + }, + }, + 4: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 5, + ), + edition: Edition2015, + dependencies: [], + origin: Library { + repo: Some( + "https://github.com/rust-lang/libc", ), - prelude: true, - sysroot: false, + name: "libc", }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "libc", + is_proc_macro: false, + proc_macro_cwd: Some( + AbsPathBuf( + "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98", ), - prelude: true, - sysroot: false, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello-world", ), }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$hello-world", + extra: ExtraCrateData { + version: Some( + "0.2.98", ), - ), - }, - 4: CrateData { - root_file_id: FileId( - 5, - ), - edition: Edition2015, - version: Some( - "0.2.98", - ), - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "libc", + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "libc", + ), + canonical_name: "libc", + }, + ), + potential_cfg_options: Some( + CfgOptions( + [ + "feature=align", + "feature=const-extern-fn", + "feature=default", + "feature=extra_traits", + "feature=rustc-dep-of-std", + "feature=std", + "feature=use_std", + "true", + ], ), - canonical_name: "libc", - }, - ), + ), + }, cfg_options: CfgOptions( [ "feature=default", @@ -314,20 +385,6 @@ "true", ], ), - potential_cfg_options: Some( - CfgOptions( - [ - "feature=align", - "feature=const-extern-fn", - "feature=default", - "feature=extra_traits", - "feature=rustc-dep-of-std", - "feature=std", - "feature=use_std", - "true", - ], - ), - ), env: Env { entries: { "CARGO": "$CARGO$", @@ -349,18 +406,11 @@ "CARGO_PKG_VERSION_PRE": "", }, }, - dependencies: [], - origin: Library { - repo: Some( - "https://github.com/rust-lang/libc", + ws_data: CrateWorkspaceData { + data_layout: Err( + "target_data_layout not loaded", ), - name: "libc", + toolchain: None, }, - is_proc_macro: false, - proc_macro_cwd: Some( - AbsPathBuf( - "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98", - ), - ), }, } \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt index 9b4be19c41c83..2b8e521f3442d 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt @@ -1,18 +1,38 @@ { - 0: CrateData { - root_file_id: FileId( - 1, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "alloc", - ), - canonical_name: "alloc", - }, - ), + 0: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 1, + ), + edition: Edition2021, + dependencies: [ + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + Alloc, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "alloc", + ), + canonical_name: "alloc", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -20,40 +40,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [ - Dependency { - crate_id: Idx::(1), - name: CrateName( - "core", - ), - prelude: true, - sysroot: false, - }, - ], - origin: Lang( - Alloc, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 1: CrateData { - root_file_id: FileId( - 2, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "core", - ), - canonical_name: "core", - }, - ), + 1: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 2, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Core, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "core", + ), + canonical_name: "core", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -61,31 +82,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Core, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 2: CrateData { - root_file_id: FileId( - 3, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "panic_abort", - ), - canonical_name: "panic_abort", - }, - ), + 2: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 3, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "panic_abort", + ), + canonical_name: "panic_abort", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -93,31 +124,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Other, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 3: CrateData { - root_file_id: FileId( - 4, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "panic_unwind", - ), - canonical_name: "panic_unwind", - }, - ), + 3: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 4, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "panic_unwind", + ), + canonical_name: "panic_unwind", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -125,31 +166,58 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Other, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 4: CrateData { - root_file_id: FileId( - 5, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "proc_macro", - ), - canonical_name: "proc_macro", - }, - ), + 4: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 5, + ), + edition: Edition2021, + dependencies: [ + Dependency { + crate_id: Idx::(6), + name: CrateName( + "std", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + ProcMacro, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "proc_macro", + ), + canonical_name: "proc_macro", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -157,48 +225,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [ - Dependency { - crate_id: Idx::(6), - name: CrateName( - "std", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(1), - name: CrateName( - "core", - ), - prelude: true, - sysroot: false, - }, - ], - origin: Lang( - ProcMacro, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 5: CrateData { - root_file_id: FileId( - 6, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "profiler_builtins", - ), - canonical_name: "profiler_builtins", - }, - ), + 5: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 6, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "profiler_builtins", + ), + canonical_name: "profiler_builtins", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -206,31 +267,106 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Other, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 6: CrateData { - root_file_id: FileId( - 7, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "std", - ), - canonical_name: "std", - }, - ), + 6: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 7, + ), + edition: Edition2021, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "alloc", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(3), + name: CrateName( + "panic_unwind", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(2), + name: CrateName( + "panic_abort", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(5), + name: CrateName( + "profiler_builtins", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(9), + name: CrateName( + "unwind", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(7), + name: CrateName( + "std_detect", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(8), + name: CrateName( + "test", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + Std, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "std", + ), + canonical_name: "std", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -238,96 +374,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [ - Dependency { - crate_id: Idx::(0), - name: CrateName( - "alloc", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(3), - name: CrateName( - "panic_unwind", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(2), - name: CrateName( - "panic_abort", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(1), - name: CrateName( - "core", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(5), - name: CrateName( - "profiler_builtins", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(9), - name: CrateName( - "unwind", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(7), - name: CrateName( - "std_detect", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(8), - name: CrateName( - "test", - ), - prelude: true, - sysroot: false, - }, - ], - origin: Lang( - Std, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 7: CrateData { - root_file_id: FileId( - 8, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "std_detect", - ), - canonical_name: "std_detect", - }, - ), + 7: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 8, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "std_detect", + ), + canonical_name: "std_detect", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -335,31 +416,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Other, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 8: CrateData { - root_file_id: FileId( - 9, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "test", - ), - canonical_name: "test", - }, - ), + 8: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 9, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Test, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "test", + ), + canonical_name: "test", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -367,31 +458,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Test, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 9: CrateData { - root_file_id: FileId( - 10, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "unwind", - ), - canonical_name: "unwind", - }, - ), + 9: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 10, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "unwind", + ), + canonical_name: "unwind", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -399,31 +500,85 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Other, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 10: CrateData { - root_file_id: FileId( - 11, - ), - edition: Edition2018, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( + 10: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 11, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(0), + name: CrateName( + "alloc", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(6), + name: CrateName( + "std", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(8), + name: CrateName( + "test", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "proc_macro", + ), + prelude: false, + sysroot: true, + }, + ], + origin: Local { + repo: None, + name: Some( "hello_world", ), - canonical_name: "hello_world", }, - ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "hello_world", + ), + canonical_name: "hello_world", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "group1_cfg=some_config", @@ -434,75 +589,85 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [ - Dependency { - crate_id: Idx::(1), - name: CrateName( - "core", - ), - prelude: true, - sysroot: true, - }, - Dependency { - crate_id: Idx::(0), - name: CrateName( - "alloc", - ), - prelude: false, - sysroot: true, - }, - Dependency { - crate_id: Idx::(6), - name: CrateName( - "std", - ), - prelude: true, - sysroot: true, - }, - Dependency { - crate_id: Idx::(8), - name: CrateName( - "test", - ), - prelude: false, - sysroot: true, - }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "proc_macro", - ), - prelude: false, - sysroot: true, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello_world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", ), + toolchain: None, }, - is_proc_macro: false, - proc_macro_cwd: None, }, - 11: CrateData { - root_file_id: FileId( - 11, - ), - edition: Edition2018, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( + 11: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 11, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(0), + name: CrateName( + "alloc", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(6), + name: CrateName( + "std", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(8), + name: CrateName( + "test", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "proc_macro", + ), + prelude: false, + sysroot: true, + }, + ], + origin: Local { + repo: None, + name: Some( "other_crate", ), - canonical_name: "other_crate", }, - ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "other_crate", + ), + canonical_name: "other_crate", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "group2_cfg=fourth_config", @@ -513,59 +678,14 @@ "unrelated_cfg", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [ - Dependency { - crate_id: Idx::(1), - name: CrateName( - "core", - ), - prelude: true, - sysroot: true, - }, - Dependency { - crate_id: Idx::(0), - name: CrateName( - "alloc", - ), - prelude: false, - sysroot: true, - }, - Dependency { - crate_id: Idx::(6), - name: CrateName( - "std", - ), - prelude: true, - sysroot: true, - }, - Dependency { - crate_id: Idx::(8), - name: CrateName( - "test", - ), - prelude: false, - sysroot: true, - }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "proc_macro", - ), - prelude: false, - sysroot: true, - }, - ], - origin: Local { - repo: None, - name: Some( - "other_crate", + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", ), + toolchain: None, }, - is_proc_macro: false, - proc_macro_cwd: None, }, } \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt index 4c8e66e8e968b..053e9473cf20b 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt @@ -1,18 +1,38 @@ { - 0: CrateData { - root_file_id: FileId( - 1, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "alloc", - ), - canonical_name: "alloc", - }, - ), + 0: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 1, + ), + edition: Edition2021, + dependencies: [ + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + Alloc, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "alloc", + ), + canonical_name: "alloc", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -20,40 +40,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [ - Dependency { - crate_id: Idx::(1), - name: CrateName( - "core", - ), - prelude: true, - sysroot: false, - }, - ], - origin: Lang( - Alloc, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 1: CrateData { - root_file_id: FileId( - 2, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "core", - ), - canonical_name: "core", - }, - ), + 1: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 2, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Core, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "core", + ), + canonical_name: "core", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -61,31 +82,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Core, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 2: CrateData { - root_file_id: FileId( - 3, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "panic_abort", - ), - canonical_name: "panic_abort", - }, - ), + 2: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 3, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "panic_abort", + ), + canonical_name: "panic_abort", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -93,31 +124,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Other, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 3: CrateData { - root_file_id: FileId( - 4, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "panic_unwind", - ), - canonical_name: "panic_unwind", - }, - ), + 3: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 4, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "panic_unwind", + ), + canonical_name: "panic_unwind", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -125,31 +166,58 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Other, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 4: CrateData { - root_file_id: FileId( - 5, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "proc_macro", - ), - canonical_name: "proc_macro", - }, - ), + 4: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 5, + ), + edition: Edition2021, + dependencies: [ + Dependency { + crate_id: Idx::(6), + name: CrateName( + "std", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + ProcMacro, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "proc_macro", + ), + canonical_name: "proc_macro", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -157,48 +225,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [ - Dependency { - crate_id: Idx::(6), - name: CrateName( - "std", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(1), - name: CrateName( - "core", - ), - prelude: true, - sysroot: false, - }, - ], - origin: Lang( - ProcMacro, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 5: CrateData { - root_file_id: FileId( - 6, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "profiler_builtins", - ), - canonical_name: "profiler_builtins", - }, - ), + 5: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 6, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "profiler_builtins", + ), + canonical_name: "profiler_builtins", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -206,31 +267,106 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Other, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 6: CrateData { - root_file_id: FileId( - 7, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "std", - ), - canonical_name: "std", - }, - ), + 6: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 7, + ), + edition: Edition2021, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "alloc", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(3), + name: CrateName( + "panic_unwind", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(2), + name: CrateName( + "panic_abort", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(5), + name: CrateName( + "profiler_builtins", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(9), + name: CrateName( + "unwind", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(7), + name: CrateName( + "std_detect", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(8), + name: CrateName( + "test", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + Std, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "std", + ), + canonical_name: "std", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -238,96 +374,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [ - Dependency { - crate_id: Idx::(0), - name: CrateName( - "alloc", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(3), - name: CrateName( - "panic_unwind", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(2), - name: CrateName( - "panic_abort", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(1), - name: CrateName( - "core", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(5), - name: CrateName( - "profiler_builtins", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(9), - name: CrateName( - "unwind", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(7), - name: CrateName( - "std_detect", - ), - prelude: true, - sysroot: false, - }, - Dependency { - crate_id: Idx::(8), - name: CrateName( - "test", - ), - prelude: true, - sysroot: false, - }, - ], - origin: Lang( - Std, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 7: CrateData { - root_file_id: FileId( - 8, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "std_detect", - ), - canonical_name: "std_detect", - }, - ), + 7: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 8, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "std_detect", + ), + canonical_name: "std_detect", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -335,31 +416,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Other, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 8: CrateData { - root_file_id: FileId( - 9, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "test", - ), - canonical_name: "test", - }, - ), + 8: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 9, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Test, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "test", + ), + canonical_name: "test", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -367,31 +458,41 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Test, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 9: CrateData { - root_file_id: FileId( - 10, - ), - edition: Edition2021, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( - "unwind", - ), - canonical_name: "unwind", - }, - ), + 9: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 10, + ), + edition: Edition2021, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "unwind", + ), + canonical_name: "unwind", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "debug_assertions", @@ -399,31 +500,85 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [], - origin: Lang( - Other, - ), - is_proc_macro: false, - proc_macro_cwd: None, + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", + ), + toolchain: None, + }, }, - 10: CrateData { - root_file_id: FileId( - 11, - ), - edition: Edition2018, - version: None, - display_name: Some( - CrateDisplayName { - crate_name: CrateName( + 10: CrateBuilder { + basic: CrateData { + root_file_id: FileId( + 11, + ), + edition: Edition2018, + dependencies: [ + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(0), + name: CrateName( + "alloc", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(6), + name: CrateName( + "std", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(8), + name: CrateName( + "test", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "proc_macro", + ), + prelude: false, + sysroot: true, + }, + ], + origin: Local { + repo: None, + name: Some( "hello_world", ), - canonical_name: "hello_world", }, - ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + extra: ExtraCrateData { + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "hello_world", + ), + canonical_name: "hello_world", + }, + ), + potential_cfg_options: None, + }, cfg_options: CfgOptions( [ "rust_analyzer", @@ -431,59 +586,14 @@ "true", ], ), - potential_cfg_options: None, env: Env { entries: {}, }, - dependencies: [ - Dependency { - crate_id: Idx::(1), - name: CrateName( - "core", - ), - prelude: true, - sysroot: true, - }, - Dependency { - crate_id: Idx::(0), - name: CrateName( - "alloc", - ), - prelude: false, - sysroot: true, - }, - Dependency { - crate_id: Idx::(6), - name: CrateName( - "std", - ), - prelude: true, - sysroot: true, - }, - Dependency { - crate_id: Idx::(8), - name: CrateName( - "test", - ), - prelude: false, - sysroot: true, - }, - Dependency { - crate_id: Idx::(4), - name: CrateName( - "proc_macro", - ), - prelude: false, - sysroot: true, - }, - ], - origin: Local { - repo: None, - name: Some( - "hello_world", + ws_data: CrateWorkspaceData { + data_layout: Err( + "test has no data layout", ), + toolchain: None, }, - is_proc_macro: false, - proc_macro_cwd: None, }, } \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index f114a4454e002..a6aa0376b0c81 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -8,7 +8,7 @@ use std::{ops::Not as _, time::Instant}; use crossbeam_channel::{unbounded, Receiver, Sender}; use hir::ChangeWithProcMacros; use ide::{Analysis, AnalysisHost, Cancellable, FileId, SourceRootId}; -use ide_db::base_db::{CrateId, ProcMacroPaths, SourceDatabase}; +use ide_db::base_db::{Crate, ProcMacroPaths, SourceDatabase}; use itertools::Itertools; use load_cargo::SourceRootConfig; use lsp_types::{SemanticTokens, Url}; @@ -158,7 +158,7 @@ pub(crate) struct GlobalState { // op queues pub(crate) fetch_workspaces_queue: OpQueue, pub(crate) fetch_build_data_queue: OpQueue<(), FetchBuildDataResponse>, - pub(crate) fetch_proc_macros_queue: OpQueue, bool>, + pub(crate) fetch_proc_macros_queue: OpQueue<(ChangeWithProcMacros, Vec), bool>, pub(crate) prime_caches_queue: OpQueue, pub(crate) discover_workspace_queue: OpQueue, @@ -714,7 +714,7 @@ impl GlobalStateSnapshot { self.vfs_read().file_path(file_id).clone() } - pub(crate) fn target_spec_for_crate(&self, crate_id: CrateId) -> Option { + pub(crate) fn target_spec_for_crate(&self, crate_id: Crate) -> Option { let file_id = self.analysis.crate_root(crate_id).ok()?; let path = self.vfs_read().file_path(file_id).clone(); let path = path.as_path()?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index b47a126424aa0..7244fbc4aaac9 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -10,7 +10,7 @@ use std::{ use always_assert::always; use crossbeam_channel::{select, Receiver}; -use ide_db::base_db::{RootQueryDb, SourceDatabase, VfsPath}; +use ide_db::base_db::{SourceDatabase, VfsPath}; use lsp_server::{Connection, Notification, Request}; use lsp_types::{notification::Notification as _, TextDocumentIdentifier}; use stdx::thread::ThreadIntent; @@ -504,8 +504,10 @@ impl GlobalState { if !self.fetch_workspaces_queue.op_in_progress() { if let Some((cause, ())) = self.fetch_build_data_queue.should_start_op() { self.fetch_build_data(cause); - } else if let Some((cause, paths)) = self.fetch_proc_macros_queue.should_start_op() { - self.fetch_proc_macros(cause, paths); + } else if let Some((cause, (change, paths))) = + self.fetch_proc_macros_queue.should_start_op() + { + self.fetch_proc_macros(cause, change, paths); } } @@ -804,9 +806,10 @@ impl GlobalState { let (state, msg) = match progress { ProcMacroProgress::Begin => (Some(Progress::Begin), None), ProcMacroProgress::Report(msg) => (Some(Progress::Report), Some(msg)), - ProcMacroProgress::End(proc_macro_load_result) => { + ProcMacroProgress::End(change) => { self.fetch_proc_macros_queue.op_completed(true); - self.set_proc_macros(proc_macro_load_result); + self.analysis_host.apply_change(change); + self.finish_loading_crate_graph(); (Some(Progress::End), None) } }; @@ -909,16 +912,15 @@ impl GlobalState { }); } QueuedTask::CheckProcMacroSources(modified_rust_files) => { - let crate_graph = self.analysis_host.raw_database().crate_graph(); let analysis = AssertUnwindSafe(self.snapshot().analysis); self.task_pool.handle.spawn_with_sender(stdx::thread::ThreadIntent::Worker, { move |sender| { if modified_rust_files.into_iter().any(|file_id| { // FIXME: Check whether these files could be build script related match analysis.crates_for(file_id) { - Ok(crates) => { - crates.iter().any(|&krate| crate_graph[krate].is_proc_macro) - } + Ok(crates) => crates.iter().any(|&krate| { + analysis.is_proc_macro_crate(krate).is_ok_and(|it| it) + }), _ => false, } }) { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 1a60fa06c9eb8..d6a99fbe55a55 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -15,10 +15,9 @@ // FIXME: This is a mess that needs some untangling work use std::{iter, mem}; -use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros, ProcMacrosBuilder}; -use ide::CrateId; +use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacrosBuilder}; use ide_db::{ - base_db::{salsa::Durability, CrateGraph, CrateWorkspaceData, ProcMacroPaths}, + base_db::{salsa::Durability, CrateGraphBuilder, ProcMacroPaths, RootQueryDb}, FxHashMap, }; use itertools::Itertools; @@ -60,7 +59,7 @@ pub(crate) enum BuildDataProgress { pub(crate) enum ProcMacroProgress { Begin, Report(String), - End(ProcMacros), + End(ChangeWithProcMacros), } impl GlobalState { @@ -387,7 +386,12 @@ impl GlobalState { }); } - pub(crate) fn fetch_proc_macros(&mut self, cause: Cause, paths: Vec) { + pub(crate) fn fetch_proc_macros( + &mut self, + cause: Cause, + mut change: ChangeWithProcMacros, + paths: Vec, + ) { info!(%cause, "will load proc macros"); let ignored_proc_macros = self.config.ignored_proc_macros(None).clone(); let proc_macro_clients = self.proc_macro_clients.clone(); @@ -440,16 +444,11 @@ impl GlobalState { .for_each(|(krate, res)| builder.insert(krate, res)); } - sender.send(Task::LoadProcMacros(ProcMacroProgress::End(builder.build()))).unwrap(); + change.set_proc_macros(builder); + sender.send(Task::LoadProcMacros(ProcMacroProgress::End(change))).unwrap(); }); } - pub(crate) fn set_proc_macros(&mut self, proc_macros: ProcMacros) { - let mut change = ChangeWithProcMacros::new(); - change.set_proc_macros(proc_macros); - self.analysis_host.apply_change(change); - } - pub(crate) fn switch_workspaces(&mut self, cause: Cause) { let _p = tracing::info_span!("GlobalState::switch_workspaces").entered(); tracing::info!(%cause, "will switch workspaces"); @@ -528,6 +527,14 @@ impl GlobalState { if self.config.run_build_scripts(None) { self.build_deps_changed = false; self.fetch_build_data_queue.request_op("workspace updated".to_owned(), ()); + + let initial_build = self.analysis_host.raw_database().all_crates().is_empty(); + if !initial_build { + // `switch_workspaces()` will be called again when build scripts already run, which should + // take a short time. If we update the workspace now we will invalidate proc macros and cfgs, + // and then when build scripts complete we will invalidate them again. + return; + } } } @@ -711,7 +718,7 @@ impl GlobalState { }) .collect(); - let (crate_graph, proc_macro_paths, ws_data) = { + let (crate_graph, proc_macro_paths) = { // Create crate graph from all the workspaces let vfs = &self.vfs.read().0; let load = |path: &AbsPath| { @@ -725,24 +732,35 @@ impl GlobalState { ws_to_crate_graph(&self.workspaces, self.config.extra_env(None), load) }; let mut change = ChangeWithProcMacros::new(); - if self.config.expand_proc_macros() { - change.set_proc_macros( - crate_graph - .iter() - .map(|id| (id, Err(("proc-macro has not been built yet".to_owned(), true)))) - .collect(), - ); - self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths); - } else { - change.set_proc_macros( - crate_graph - .iter() - .map(|id| (id, Err(("proc-macro expansion is disabled".to_owned(), false)))) - .collect(), - ); + let initial_build = self.analysis_host.raw_database().all_crates().is_empty(); + if initial_build || !self.config.expand_proc_macros() { + if self.config.expand_proc_macros() { + change.set_proc_macros( + crate_graph + .iter() + .map(|id| (id, Err(("proc-macro has not been built yet".to_owned(), true)))) + .collect(), + ); + } else { + change.set_proc_macros( + crate_graph + .iter() + .map(|id| (id, Err(("proc-macro expansion is disabled".to_owned(), false)))) + .collect(), + ); + } + + change.set_crate_graph(crate_graph); + self.analysis_host.apply_change(change); + + self.finish_loading_crate_graph(); + return; } - change.set_crate_graph(crate_graph, ws_data); - self.analysis_host.apply_change(change); + change.set_crate_graph(crate_graph); + self.fetch_proc_macros_queue.request_op(cause, (change, proc_macro_paths)); + } + + pub(crate) fn finish_loading_crate_graph(&mut self) { self.report_progress( "Building CrateGraph", crate::lsp::utils::Progress::End, @@ -883,26 +901,19 @@ pub fn ws_to_crate_graph( workspaces: &[ProjectWorkspace], extra_env: &FxHashMap, mut load: impl FnMut(&AbsPath) -> Option, -) -> (CrateGraph, Vec, FxHashMap>) { - let mut crate_graph = CrateGraph::default(); +) -> (CrateGraphBuilder, Vec) { + let mut crate_graph = CrateGraphBuilder::default(); let mut proc_macro_paths = Vec::default(); - let mut ws_data = FxHashMap::default(); for ws in workspaces { let (other, mut crate_proc_macros) = ws.to_crate_graph(&mut load, extra_env); - let ProjectWorkspace { toolchain, target_layout, .. } = ws; - - let mapping = crate_graph.extend(other, &mut crate_proc_macros); - // Populate the side tables for the newly merged crates - ws_data.extend(mapping.values().copied().zip(iter::repeat(Arc::new(CrateWorkspaceData { - toolchain: toolchain.clone(), - data_layout: target_layout.clone(), - })))); + + crate_graph.extend(other, &mut crate_proc_macros); proc_macro_paths.push(crate_proc_macros); } crate_graph.shrink_to_fit(); proc_macro_paths.shrink_to_fit(); - (crate_graph, proc_macro_paths, ws_data) + (crate_graph, proc_macro_paths) } pub(crate) fn should_refresh_for_change( diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs index b28567fe09b58..abb70ebe36f48 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs @@ -4,7 +4,7 @@ use std::mem; use cfg::{CfgAtom, CfgExpr}; use hir::sym; -use ide::{Cancellable, CrateId, FileId, RunnableKind, TestId}; +use ide::{Cancellable, Crate, FileId, RunnableKind, TestId}; use project_model::project_json::Runnable; use project_model::{CargoFeatures, ManifestPath, TargetKind}; use rustc_hash::FxHashSet; @@ -54,7 +54,7 @@ pub(crate) struct CargoTargetSpec { pub(crate) package: String, pub(crate) target: String, pub(crate) target_kind: TargetKind, - pub(crate) crate_id: CrateId, + pub(crate) crate_id: Crate, pub(crate) required_features: Vec, pub(crate) features: FxHashSet, pub(crate) sysroot_root: Option, diff --git a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml index 95f4cb9d67e25..2547a02a2916c 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml +++ b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml @@ -18,6 +18,7 @@ rustc-hash.workspace = true span.workspace = true stdx.workspace = true intern.workspace = true +triomphe.workspace = true [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs index 4b5c2ff4cf7d2..51d6179a62bad 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs +++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs @@ -1,10 +1,10 @@ //! A set of high-level utility fixture methods to use in tests. -use std::{iter, mem, str::FromStr, sync}; +use std::{mem, str::FromStr, sync}; use base_db::{ - CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, CrateWorkspaceData, Dependency, - Env, FileChange, FileSet, LangCrateOrigin, RootQueryDb, SourceDatabase, SourceRoot, Version, - VfsPath, + Crate, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData, + DependencyBuilder, Env, FileChange, FileSet, LangCrateOrigin, SourceDatabase, SourceRoot, + Version, VfsPath, }; use cfg::CfgOptions; use hir_expand::{ @@ -26,6 +26,7 @@ use test_utils::{ extract_range_or_offset, Fixture, FixtureWithProjectMeta, RangeOrOffset, CURSOR_MARKER, ESCAPED_CURSOR_MARKER, }; +use triomphe::Arc; pub const WORKSPACE: base_db::SourceRootId = base_db::SourceRootId(0); @@ -101,14 +102,8 @@ pub trait WithFixture: Default + ExpandDatabase + SourceDatabase + 'static { (db, file_id, range_or_offset) } - fn test_crate(&self) -> CrateId { - let crate_graph = RootQueryDb::crate_graph(self); - let mut it = crate_graph.iter(); - let mut res = it.next().unwrap(); - while crate_graph[res].origin.is_lang() { - res = it.next().unwrap(); - } - res + fn test_crate(&self) -> Crate { + self.all_crates().iter().copied().find(|&krate| !krate.data(self).origin.is_lang()).unwrap() } } @@ -146,7 +141,7 @@ impl ChangeFixture { let mut source_change = FileChange::new(); let mut files = Vec::new(); - let mut crate_graph = CrateGraph::default(); + let mut crate_graph = CrateGraphBuilder::default(); let mut crates = FxHashMap::default(); let mut crate_deps = Vec::new(); let mut default_crate_root: Option = None; @@ -163,6 +158,9 @@ impl ChangeFixture { let mut file_position = None; + let crate_ws_data = + Arc::new(CrateWorkspaceData { data_layout: target_data_layout, toolchain }); + for entry in fixture { let mut range_or_offset = None; let text = if entry.text.contains(CURSOR_MARKER) { @@ -210,11 +208,12 @@ impl ChangeFixture { Some(crate_name.clone().into()), version, From::from(meta.cfg.clone()), - Some(From::from(meta.cfg)), + Some(meta.cfg), meta.env, origin, false, None, + crate_ws_data.clone(), ); let prev = crates.insert(crate_name.clone(), crate_id); assert!(prev.is_none(), "multiple crates with same name: {crate_name}"); @@ -249,19 +248,23 @@ impl ChangeFixture { Some(CrateName::new("ra_test_fixture").unwrap().into()), None, From::from(default_cfg.clone()), - Some(From::from(default_cfg)), + Some(default_cfg), default_env, CrateOrigin::Local { repo: None, name: None }, false, None, + crate_ws_data.clone(), ); } else { for (from, to, prelude) in crate_deps { let from_id = crates[&from]; let to_id = crates[&to]; - let sysroot = crate_graph[to_id].origin.is_lang(); + let sysroot = crate_graph[to_id].basic.origin.is_lang(); crate_graph - .add_dep(from_id, Dependency::with_prelude(to.clone(), to_id, prelude, sysroot)) + .add_dep( + from_id, + DependencyBuilder::with_prelude(to.clone(), to_id, prelude, sysroot), + ) .unwrap(); } } @@ -276,7 +279,7 @@ impl ChangeFixture { source_change.change_file(core_file, Some(mini_core.source_code())); - let all_crates = crate_graph.crates_in_topological_order(); + let all_crates = crate_graph.iter().collect::>(); let core_crate = crate_graph.add_crate_root( core_file, @@ -292,13 +295,14 @@ impl ChangeFixture { CrateOrigin::Lang(LangCrateOrigin::Core), false, None, + crate_ws_data.clone(), ); for krate in all_crates { crate_graph .add_dep( krate, - Dependency::with_prelude( + DependencyBuilder::with_prelude( CrateName::new("core").unwrap(), core_crate, true, @@ -324,7 +328,7 @@ impl ChangeFixture { source_change.change_file(proc_lib_file, Some(source)); - let all_crates = crate_graph.crates_in_topological_order(); + let all_crates = crate_graph.iter().collect::>(); let proc_macros_crate = crate_graph.add_crate_root( proc_lib_file, @@ -340,6 +344,7 @@ impl ChangeFixture { CrateOrigin::Local { repo: None, name: None }, true, None, + crate_ws_data, ); proc_macros.insert(proc_macros_crate, Ok(proc_macro)); @@ -347,7 +352,10 @@ impl ChangeFixture { crate_graph .add_dep( krate, - Dependency::new(CrateName::new("proc_macros").unwrap(), proc_macros_crate), + DependencyBuilder::new( + CrateName::new("proc_macros").unwrap(), + proc_macros_crate, + ), ) .unwrap(); } @@ -359,19 +367,9 @@ impl ChangeFixture { }; roots.push(root); - let mut change = - ChangeWithProcMacros { source_change, proc_macros: Some(proc_macros.build()) }; + let mut change = ChangeWithProcMacros { source_change, proc_macros: Some(proc_macros) }; change.source_change.set_roots(roots); - change.source_change.set_ws_data( - crate_graph - .iter() - .zip(iter::repeat(From::from(CrateWorkspaceData { - data_layout: target_data_layout, - toolchain, - }))) - .collect(), - ); change.source_change.set_crate_graph(crate_graph); ChangeFixture { file_position, files, change } @@ -654,6 +652,10 @@ impl ProcMacroExpander for IdentityProcMacroExpander { ) -> Result { Ok(subtree.clone()) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.as_any().type_id() == std::any::TypeId::of::() + } } // Expands to a macro_rules! macro, for issue #18089. @@ -685,6 +687,10 @@ impl ProcMacroExpander for Issue18089ProcMacroExpander { #subtree }) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.as_any().type_id() == std::any::TypeId::of::() + } } // Pastes the attribute input as its output @@ -705,6 +711,10 @@ impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander { .cloned() .ok_or_else(|| ProcMacroExpansionError::Panic("Expected attribute input".into())) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.as_any().type_id() == std::any::TypeId::of::() + } } #[derive(Debug)] @@ -736,6 +746,10 @@ impl ProcMacroExpander for Issue18840ProcMacroExpander { top_subtree_delimiter_mut.close = def_site; Ok(result) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.as_any().type_id() == std::any::TypeId::of::() + } } #[derive(Debug)] @@ -767,6 +781,10 @@ impl ProcMacroExpander for MirrorProcMacroExpander { traverse(&mut builder, input.iter()); Ok(builder.build()) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.as_any().type_id() == std::any::TypeId::of::() + } } // Replaces every literal with an empty string literal and every identifier with its first letter, @@ -807,6 +825,10 @@ impl ProcMacroExpander for ShortenProcMacroExpander { } } } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.as_any().type_id() == std::any::TypeId::of::() + } } // Reads ident type within string quotes, for issue #17479. @@ -832,6 +854,10 @@ impl ProcMacroExpander for Issue17479ProcMacroExpander { #symbol() }) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.as_any().type_id() == std::any::TypeId::of::() + } } // Reads ident type within string quotes, for issue #17479. @@ -883,6 +909,10 @@ impl ProcMacroExpander for Issue18898ProcMacroExpander { } }) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.as_any().type_id() == std::any::TypeId::of::() + } } // Reads ident type within string quotes, for issue #17479. @@ -910,4 +940,8 @@ impl ProcMacroExpander for DisallowCfgProcMacroExpander { } Ok(subtree.clone()) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.as_any().type_id() == std::any::TypeId::of::() + } } From f335d00263fd429d12fd844134df54657357de56 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sat, 8 Mar 2025 20:38:47 +0200 Subject: [PATCH 0106/2248] Lower Return Type Notation (`Type::method(..): Send`) We do it the way rustc does it, by only marking segments with it, and not the whole path. This will allow extending where it is allowed in the future. --- .../crates/hir-def/src/generics.rs | 2 +- .../rust-analyzer/crates/hir-def/src/path.rs | 29 +++- .../crates/hir-def/src/path/lower.rs | 26 +++- .../crates/hir-ty/src/display.rs | 131 +++++++++--------- .../crates/hir-ty/src/lower/path.rs | 17 ++- 5 files changed, 125 insertions(+), 80 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs index 6f1650adeb6fe..682f21ab3b4c0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs @@ -872,7 +872,7 @@ fn copy_generic_args( args, has_self_type: generic_args.has_self_type, bindings, - desugared_from_fn: generic_args.desugared_from_fn, + parenthesized: generic_args.parenthesized, } }) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/path.rs index 713e7389736a0..8f170fb983acc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path.rs @@ -79,6 +79,19 @@ thin_vec_with_header_struct! { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum GenericArgsParentheses { + No, + /// Bounds of the form `Type::method(..): Send` or `impl Trait`, + /// aka. Return Type Notation or RTN. + ReturnTypeNotation, + /// `Fn`-family parenthesized traits, e.g. `impl Fn(u32) -> String`. + /// + /// This is desugared into one generic argument containing a tuple of all arguments, + /// and an associated type binding for `Output` for the return type. + ParenSugar, +} + /// Generic arguments to a path segment (e.g. the `i32` in `Option`). This /// also includes bindings of associated types, like in `Iterator`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -92,9 +105,8 @@ pub struct GenericArgs { pub has_self_type: bool, /// Associated type bindings like in `Iterator`. pub bindings: Box<[AssociatedTypeBinding]>, - /// Whether these generic args were desugared from `Trait(Arg) -> Output` - /// parenthesis notation typically used for the `Fn` traits. - pub desugared_from_fn: bool, + /// Whether these generic args were written with parentheses and how. + pub parenthesized: GenericArgsParentheses, } /// An associated type binding like in `Iterator`. @@ -326,7 +338,16 @@ impl GenericArgs { args: Box::default(), has_self_type: false, bindings: Box::default(), - desugared_from_fn: false, + parenthesized: GenericArgsParentheses::No, + } + } + + pub(crate) fn return_type_notation() -> GenericArgs { + GenericArgs { + args: Box::default(), + has_self_type: false, + bindings: Box::default(), + parenthesized: GenericArgsParentheses::ReturnTypeNotation, } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs index 7a6d6973298b7..c6ea3c4d71054 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs @@ -13,7 +13,10 @@ use stdx::thin_vec::EmptyOptimizedThinVec; use syntax::ast::{self, AstNode, HasGenericArgs, HasTypeBounds}; use crate::{ - path::{AssociatedTypeBinding, GenericArg, GenericArgs, ModPath, Path, PathKind}, + path::{ + AssociatedTypeBinding, GenericArg, GenericArgs, GenericArgsParentheses, ModPath, Path, + PathKind, + }, type_ref::{LifetimeRef, TypeBound, TypeRef}, }; @@ -73,6 +76,9 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option< segment.parenthesized_arg_list(), segment.ret_type(), ) + }) + .or_else(|| { + segment.return_type_syntax().map(|_| GenericArgs::return_type_notation()) }); if args.is_some() { generic_args.resize(segments.len(), None); @@ -126,7 +132,7 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option< has_self_type: true, bindings: it.bindings.clone(), - desugared_from_fn: it.desugared_from_fn, + parenthesized: it.parenthesized, }, None => GenericArgs { args: Box::new([self_type]), @@ -281,7 +287,12 @@ pub(super) fn lower_generic_args( let name = name_ref.as_name(); let args = assoc_type_arg .generic_arg_list() - .and_then(|args| lower_generic_args(lower_ctx, args)); + .and_then(|args| lower_generic_args(lower_ctx, args)) + .or_else(|| { + assoc_type_arg + .return_type_syntax() + .map(|_| GenericArgs::return_type_notation()) + }); let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it)); let type_ref = type_ref @@ -315,7 +326,7 @@ pub(super) fn lower_generic_args( args: args.into_boxed_slice(), has_self_type: false, bindings: bindings.into_boxed_slice(), - desugared_from_fn: false, + parenthesized: GenericArgsParentheses::No, }) } @@ -353,5 +364,10 @@ fn lower_generic_args_from_fn_path( bounds: Box::default(), }]) }; - Some(GenericArgs { args, has_self_type: false, bindings, desugared_from_fn: true }) + Some(GenericArgs { + args, + has_self_type: false, + bindings, + parenthesized: GenericArgsParentheses::ParenSugar, + }) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 2ae7e746ba203..db305e98da434 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -2303,77 +2303,82 @@ impl HirDisplayWithTypesMap for Path { if let Some(generic_args) = segment.args_and_bindings { // We should be in type context, so format as `Foo` instead of `Foo::`. // Do we actually format expressions? - if generic_args.desugared_from_fn { - // First argument will be a tuple, which already includes the parentheses. - // If the tuple only contains 1 item, write it manually to avoid the trailing `,`. - let tuple = match generic_args.args[0] { - hir_def::path::GenericArg::Type(ty) => match &types_map[ty] { - TypeRef::Tuple(it) => Some(it), + match generic_args.parenthesized { + hir_def::path::GenericArgsParentheses::ReturnTypeNotation => { + write!(f, "(..)")?; + } + hir_def::path::GenericArgsParentheses::ParenSugar => { + // First argument will be a tuple, which already includes the parentheses. + // If the tuple only contains 1 item, write it manually to avoid the trailing `,`. + let tuple = match generic_args.args[0] { + hir_def::path::GenericArg::Type(ty) => match &types_map[ty] { + TypeRef::Tuple(it) => Some(it), + _ => None, + }, _ => None, - }, - _ => None, - }; - if let Some(v) = tuple { - if v.len() == 1 { - write!(f, "(")?; - v[0].hir_fmt(f, types_map)?; - write!(f, ")")?; - } else { - generic_args.args[0].hir_fmt(f, types_map)?; + }; + if let Some(v) = tuple { + if v.len() == 1 { + write!(f, "(")?; + v[0].hir_fmt(f, types_map)?; + write!(f, ")")?; + } else { + generic_args.args[0].hir_fmt(f, types_map)?; + } } - } - if let Some(ret) = generic_args.bindings[0].type_ref { - if !matches!(&types_map[ret], TypeRef::Tuple(v) if v.is_empty()) { - write!(f, " -> ")?; - ret.hir_fmt(f, types_map)?; + if let Some(ret) = generic_args.bindings[0].type_ref { + if !matches!(&types_map[ret], TypeRef::Tuple(v) if v.is_empty()) { + write!(f, " -> ")?; + ret.hir_fmt(f, types_map)?; + } } } - return Ok(()); - } - - let mut first = true; - // Skip the `Self` bound if exists. It's handled outside the loop. - for arg in &generic_args.args[generic_args.has_self_type as usize..] { - if first { - first = false; - write!(f, "<")?; - } else { - write!(f, ", ")?; - } - arg.hir_fmt(f, types_map)?; - } - for binding in generic_args.bindings.iter() { - if first { - first = false; - write!(f, "<")?; - } else { - write!(f, ", ")?; - } - write!(f, "{}", binding.name.display(f.db.upcast(), f.edition()))?; - match &binding.type_ref { - Some(ty) => { - write!(f, " = ")?; - ty.hir_fmt(f, types_map)? + hir_def::path::GenericArgsParentheses::No => { + let mut first = true; + // Skip the `Self` bound if exists. It's handled outside the loop. + for arg in &generic_args.args[generic_args.has_self_type as usize..] { + if first { + first = false; + write!(f, "<")?; + } else { + write!(f, ", ")?; + } + arg.hir_fmt(f, types_map)?; } - None => { - write!(f, ": ")?; - f.write_joined( - binding.bounds.iter().map(TypesMapAdapter::wrap(types_map)), - " + ", - )?; + for binding in generic_args.bindings.iter() { + if first { + first = false; + write!(f, "<")?; + } else { + write!(f, ", ")?; + } + write!(f, "{}", binding.name.display(f.db.upcast(), f.edition()))?; + match &binding.type_ref { + Some(ty) => { + write!(f, " = ")?; + ty.hir_fmt(f, types_map)? + } + None => { + write!(f, ": ")?; + f.write_joined( + binding.bounds.iter().map(TypesMapAdapter::wrap(types_map)), + " + ", + )?; + } + } } - } - } - // There may be no generic arguments to print, in case of a trait having only a - // single `Self` bound which is converted to `::Assoc`. - if !first { - write!(f, ">")?; - } + // There may be no generic arguments to print, in case of a trait having only a + // single `Self` bound which is converted to `::Assoc`. + if !first { + write!(f, ">")?; + } - // Current position: `|` - if generic_args.has_self_type { - write!(f, ">")?; + // Current position: `|` + if generic_args.has_self_type { + write!(f, ">")?; + } + } } } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs index a165932ddcc8c..58b143e84e0cf 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs @@ -8,7 +8,7 @@ use hir_def::{ data::TraitFlags, expr_store::HygieneId, generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, - path::{GenericArg, GenericArgs, Path, PathSegment, PathSegments}, + path::{GenericArg, GenericArgs, GenericArgsParentheses, Path, PathSegment, PathSegments}, resolver::{ResolveValueResult, TypeNs, ValueNs}, type_ref::{TypeBound, TypeRef, TypesMap}, GenericDefId, GenericParamId, ItemContainerId, Lookup, TraitId, @@ -138,12 +138,15 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { fn prohibit_parenthesized_generic_args(&mut self) -> bool { if let Some(generic_args) = self.current_or_prev_segment.args_and_bindings { - if generic_args.desugared_from_fn { - let segment = self.current_segment_u32(); - self.on_diagnostic( - PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment }, - ); - return true; + match generic_args.parenthesized { + GenericArgsParentheses::No => {} + GenericArgsParentheses::ReturnTypeNotation | GenericArgsParentheses::ParenSugar => { + let segment = self.current_segment_u32(); + self.on_diagnostic( + PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment }, + ); + return true; + } } } false From f31ddcf52406c28dad8c35c7d5bbbe496e9cf2fb Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sat, 8 Mar 2025 20:56:54 +0200 Subject: [PATCH 0107/2248] Emit an error when RTN is used in an incorrect place We miss one place: associated type bindings aka. `impl Trait`, but we also miss it for Fn-style parenthesizes error so I left it out for now. --- .../crates/hir-ty/src/lower/path.rs | 10 +++- .../crates/hir/src/diagnostics.rs | 18 +++++++ .../ide-diagnostics/src/handlers/bad_rtn.rs | 52 +++++++++++++++++++ .../crates/ide-diagnostics/src/lib.rs | 2 + 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/bad_rtn.rs diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs index 58b143e84e0cf..e237009ebaf65 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs @@ -607,8 +607,14 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { ) -> Substitution { let prohibit_parens = match def { GenericDefId::TraitId(trait_) => { - let trait_data = self.ctx.db.trait_data(trait_); - !trait_data.flags.contains(TraitFlags::RUSTC_PAREN_SUGAR) + // RTN is prohibited anyways if we got here. + let is_rtn = + self.current_or_prev_segment.args_and_bindings.is_some_and(|generics| { + generics.parenthesized == GenericArgsParentheses::ReturnTypeNotation + }); + let is_fn_trait = + !self.ctx.db.trait_data(trait_).flags.contains(TraitFlags::RUSTC_PAREN_SUGAR); + is_rtn || is_fn_trait } _ => true, }; diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index 1ed0daa375630..b383fa625e3bc 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -113,6 +113,7 @@ diagnostics![ UnusedVariable, GenericArgsProhibited, ParenthesizedGenericArgsWithoutFnTrait, + BadRtn, ]; #[derive(Debug)] @@ -420,6 +421,11 @@ pub struct ParenthesizedGenericArgsWithoutFnTrait { pub args: InFile>, } +#[derive(Debug)] +pub struct BadRtn { + pub rtn: InFile>, +} + impl AnyDiagnostic { pub(crate) fn body_validation_diagnostic( db: &dyn HirDatabase, @@ -712,6 +718,12 @@ impl AnyDiagnostic { Some(match *diag { PathLoweringDiagnostic::GenericArgsProhibited { segment, reason } => { let segment = hir_segment_to_ast_segment(&path.value, segment)?; + + if let Some(rtn) = segment.return_type_syntax() { + // RTN errors are emitted as `GenericArgsProhibited` or `ParenthesizedGenericArgsWithoutFnTrait`. + return Some(BadRtn { rtn: path.with_value(AstPtr::new(&rtn)) }.into()); + } + let args = if let Some(generics) = segment.generic_arg_list() { AstPtr::new(&generics).wrap_left() } else { @@ -722,6 +734,12 @@ impl AnyDiagnostic { } PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment } => { let segment = hir_segment_to_ast_segment(&path.value, segment)?; + + if let Some(rtn) = segment.return_type_syntax() { + // RTN errors are emitted as `GenericArgsProhibited` or `ParenthesizedGenericArgsWithoutFnTrait`. + return Some(BadRtn { rtn: path.with_value(AstPtr::new(&rtn)) }.into()); + } + let args = AstPtr::new(&segment.parenthesized_arg_list()?); let args = path.with_value(args); ParenthesizedGenericArgsWithoutFnTrait { args }.into() diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/bad_rtn.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/bad_rtn.rs new file mode 100644 index 0000000000000..9ed85f9f208e8 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/bad_rtn.rs @@ -0,0 +1,52 @@ +use ide_db::Severity; + +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; + +// Diagnostic: bad-rtn +// +// This diagnostic is shown when a RTN (Return Type Notation, `Type::method(..): Send`) is written in an improper place. +pub(crate) fn bad_rtn(ctx: &DiagnosticsContext<'_>, d: &hir::BadRtn) -> Diagnostic { + Diagnostic::new_with_syntax_node_ptr( + ctx, + DiagnosticCode::Ra("bad-rtn", Severity::Error), + "return type notation not allowed in this position yet", + d.rtn.map(Into::into), + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::check_diagnostics; + + #[test] + fn fn_traits_also_emit() { + check_diagnostics( + r#" +//- minicore: fn +fn foo< + A: Fn(..), + // ^^^^ error: return type notation not allowed in this position yet +>() {} + "#, + ); + } + + #[test] + fn bad_rtn() { + check_diagnostics( + r#" +mod module { + pub struct Type; +} +trait Trait {} + +fn foo() +where + module(..)::Type: Trait + // ^^^^ error: return type notation not allowed in this position yet +{ +} + "#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index f4ced736b3df8..d1d852faf00e7 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -25,6 +25,7 @@ mod handlers { pub(crate) mod await_outside_of_async; + pub(crate) mod bad_rtn; pub(crate) mod break_outside_of_loop; pub(crate) mod expected_function; pub(crate) mod generic_args_prohibited; @@ -493,6 +494,7 @@ pub fn semantic_diagnostics( AnyDiagnostic::ParenthesizedGenericArgsWithoutFnTrait(d) => { handlers::parenthesized_generic_args_without_fn_trait::parenthesized_generic_args_without_fn_trait(&ctx, &d) } + AnyDiagnostic::BadRtn(d) => handlers::bad_rtn::bad_rtn(&ctx, &d), }; res.push(d) } From 65bd61d2fbef50d28caed626ce601a908d5be77f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 12 Mar 2025 09:47:11 +0100 Subject: [PATCH 0108/2248] 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 7bcf2506f7d5560d81cc3998953b1cd0f8019efd Mon Sep 17 00:00:00 2001 From: jnyfah Date: Thu, 13 Mar 2025 09:04:47 +0100 Subject: [PATCH 0109/2248] insert braces for closure --- .../crates/ide/src/inlay_hints/bind_pat.rs | 10 +++++-- .../crates/ide/src/inlay_hints/closure_ret.rs | 27 ++++++++++++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs index aab8a3f873994..60abb7a44e0ce 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs @@ -1140,12 +1140,11 @@ fn test() { #[test] fn no_edit_for_closure_return_without_body_block() { - // We can lift this limitation; see FIXME in closure_ret module. let config = InlayHintsConfig { closure_return_type_hints: ClosureReturnTypeHints::Always, ..TEST_CONFIG }; - check_no_edit( + check_edit( config, r#" struct S(T); @@ -1154,6 +1153,13 @@ fn test() { let f = |a: S| S(a); } "#, + expect![[r#" + struct S(T); + fn test() { + let f = || -> i32 { 3 }; + let f = |a: S| -> S> { S(a) }; + } + "#]], ); } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs index 61c9c25fe7396..b9bbff333f594 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs @@ -1,8 +1,8 @@ //! Implementation of "closure return type" inlay hints. //! //! Tests live in [`bind_pat`][super::bind_pat] module. -use hir::DisplayTarget; -use ide_db::famous_defs::FamousDefs; +use hir::{DisplayTarget, HirDisplay}; +use ide_db::{famous_defs::FamousDefs, text_edit::TextEdit}; use syntax::ast::{self, AstNode}; use crate::{ @@ -62,7 +62,28 @@ pub(super) fn hints( if arrow.is_none() { " -> " } else { "" }, ) } else { - None + let body = closure.body()?; + let body_range = body.syntax().text_range(); + + Some(config.lazy_text_edit(|| { + let mut builder = TextEdit::builder(); + let insert_pos = param_list.syntax().text_range().end(); + + let rendered = match sema.scope(closure.syntax()).and_then(|scope| { + ty.display_source_code(scope.db, scope.module().into(), false).ok() + }) { + Some(rendered) => rendered, + None => return TextEdit::builder().finish(), + }; + + let arrow_text = if arrow.is_none() { " -> ".to_owned() } else { "".to_owned() }; + builder.insert(insert_pos, arrow_text); + builder.insert(insert_pos, rendered); + builder.insert(body_range.start(), "{ ".to_owned()); + builder.insert(body_range.end(), " }".to_owned()); + + builder.finish() + })) }; acc.push(InlayHint { From 21ee875b4c619141af7347cff9853c7a71131bcf Mon Sep 17 00:00:00 2001 From: jnyfah Date: Thu, 13 Mar 2025 10:53:34 +0100 Subject: [PATCH 0110/2248] remove fixme --- .../rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs index b9bbff333f594..03835ec1f4cf1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs @@ -48,7 +48,6 @@ pub(super) fn hints( if arrow.is_none() { label.prepend_str(" -> "); } - // FIXME?: We could provide text edit to insert braces for closures with non-block body. let text_edit = if has_block_body { ty_to_text_edit( sema, 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 0111/2248] 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 a508206f4e39e28274f77e6f1eb6eac1bbb27191 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Thu, 13 Mar 2025 13:38:29 -0400 Subject: [PATCH 0112/2248] internal: don't panic when the crate graph isn't ready #19351 --- src/tools/rust-analyzer/crates/base-db/src/lib.rs | 7 +++---- .../crates/hir-def/src/nameres/tests/macros.rs | 4 ++-- .../crates/hir-ty/src/consteval/tests.rs | 3 ++- .../rust-analyzer/crates/hir/src/semantics.rs | 8 ++++---- src/tools/rust-analyzer/crates/hir/src/symbols.rs | 5 ++++- .../crates/ide-diagnostics/src/lib.rs | 14 +++++++++++--- .../rust-analyzer/crates/ide-ssr/src/matching.rs | 8 +++----- src/tools/rust-analyzer/crates/ide/src/hover.rs | 2 +- .../rust-analyzer/crates/ide/src/inlay_hints.rs | 5 ++++- .../rust-analyzer/crates/ide/src/runnables.rs | 5 +++-- .../rust-analyzer/crates/ide/src/signature_help.rs | 2 +- .../rust-analyzer/crates/ide/src/static_index.rs | 9 +++++++-- .../crates/ide/src/view_memory_layout.rs | 2 +- .../crates/rust-analyzer/src/cli/analysis_stats.rs | 6 ++++-- 14 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index 324979b2e463b..0f29abbb54f14 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -212,22 +212,21 @@ pub trait RootQueryDb: SourceDatabase + salsa::Database { /// Returns the crates in topological order. /// - /// **Warning**: do not use this query in analysis! It kills incrementality across crate metadata modifications. + /// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications. #[salsa::input] fn all_crates(&self) -> Arc>; /// Returns an iterator over all transitive dependencies of the given crate, /// including the crate itself. /// - /// **Warning**: do not use this query in analysis! It kills incrementality across crate metadata modifications. - /// + /// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications. #[salsa::transparent] fn transitive_deps(&self, crate_id: Crate) -> FxHashSet; /// Returns all transitive reverse dependencies of the given crate, /// including the crate itself. /// - /// **Warning**: Do not use this query in analysis! It kills incrementality across crate metadata modifications. + /// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications. #[salsa::invoke(input::transitive_rev_deps)] #[salsa::transparent] fn transitive_rev_deps(&self, of: Crate) -> FxHashSet; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs index 0348a7076a8d0..5f8a01523d820 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs @@ -1095,7 +1095,7 @@ pub fn derive_macro_2(_item: TokenStream) -> TokenStream { } "#, ); - let krate = *db.all_crates().last().unwrap(); + let krate = *db.all_crates().last().expect("no crate graph present"); let def_map = db.crate_def_map(krate); assert_eq!(def_map.data.exported_derives.len(), 1); @@ -1445,7 +1445,7 @@ struct TokenStream; fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a } "#, ); - let krate = *db.all_crates().last().unwrap(); + let krate = *db.all_crates().last().expect("no crate graph present"); let def_map = db.crate_def_map(krate); let root_module = &def_map[DefMap::ROOT].scope; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 37e7df6f4b46e..d679f9dd7ca42 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -101,7 +101,8 @@ fn check_answer( fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String { let mut err = String::new(); let span_formatter = |file, range| format!("{file:?} {range:?}"); - let display_target = DisplayTarget::from_crate(&db, *db.all_crates().last().unwrap()); + let display_target = + DisplayTarget::from_crate(&db, *db.all_crates().last().expect("no crate graph present")); match e { ConstEvalError::MirLowerError(e) => { e.pretty_print(&mut err, &db, span_formatter, display_target) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 6378eebd24fa0..15cd69f320d33 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -314,11 +314,11 @@ impl<'db> SemanticsImpl<'db> { tree } - /// If not crate is found for the file, returns the last crate in topological order. - pub fn first_crate_or_default(&self, file: FileId) -> Crate { + /// If not crate is found for the file, try to return the last crate in topological order. + pub fn first_crate(&self, file: FileId) -> Option { match self.file_to_module_defs(file).next() { - Some(module) => module.krate(), - None => (*self.db.all_crates().last().unwrap()).into(), + Some(module) => Some(module.krate()), + None => self.db.all_crates().last().copied().map(Into::into), } } diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index cc8aa1f1a18ed..2a6c15207a337 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -77,7 +77,10 @@ impl<'a> SymbolCollector<'a> { symbols: Default::default(), work: Default::default(), current_container_name: None, - display_target: DisplayTarget::from_crate(db, *db.all_crates().last().unwrap()), + display_target: DisplayTarget::from_crate( + db, + *db.all_crates().last().expect("no crate graph present"), + ), } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index f4ced736b3df8..dc6fd1f5eaeb7 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -389,9 +389,17 @@ pub fn semantic_diagnostics( module.and_then(|m| db.toolchain_channel(m.krate().into())), Some(ReleaseChannel::Nightly) | None ); - let krate = module - .map(|module| module.krate()) - .unwrap_or_else(|| (*db.all_crates().last().unwrap()).into()); + + let krate = match module { + Some(module) => module.krate(), + None => { + match db.all_crates().last() { + Some(last) => (*last).into(), + // short-circuit, return an empty vec of diagnostics + None => return vec![], + } + } + }; let display_target = krate.to_display_target(db); let ctx = DiagnosticsContext { config, sema, resolve, edition, is_nightly, display_target }; diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs index 48d2431a11fbf..a76516f44f03b 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs @@ -626,11 +626,9 @@ impl<'db, 'sema> Matcher<'db, 'sema> { match_error!("Failed to get receiver type for `{}`", expr.syntax().text()) })? .original; - let krate = self - .sema - .scope(expr.syntax()) - .map(|it| it.krate()) - .unwrap_or_else(|| hir::Crate::from(*self.sema.db.all_crates().last().unwrap())); + let krate = self.sema.scope(expr.syntax()).map(|it| it.krate()).unwrap_or_else(|| { + hir::Crate::from(*self.sema.db.all_crates().last().expect("no crate graph present")) + }); let res = code_type .autoderef(self.sema.db) .enumerate() diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index b00de6ba40833..04189ed52aa79 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -130,7 +130,7 @@ pub(crate) fn hover( let file = sema.parse_guess_edition(file_id).syntax().clone(); let edition = sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT); - let display_target = sema.first_crate_or_default(file_id).to_display_target(db); + let display_target = sema.first_crate(file_id)?.to_display_target(db); let mut res = if range.is_empty() { hover_offset( sema, diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index 3a709e71fbe70..57adf3e2a4721 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -211,7 +211,10 @@ fn hints( file_id: EditionedFileId, node: SyntaxNode, ) { - let display_target = sema.first_crate_or_default(file_id.file_id()).to_display_target(sema.db); + let Some(krate) = sema.first_crate(file_id.file_id()) else { + return; + }; + let display_target = krate.to_display_target(sema.db); closing_brace::hints(hints, sema, config, file_id, display_target, node.clone()); if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) { generic_param::hints(hints, famous_defs, config, any_has_generic_args); diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index baa7ee6897352..f2cb3c1f991a7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -498,8 +498,9 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option { }; let krate = def.krate(db); let edition = krate.map(|it| it.edition(db)).unwrap_or(Edition::CURRENT); - let display_target = - krate.unwrap_or_else(|| (*db.all_crates().last().unwrap()).into()).to_display_target(db); + let display_target = krate + .unwrap_or_else(|| (*db.all_crates().last().expect("no crate graph present")).into()) + .to_display_target(db); if !has_runnable_doc_test(&attrs) { return None; } diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs index b5468a5aee9ff..84912f6be65af 100644 --- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs +++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs @@ -84,7 +84,7 @@ pub(crate) fn signature_help( let token = sema.descend_into_macros_single_exact(token); let edition = sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT); - let display_target = sema.first_crate_or_default(file_id).to_display_target(db); + let display_target = sema.first_crate(file_id)?.to_display_target(db); for node in token.parent_ancestors() { match_ast! { diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs index 5a2b09b513774..c1562769309ed 100644 --- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs +++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs @@ -119,7 +119,9 @@ fn documentation_for_definition( sema.db, famous_defs.as_ref(), def.krate(sema.db) - .unwrap_or_else(|| (*sema.db.all_crates().last().unwrap()).into()) + .unwrap_or_else(|| { + (*sema.db.all_crates().last().expect("no crate graph present")).into() + }) .to_display_target(sema.db), ) } @@ -175,7 +177,10 @@ impl StaticIndex<'_> { let root = sema.parse_guess_edition(file_id).syntax().clone(); let edition = sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT); - let display_target = sema.first_crate_or_default(file_id).to_display_target(self.db); + let display_target = match sema.first_crate(file_id) { + Some(krate) => krate.to_display_target(sema.db), + None => return, + }; let tokens = root.descendants_with_tokens().filter_map(|it| match it { syntax::NodeOrToken::Node(_) => None, syntax::NodeOrToken::Token(it) => Some(it), diff --git a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs index 34bca7bce12cf..02e3b1d500f26 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs @@ -83,7 +83,7 @@ pub(crate) fn view_memory_layout( ) -> Option { let sema = Semantics::new(db); let file = sema.parse_guess_edition(position.file_id); - let display_target = sema.first_crate_or_default(position.file_id).to_display_target(db); + let display_target = sema.first_crate(position.file_id)?.to_display_target(db); let token = pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind { SyntaxKind::IDENT => 3, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index a391a01fae74e..1efc242bfb6d0 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -384,8 +384,10 @@ impl flags::AnalysisStats { for &file_id in &file_ids { let sema = hir::Semantics::new(db); - let display_target = - sema.first_crate_or_default(file_id.file_id()).to_display_target(db); + let display_target = match sema.first_crate(file_id.file_id()) { + Some(krate) => krate.to_display_target(sema.db), + None => continue, + }; let parse = sema.parse_guess_edition(file_id.into()); let file_txt = db.file_text(file_id.into()); From f9696dda6e9d88a88c057e93fbc854104996bc33 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 7 Mar 2025 17:52:17 +0000 Subject: [PATCH 0113/2248] 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 0114/2248] 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 0115/2248] 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 80ce9d1effd19b42a3eea3c571634960ab9a90ef Mon Sep 17 00:00:00 2001 From: yanglsh Date: Fri, 14 Mar 2025 00:15:02 +0800 Subject: [PATCH 0116/2248] fix: `borrow_deref_ref` suggests wrongly when coerce to mut --- clippy_lints/src/borrow_deref_ref.rs | 5 +++- tests/ui/borrow_deref_ref.fixed | 43 ++++++++++++++++++++++++++++ tests/ui/borrow_deref_ref.rs | 43 ++++++++++++++++++++++++++++ tests/ui/borrow_deref_ref.stderr | 8 +++++- 4 files changed, 97 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/borrow_deref_ref.rs b/clippy_lints/src/borrow_deref_ref.rs index 8892a9e6b6b08..cfe5e424ff750 100644 --- a/clippy_lints/src/borrow_deref_ref.rs +++ b/clippy_lints/src/borrow_deref_ref.rs @@ -2,7 +2,7 @@ use crate::reference::DEREF_ADDROF; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; -use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed}; +use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed, is_mutable}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; @@ -73,6 +73,9 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { } }) && !is_from_proc_macro(cx, e) + && let e_ty = cx.typeck_results().expr_ty_adjusted(e) + // check if the reference is coercing to a mutable reference + && (!matches!(e_ty.kind(), ty::Ref(_, _, Mutability::Mut)) || is_mutable(cx, deref_target)) && let Some(deref_text) = deref_target.span.get_source_text(cx) { span_lint_and_then( diff --git a/tests/ui/borrow_deref_ref.fixed b/tests/ui/borrow_deref_ref.fixed index 17c224f10bfea..765dd75fceb92 100644 --- a/tests/ui/borrow_deref_ref.fixed +++ b/tests/ui/borrow_deref_ref.fixed @@ -81,3 +81,46 @@ fn issue_13584() { let p = &raw const *s; let _ = p as *const i8; } + +mod issue_9905 { + use std::{fs, io}; + + pub enum File { + Stdio, + File(fs::File), + } + + impl io::Read for &'_ File { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + match self { + File::Stdio => io::stdin().read(buf), + File::File(file) => (&*file).read(buf), + } + } + } +} + +mod issue_11346 { + struct Struct; + + impl Struct { + fn foo(self: &mut &Self) {} + } + + trait Trait { + fn bar(&mut self) {} + } + + impl Trait for &Struct {} + + fn bar() { + let s = &Struct; + (&*s).foo(); + (&*s).bar(); + + let mut s = &Struct; + s.foo(); // To avoid a warning about `s` not needing to be mutable + s.foo(); + //~^ borrow_deref_ref + } +} diff --git a/tests/ui/borrow_deref_ref.rs b/tests/ui/borrow_deref_ref.rs index 130ed2903dc61..8ee66bfa881ab 100644 --- a/tests/ui/borrow_deref_ref.rs +++ b/tests/ui/borrow_deref_ref.rs @@ -81,3 +81,46 @@ fn issue_13584() { let p = &raw const *s; let _ = p as *const i8; } + +mod issue_9905 { + use std::{fs, io}; + + pub enum File { + Stdio, + File(fs::File), + } + + impl io::Read for &'_ File { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + match self { + File::Stdio => io::stdin().read(buf), + File::File(file) => (&*file).read(buf), + } + } + } +} + +mod issue_11346 { + struct Struct; + + impl Struct { + fn foo(self: &mut &Self) {} + } + + trait Trait { + fn bar(&mut self) {} + } + + impl Trait for &Struct {} + + fn bar() { + let s = &Struct; + (&*s).foo(); + (&*s).bar(); + + let mut s = &Struct; + s.foo(); // To avoid a warning about `s` not needing to be mutable + (&*s).foo(); + //~^ borrow_deref_ref + } +} diff --git a/tests/ui/borrow_deref_ref.stderr b/tests/ui/borrow_deref_ref.stderr index f5868aa874900..3d55da25b9b20 100644 --- a/tests/ui/borrow_deref_ref.stderr +++ b/tests/ui/borrow_deref_ref.stderr @@ -19,5 +19,11 @@ error: deref on an immutable reference LL | let addr_y = &&*x as *const _ as usize; // assert ok | ^^^ help: if you would like to reborrow, try removing `&*`: `x` -error: aborting due to 3 previous errors +error: deref on an immutable reference + --> tests/ui/borrow_deref_ref.rs:123:9 + | +LL | (&*s).foo(); + | ^^^^^ help: if you would like to reborrow, try removing `&*`: `s` + +error: aborting due to 4 previous errors From 95d72812f83c0fadb4ffba9de6cd230ee85a10d6 Mon Sep 17 00:00:00 2001 From: yanglsh Date: Fri, 14 Mar 2025 14:46:00 +0800 Subject: [PATCH 0117/2248] fix: `manual_find` suggests wrongly when early return --- clippy_lints/src/loops/manual_find.rs | 2 ++ tests/ui/manual_find.rs | 28 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/clippy_lints/src/loops/manual_find.rs b/clippy_lints/src/loops/manual_find.rs index aa8a2934f89bd..35737f3eafe23 100644 --- a/clippy_lints/src/loops/manual_find.rs +++ b/clippy_lints/src/loops/manual_find.rs @@ -3,6 +3,7 @@ use super::utils::make_iterator_snippet; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::implements_trait; +use clippy_utils::usage::contains_return_break_continue_macro; use clippy_utils::{higher, is_res_lang_ctor, path_res, peel_blocks_with_stmt}; use rustc_errors::Applicability; use rustc_hir::def::Res; @@ -35,6 +36,7 @@ pub(super) fn check<'tcx>( && let ExprKind::Call(ctor, [inner_ret]) = ret_value.kind && is_res_lang_ctor(cx, path_res(cx, ctor), LangItem::OptionSome) && path_res(cx, inner_ret) == Res::Local(binding_id) + && !contains_return_break_continue_macro(cond) && let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr) { let mut applicability = Applicability::MachineApplicable; diff --git a/tests/ui/manual_find.rs b/tests/ui/manual_find.rs index 20b557f21d141..7b9846cfe429d 100644 --- a/tests/ui/manual_find.rs +++ b/tests/ui/manual_find.rs @@ -23,4 +23,32 @@ fn tuple(arr: Vec<(String, i32)>) -> Option { None } +mod issue9521 { + fn condition(x: u32, y: u32) -> Result { + todo!() + } + + fn find_with_early_return(v: Vec) -> Option { + for x in v { + if condition(x, 10).ok()? { + return Some(x); + } + } + None + } + + fn find_with_early_break(v: Vec) -> Option { + for x in v { + if if x < 3 { + break; + } else { + x < 10 + } { + return Some(x); + } + } + None + } +} + fn main() {} From 9ccee20d423f567220ce8f29ee215f5d1a17736b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 26 Feb 2025 07:40:42 +0100 Subject: [PATCH 0118/2248] Split assoc items out of `trait_data`/`impl_data` queries --- .../rust-analyzer/crates/hir-def/src/data.rs | 321 +---------------- .../rust-analyzer/crates/hir-def/src/db.rs | 25 +- .../crates/hir-def/src/expr_store/pretty.rs | 2 +- .../crates/hir-def/src/import_map.rs | 6 +- .../crates/hir-def/src/lang_item.rs | 4 +- .../crates/hir-def/src/nameres.rs | 1 + .../crates/hir-def/src/nameres/assoc.rs | 325 ++++++++++++++++++ .../crates/hir-ty/src/autoderef.rs | 2 +- .../crates/hir-ty/src/chalk_db.rs | 12 +- .../crates/hir-ty/src/diagnostics/expr.rs | 2 +- .../crates/hir-ty/src/display.rs | 2 +- .../crates/hir-ty/src/dyn_compatibility.rs | 4 +- .../rust-analyzer/crates/hir-ty/src/infer.rs | 2 +- .../crates/hir-ty/src/infer/closure.rs | 2 +- .../crates/hir-ty/src/infer/expr.rs | 8 +- .../crates/hir-ty/src/infer/mutability.rs | 4 +- .../crates/hir-ty/src/infer/path.rs | 2 +- .../crates/hir-ty/src/infer/unify.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/lib.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/lower.rs | 4 +- .../crates/hir-ty/src/lower/path.rs | 2 +- .../crates/hir-ty/src/method_resolution.rs | 24 +- .../crates/hir-ty/src/mir/eval.rs | 12 +- .../crates/hir-ty/src/mir/eval/shim.rs | 2 +- .../crates/hir-ty/src/mir/lower/as_place.rs | 4 +- .../rust-analyzer/crates/hir-ty/src/tests.rs | 4 +- .../rust-analyzer/crates/hir-ty/src/utils.rs | 2 +- .../rust-analyzer/crates/hir/src/attrs.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/db.rs | 4 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 37 +- .../hir/src/semantics/child_by_source.rs | 4 +- .../crates/hir/src/source_analyzer.rs | 6 +- .../rust-analyzer/crates/hir/src/symbols.rs | 4 +- .../crates/ide-db/src/apply_change.rs | 4 +- 34 files changed, 446 insertions(+), 397 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index 9c87dc31dba95..8a1f07c92efff 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -3,33 +3,21 @@ pub mod adt; use base_db::Crate; -use hir_expand::{ - name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind, -}; +use hir_expand::name::Name; use intern::{sym, Symbol}; use la_arena::{Idx, RawIdx}; -use smallvec::SmallVec; -use syntax::{ast, Parse}; use triomphe::Arc; use tt::iter::TtElement; use crate::{ db::DefDatabase, - expander::{Expander, Mark}, - item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId}, - macro_call_as_call_id, - nameres::{ - attr_resolution::ResolvedAttr, - diagnostics::{DefDiagnostic, DefDiagnostics}, - proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind}, - DefMap, LocalDefMap, MacroSubNs, - }, + item_tree::{self, FnFlags, ModItem}, + nameres::proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind}, path::ImportAlias, type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap}, visibility::RawVisibility, - AssocItemId, AstIdWithPath, ConstId, ConstLoc, ExternCrateId, FunctionId, FunctionLoc, - HasModule, ImplId, Intern, ItemContainerId, ItemLoc, Lookup, Macro2Id, MacroRulesId, ModuleId, - ProcMacroId, StaticId, TraitAliasId, TraitId, TypeAliasId, TypeAliasLoc, + ConstId, ExternCrateId, FunctionId, HasModule, ImplId, ItemContainerId, ItemLoc, Lookup, + Macro2Id, MacroRulesId, ProcMacroId, StaticId, TraitAliasId, TraitId, TypeAliasId, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -256,23 +244,13 @@ bitflags::bitflags! { #[derive(Debug, Clone, PartialEq, Eq)] pub struct TraitData { pub name: Name, - pub items: Box<[(Name, AssocItemId)]>, pub flags: TraitFlags, pub visibility: RawVisibility, - // box it as the vec is usually empty anyways - pub macro_calls: Option, MacroCallId)>>>, } impl TraitData { #[inline] pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc { - db.trait_data_with_diagnostics(tr).0 - } - - pub(crate) fn trait_data_with_diagnostics_query( - db: &dyn DefDatabase, - tr: TraitId, - ) -> (Arc, DefDiagnostics) { let ItemLoc { container: module_id, id: tree_id } = tr.lookup(db); let item_tree = tree_id.item_tree(db); let tr_def = &item_tree[tree_id.value]; @@ -317,40 +295,7 @@ impl TraitData { flags |= TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH; } - let mut collector = - AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr)); - collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items); - let (items, macro_calls, diagnostics) = collector.finish(); - - ( - Arc::new(TraitData { name, macro_calls, items, visibility, flags }), - DefDiagnostics::new(diagnostics), - ) - } - - pub fn associated_types(&self) -> impl Iterator + '_ { - self.items.iter().filter_map(|(_name, item)| match item { - AssocItemId::TypeAliasId(t) => Some(*t), - _ => None, - }) - } - - pub fn associated_type_by_name(&self, name: &Name) -> Option { - self.items.iter().find_map(|(item_name, item)| match item { - AssocItemId::TypeAliasId(t) if item_name == name => Some(*t), - _ => None, - }) - } - - pub fn method_by_name(&self, name: &Name) -> Option { - self.items.iter().find_map(|(item_name, item)| match item { - AssocItemId::FunctionId(t) if item_name == name => Some(*t), - _ => None, - }) - } - - pub fn attribute_calls(&self) -> impl Iterator, MacroCallId)> + '_ { - self.macro_calls.iter().flat_map(|it| it.iter()).copied() + Arc::new(TraitData { name, visibility, flags }) } } @@ -375,26 +320,16 @@ impl TraitAliasData { pub struct ImplData { pub target_trait: Option, pub self_ty: TypeRefId, - pub items: Box<[(Name, AssocItemId)]>, pub is_negative: bool, pub is_unsafe: bool, - // box it as the vec is usually empty anyways - pub macro_calls: Option, MacroCallId)>>>, pub types_map: Arc, } impl ImplData { #[inline] pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc { - db.impl_data_with_diagnostics(id).0 - } - - pub(crate) fn impl_data_with_diagnostics_query( - db: &dyn DefDatabase, - id: ImplId, - ) -> (Arc, DefDiagnostics) { - let _p = tracing::info_span!("impl_data_with_diagnostics_query").entered(); - let ItemLoc { container: module_id, id: tree_id } = id.lookup(db); + let _p = tracing::info_span!("impl_data_query").entered(); + let ItemLoc { id: tree_id, .. } = id.lookup(db); let item_tree = tree_id.item_tree(db); let impl_def = &item_tree[tree_id.value]; @@ -403,28 +338,13 @@ impl ImplData { let is_negative = impl_def.is_negative; let is_unsafe = impl_def.is_unsafe; - let mut collector = - AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id)); - collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items); - - let (items, macro_calls, diagnostics) = collector.finish(); - - ( - Arc::new(ImplData { - target_trait, - self_ty, - items, - is_negative, - is_unsafe, - macro_calls, - types_map: impl_def.types_map.clone(), - }), - DefDiagnostics::new(diagnostics), - ) - } - - pub fn attribute_calls(&self) -> impl Iterator, MacroCallId)> + '_ { - self.macro_calls.iter().flat_map(|it| it.iter()).copied() + Arc::new(ImplData { + target_trait, + self_ty, + is_negative, + is_unsafe, + types_map: impl_def.types_map.clone(), + }) } } @@ -628,217 +548,6 @@ impl StaticData { } } -struct AssocItemCollector<'a> { - db: &'a dyn DefDatabase, - module_id: ModuleId, - def_map: Arc, - local_def_map: Arc, - diagnostics: Vec, - container: ItemContainerId, - expander: Expander, - - items: Vec<(Name, AssocItemId)>, - macro_calls: Vec<(AstId, MacroCallId)>, -} - -impl<'a> AssocItemCollector<'a> { - fn new( - db: &'a dyn DefDatabase, - module_id: ModuleId, - file_id: HirFileId, - container: ItemContainerId, - ) -> Self { - let (def_map, local_def_map) = module_id.local_def_map(db); - Self { - db, - module_id, - def_map, - local_def_map, - container, - expander: Expander::new(db, file_id, module_id), - items: Vec::new(), - macro_calls: Vec::new(), - diagnostics: Vec::new(), - } - } - - fn finish( - self, - ) -> ( - Box<[(Name, AssocItemId)]>, - Option, MacroCallId)>>>, - Vec, - ) { - ( - self.items.into_boxed_slice(), - if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) }, - self.diagnostics, - ) - } - - fn collect(&mut self, item_tree: &ItemTree, tree_id: TreeId, assoc_items: &[AssocItem]) { - let container = self.container; - self.items.reserve(assoc_items.len()); - - 'items: for &item in assoc_items { - let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into()); - if !attrs.is_cfg_enabled(self.expander.cfg_options()) { - self.diagnostics.push(DefDiagnostic::unconfigured_code( - self.module_id.local_id, - tree_id, - ModItem::from(item).into(), - attrs.cfg().unwrap(), - self.expander.cfg_options().clone(), - )); - continue; - } - - 'attrs: for attr in &*attrs { - let ast_id = - AstId::new(self.expander.current_file_id(), item.ast_id(item_tree).upcast()); - let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id }; - - match self.def_map.resolve_attr_macro( - &self.local_def_map, - self.db, - self.module_id.local_id, - ast_id_with_path, - attr, - ) { - Ok(ResolvedAttr::Macro(call_id)) => { - let loc = self.db.lookup_intern_macro_call(call_id); - if let MacroDefKind::ProcMacro(_, exp, _) = loc.def.kind { - // If there's no expander for the proc macro (e.g. the - // proc macro is ignored, or building the proc macro - // crate failed), skip expansion like we would if it was - // disabled. This is analogous to the handling in - // `DefCollector::collect_macros`. - if let Some(err) = exp.as_expand_error(self.module_id.krate) { - self.diagnostics.push(DefDiagnostic::macro_error( - self.module_id.local_id, - ast_id, - (*attr.path).clone(), - err, - )); - continue 'attrs; - } - } - - self.macro_calls.push((ast_id, call_id)); - let res = - self.expander.enter_expand_id::(self.db, call_id); - self.collect_macro_items(res); - continue 'items; - } - Ok(_) => (), - Err(_) => { - self.diagnostics.push(DefDiagnostic::unresolved_macro_call( - self.module_id.local_id, - MacroCallKind::Attr { - ast_id, - attr_args: None, - invoc_attr_index: attr.id, - }, - attr.path().clone(), - )); - } - } - } - - self.collect_item(item_tree, tree_id, container, item); - } - } - - fn collect_item( - &mut self, - item_tree: &ItemTree, - tree_id: TreeId, - container: ItemContainerId, - item: AssocItem, - ) { - match item { - AssocItem::Function(id) => { - let item = &item_tree[id]; - let def = - FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db); - self.items.push((item.name.clone(), def.into())); - } - AssocItem::TypeAlias(id) => { - let item = &item_tree[id]; - let def = - TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db); - self.items.push((item.name.clone(), def.into())); - } - AssocItem::Const(id) => { - let item = &item_tree[id]; - let Some(name) = item.name.clone() else { return }; - let def = ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db); - self.items.push((name, def.into())); - } - AssocItem::MacroCall(call) => { - let file_id = self.expander.current_file_id(); - let MacroCall { ast_id, expand_to, ctxt, ref path } = item_tree[call]; - let module = self.expander.module.local_id; - - let resolver = |path: &_| { - self.def_map - .resolve_path( - &self.local_def_map, - self.db, - module, - path, - crate::item_scope::BuiltinShadowMode::Other, - Some(MacroSubNs::Bang), - ) - .0 - .take_macros() - .map(|it| self.db.macro_def(it)) - }; - match macro_call_as_call_id( - self.db.upcast(), - &AstIdWithPath::new(file_id, ast_id, Clone::clone(path)), - ctxt, - expand_to, - self.expander.krate(), - resolver, - ) { - Ok(Some(call_id)) => { - let res = - self.expander.enter_expand_id::(self.db, call_id); - self.macro_calls.push((InFile::new(file_id, ast_id.upcast()), call_id)); - self.collect_macro_items(res); - } - Ok(None) => (), - Err(_) => { - self.diagnostics.push(DefDiagnostic::unresolved_macro_call( - self.module_id.local_id, - MacroCallKind::FnLike { - ast_id: InFile::new(file_id, ast_id), - expand_to, - eager: None, - }, - Clone::clone(path), - )); - } - } - } - } - } - - fn collect_macro_items(&mut self, res: ExpandResult)>>) { - let Some((mark, _parse)) = res.value else { return }; - - let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None); - let item_tree = tree_id.item_tree(self.db); - let iter: SmallVec<[_; 2]> = - item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item).collect(); - - self.collect(&item_tree, tree_id, &iter); - - self.expander.exit(mark); - } -} - fn trait_vis(db: &dyn DefDatabase, trait_id: TraitId) -> RawVisibility { let ItemLoc { id: tree_id, .. } = trait_id.lookup(db); let item_tree = tree_id.item_tree(db); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index b6707af618115..ff33056538071 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -20,7 +20,11 @@ use crate::{ import_map::ImportMap, item_tree::{AttrOwner, ItemTree, ItemTreeSourceMaps}, lang_item::{self, LangItem, LangItemTarget, LangItems}, - nameres::{diagnostics::DefDiagnostics, DefMap, LocalDefMap}, + nameres::{ + assoc::{ImplItems, TraitItems}, + diagnostics::DefDiagnostics, + DefMap, LocalDefMap, + }, tt, type_ref::TypesSourceMap, visibility::{self, Visibility}, @@ -176,19 +180,26 @@ pub trait DefDatabase: #[salsa::transparent] #[salsa::invoke_actual(VariantData::variant_data)] fn variant_data(&self, id: VariantId) -> Arc; - #[salsa::transparent] + #[salsa::invoke_actual(ImplData::impl_data_query)] fn impl_data(&self, e: ImplId) -> Arc; - #[salsa::invoke_actual(ImplData::impl_data_with_diagnostics_query)] - fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc, DefDiagnostics); - #[salsa::transparent] + #[salsa::invoke_actual(ImplItems::impl_items_query)] + fn impl_items(&self, e: ImplId) -> Arc; + + #[salsa::invoke_actual(ImplItems::impl_items_with_diagnostics_query)] + fn impl_items_with_diagnostics(&self, e: ImplId) -> (Arc, DefDiagnostics); + #[salsa::invoke_actual(TraitData::trait_data_query)] fn trait_data(&self, e: TraitId) -> Arc; - #[salsa::invoke_actual(TraitData::trait_data_with_diagnostics_query)] - fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc, DefDiagnostics); + #[salsa::transparent] + #[salsa::invoke_actual(TraitItems::trait_items_query)] + fn trait_items(&self, e: TraitId) -> Arc; + + #[salsa::invoke_actual(TraitItems::trait_items_with_diagnostics_query)] + fn trait_items_with_diagnostics(&self, tr: TraitId) -> (Arc, DefDiagnostics); #[salsa::invoke_actual(TraitAliasData::trait_alias_query)] fn trait_alias_data(&self, e: TraitAliasId) -> Arc; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs index 82ad756dc2c6a..cc6d200051c3f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs @@ -82,7 +82,7 @@ pub(super) fn print_body_hir( p.buf.push_str(", "); }); // remove the last ", " in param list - if body.params.len() > 0 { + if !body.params.is_empty() { p.buf.truncate(p.buf.len() - 2); } p.buf.push(')'); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs index 1cdc4c025975c..9e4479f05b427 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs @@ -222,7 +222,7 @@ impl ImportMap { trait_import_info: &ImportInfo, ) { let _p = tracing::info_span!("collect_trait_assoc_items").entered(); - for &(ref assoc_item_name, item) in &db.trait_data(tr).items { + for &(ref assoc_item_name, item) in &db.trait_items(tr).items { let module_def_id = match item { AssocItemId::FunctionId(f) => ModuleDefId::from(f), AssocItemId::ConstId(c) => ModuleDefId::from(c), @@ -575,8 +575,8 @@ mod tests { let trait_info = dependency_imports.import_info_for(ItemInNs::Types(trait_id.into()))?; - let trait_data = db.trait_data(trait_id); - let (assoc_item_name, _) = trait_data + let trait_items = db.trait_items(trait_id); + let (assoc_item_name, _) = trait_items .items .iter() .find(|(_, assoc_item_id)| &dependency_assoc_item_id == assoc_item_id)?; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 70c28009f4b99..67788576c13bc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -107,7 +107,7 @@ impl LangItems { for (_, module_data) in crate_def_map.modules() { for impl_def in module_data.scope.impls() { lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef); - for &(_, assoc) in db.impl_data(impl_def).items.iter() { + for &(_, assoc) in db.impl_items(impl_def).items.iter() { match assoc { AssocItemId::FunctionId(f) => { lang_items.collect_lang_item(db, f, LangItemTarget::Function) @@ -124,7 +124,7 @@ impl LangItems { match def { ModuleDefId::TraitId(trait_) => { lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait); - db.trait_data(trait_).items.iter().for_each( + db.trait_items(trait_).items.iter().for_each( |&(_, assoc_id)| match assoc_id { AssocItemId::FunctionId(f) => { lang_items.collect_lang_item(db, f, LangItemTarget::Function); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index 054c285fa2567..a34766ebc1dca 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -47,6 +47,7 @@ //! path and, upon success, we run macro expansion and "collect module" phase on //! the result +pub mod assoc; pub mod attr_resolution; mod collector; pub mod diagnostics; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs new file mode 100644 index 0000000000000..dea6d334f8aa6 --- /dev/null +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs @@ -0,0 +1,325 @@ +//! Expansion of associated items + +use hir_expand::{ + name::Name, AstId, ExpandResult, InFile, Intern, Lookup, MacroCallKind, MacroDefKind, +}; +use smallvec::SmallVec; +use span::{HirFileId, MacroCallId}; +use syntax::{ast, Parse}; +use triomphe::Arc; + +use crate::{ + db::DefDatabase, + expander::{Expander, Mark}, + item_tree::{self, AssocItem, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId}, + macro_call_as_call_id, + nameres::{ + attr_resolution::ResolvedAttr, + diagnostics::{DefDiagnostic, DefDiagnostics}, + DefMap, LocalDefMap, MacroSubNs, + }, + AssocItemId, AstIdWithPath, ConstLoc, FunctionId, FunctionLoc, ImplId, ItemContainerId, + ItemLoc, ModuleId, TraitId, TypeAliasId, TypeAliasLoc, +}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TraitItems { + pub items: Box<[(Name, AssocItemId)]>, + // box it as the vec is usually empty anyways + pub macro_calls: Option, MacroCallId)>>>, +} + +impl TraitItems { + #[inline] + pub(crate) fn trait_items_query(db: &dyn DefDatabase, tr: TraitId) -> Arc { + db.trait_items_with_diagnostics(tr).0 + } + + pub(crate) fn trait_items_with_diagnostics_query( + db: &dyn DefDatabase, + tr: TraitId, + ) -> (Arc, DefDiagnostics) { + let ItemLoc { container: module_id, id: tree_id } = tr.lookup(db); + let item_tree = tree_id.item_tree(db); + let tr_def = &item_tree[tree_id.value]; + + let mut collector = + AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr)); + collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items); + let (items, macro_calls, diagnostics) = collector.finish(); + + (Arc::new(TraitItems { macro_calls, items }), DefDiagnostics::new(diagnostics)) + } + + pub fn associated_types(&self) -> impl Iterator + '_ { + self.items.iter().filter_map(|(_name, item)| match item { + AssocItemId::TypeAliasId(t) => Some(*t), + _ => None, + }) + } + + pub fn associated_type_by_name(&self, name: &Name) -> Option { + self.items.iter().find_map(|(item_name, item)| match item { + AssocItemId::TypeAliasId(t) if item_name == name => Some(*t), + _ => None, + }) + } + + pub fn method_by_name(&self, name: &Name) -> Option { + self.items.iter().find_map(|(item_name, item)| match item { + AssocItemId::FunctionId(t) if item_name == name => Some(*t), + _ => None, + }) + } + + pub fn attribute_calls(&self) -> impl Iterator, MacroCallId)> + '_ { + self.macro_calls.iter().flat_map(|it| it.iter()).copied() + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct ImplItems { + pub items: Box<[(Name, AssocItemId)]>, + // box it as the vec is usually empty anyways + pub macro_calls: Option, MacroCallId)>>>, +} + +impl ImplItems { + #[inline] + pub(crate) fn impl_items_query(db: &dyn DefDatabase, id: ImplId) -> Arc { + db.impl_items_with_diagnostics(id).0 + } + + pub(crate) fn impl_items_with_diagnostics_query( + db: &dyn DefDatabase, + id: ImplId, + ) -> (Arc, DefDiagnostics) { + let _p = tracing::info_span!("impl_items_with_diagnostics_query").entered(); + let ItemLoc { container: module_id, id: tree_id } = id.lookup(db); + + let item_tree = tree_id.item_tree(db); + let impl_def = &item_tree[tree_id.value]; + let mut collector = + AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id)); + collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items); + + let (items, macro_calls, diagnostics) = collector.finish(); + + (Arc::new(ImplItems { items, macro_calls }), DefDiagnostics::new(diagnostics)) + } + + pub fn attribute_calls(&self) -> impl Iterator, MacroCallId)> + '_ { + self.macro_calls.iter().flat_map(|it| it.iter()).copied() + } +} + +struct AssocItemCollector<'a> { + db: &'a dyn DefDatabase, + module_id: ModuleId, + def_map: Arc, + local_def_map: Arc, + diagnostics: Vec, + container: ItemContainerId, + expander: Expander, + + items: Vec<(Name, AssocItemId)>, + macro_calls: Vec<(AstId, MacroCallId)>, +} + +impl<'a> AssocItemCollector<'a> { + fn new( + db: &'a dyn DefDatabase, + module_id: ModuleId, + file_id: HirFileId, + container: ItemContainerId, + ) -> Self { + let (def_map, local_def_map) = module_id.local_def_map(db); + Self { + db, + module_id, + def_map, + local_def_map, + container, + expander: Expander::new(db, file_id, module_id), + items: Vec::new(), + macro_calls: Vec::new(), + diagnostics: Vec::new(), + } + } + + fn finish( + self, + ) -> ( + Box<[(Name, AssocItemId)]>, + Option, MacroCallId)>>>, + Vec, + ) { + ( + self.items.into_boxed_slice(), + if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) }, + self.diagnostics, + ) + } + + fn collect(&mut self, item_tree: &ItemTree, tree_id: TreeId, assoc_items: &[AssocItem]) { + let container = self.container; + self.items.reserve(assoc_items.len()); + + 'items: for &item in assoc_items { + let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into()); + if !attrs.is_cfg_enabled(self.expander.cfg_options()) { + self.diagnostics.push(DefDiagnostic::unconfigured_code( + self.module_id.local_id, + tree_id, + ModItem::from(item).into(), + attrs.cfg().unwrap(), + self.expander.cfg_options().clone(), + )); + continue; + } + + 'attrs: for attr in &*attrs { + let ast_id = + AstId::new(self.expander.current_file_id(), item.ast_id(item_tree).upcast()); + let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id }; + + match self.def_map.resolve_attr_macro( + &self.local_def_map, + self.db, + self.module_id.local_id, + ast_id_with_path, + attr, + ) { + Ok(ResolvedAttr::Macro(call_id)) => { + let loc = self.db.lookup_intern_macro_call(call_id); + if let MacroDefKind::ProcMacro(_, exp, _) = loc.def.kind { + // If there's no expander for the proc macro (e.g. the + // proc macro is ignored, or building the proc macro + // crate failed), skip expansion like we would if it was + // disabled. This is analogous to the handling in + // `DefCollector::collect_macros`. + if let Some(err) = exp.as_expand_error(self.module_id.krate) { + self.diagnostics.push(DefDiagnostic::macro_error( + self.module_id.local_id, + ast_id, + (*attr.path).clone(), + err, + )); + continue 'attrs; + } + } + + self.macro_calls.push((ast_id, call_id)); + let res = + self.expander.enter_expand_id::(self.db, call_id); + self.collect_macro_items(res); + continue 'items; + } + Ok(_) => (), + Err(_) => { + self.diagnostics.push(DefDiagnostic::unresolved_macro_call( + self.module_id.local_id, + MacroCallKind::Attr { + ast_id, + attr_args: None, + invoc_attr_index: attr.id, + }, + attr.path().clone(), + )); + } + } + } + + self.collect_item(item_tree, tree_id, container, item); + } + } + + fn collect_item( + &mut self, + item_tree: &ItemTree, + tree_id: TreeId, + container: ItemContainerId, + item: AssocItem, + ) { + match item { + AssocItem::Function(id) => { + let item = &item_tree[id]; + let def = + FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db); + self.items.push((item.name.clone(), def.into())); + } + AssocItem::TypeAlias(id) => { + let item = &item_tree[id]; + let def = + TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db); + self.items.push((item.name.clone(), def.into())); + } + AssocItem::Const(id) => { + let item = &item_tree[id]; + let Some(name) = item.name.clone() else { return }; + let def = ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db); + self.items.push((name, def.into())); + } + AssocItem::MacroCall(call) => { + let file_id = self.expander.current_file_id(); + let MacroCall { ast_id, expand_to, ctxt, ref path } = item_tree[call]; + let module = self.expander.module.local_id; + + let resolver = |path: &_| { + self.def_map + .resolve_path( + &self.local_def_map, + self.db, + module, + path, + crate::item_scope::BuiltinShadowMode::Other, + Some(MacroSubNs::Bang), + ) + .0 + .take_macros() + .map(|it| self.db.macro_def(it)) + }; + match macro_call_as_call_id( + self.db.upcast(), + &AstIdWithPath::new(file_id, ast_id, Clone::clone(path)), + ctxt, + expand_to, + self.expander.krate(), + resolver, + ) { + Ok(Some(call_id)) => { + let res = + self.expander.enter_expand_id::(self.db, call_id); + self.macro_calls.push((InFile::new(file_id, ast_id.upcast()), call_id)); + self.collect_macro_items(res); + } + Ok(None) => (), + Err(_) => { + self.diagnostics.push(DefDiagnostic::unresolved_macro_call( + self.module_id.local_id, + MacroCallKind::FnLike { + ast_id: InFile::new(file_id, ast_id), + expand_to, + eager: None, + }, + Clone::clone(path), + )); + } + } + } + } + } + + fn collect_macro_items(&mut self, res: ExpandResult)>>) { + let Some((mark, _parse)) = res.value else { return }; + + let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None); + let item_tree = tree_id.item_tree(self.db); + let iter: SmallVec<[_; 2]> = + item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item).collect(); + + self.collect(&item_tree, tree_id, &iter); + + self.expander.exit(mark); + } +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs index 171ba001c4a79..2c27f5e3bbf18 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs @@ -210,7 +210,7 @@ pub(crate) fn deref_by_trait( }; let trait_id = trait_id()?; let target = db - .trait_data(trait_id) + .trait_items(trait_id) .associated_type_by_name(&Name::new_symbol_root(sym::Target.clone()))?; let projection = { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 84eb964d564bd..e5751a394dae5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -294,7 +294,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { .lang_item(self.krate, LangItem::Future) .and_then(|item| item.as_trait()) .and_then(|trait_| { - let alias = self.db.trait_data(trait_).associated_type_by_name( + let alias = self.db.trait_items(trait_).associated_type_by_name( &Name::new_symbol_root(sym::Output.clone()), )?; Some((trait_, alias)) @@ -684,7 +684,8 @@ pub(crate) fn trait_datum_query( fundamental: trait_data.flags.contains(TraitFlags::IS_FUNDAMENTAL), }; let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); - let associated_ty_ids = trait_data.associated_types().map(to_assoc_type_id).collect(); + let associated_ty_ids = + db.trait_items(trait_).associated_types().map(to_assoc_type_id).collect(); let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses }; let well_known = db.lang_attr(trait_.into()).and_then(well_known_trait_from_lang_item); let trait_datum = TraitDatum { @@ -856,8 +857,9 @@ fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId) let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive }; let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses }; - let trait_data = db.trait_data(trait_); - let associated_ty_value_ids = impl_data + let trait_data = db.trait_items(trait_); + let associated_ty_value_ids = db + .impl_items(impl_id) .items .iter() .filter_map(|(_, item)| match item { @@ -908,7 +910,7 @@ fn type_alias_associated_ty_value( .0; // we don't return any assoc ty values if the impl'd trait can't be resolved let assoc_ty = db - .trait_data(trait_ref.hir_trait_id()) + .trait_items(trait_ref.hir_trait_id()) .associated_type_by_name(&type_alias_data.name) .expect("assoc ty value should not exist"); // validated when building the impl data as well let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 053d1cd41e9f1..1035651692ec8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -492,7 +492,7 @@ impl FilterMapNextChecker { Some(next_function_id), match next_function_id.lookup(db.upcast()).container { ItemContainerId::TraitId(iterator_trait_id) => { - let iterator_trait_items = &db.trait_data(iterator_trait_id).items; + let iterator_trait_items = &db.trait_items(iterator_trait_id).items; iterator_trait_items.iter().find_map(|(name, it)| match it { &AssocItemId::FunctionId(id) if *name == sym::filter_map.clone() => { Some(id) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 2ae7e746ba203..be590b6101d6a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -1342,7 +1342,7 @@ impl HirDisplay for Ty { .lang_item(body.module(db.upcast()).krate(), LangItem::Future) .and_then(LangItemTarget::as_trait); let output = future_trait.and_then(|t| { - db.trait_data(t).associated_type_by_name(&Name::new_symbol_root( + db.trait_items(t).associated_type_by_name(&Name::new_symbol_root( sym::Output.clone(), )) }); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs index 6a01579bccc9d..af16a2499ba08 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs @@ -103,7 +103,7 @@ where // rustc checks for non-lifetime binders here, but we don't support HRTB yet - let trait_data = db.trait_data(trait_); + let trait_data = db.trait_items(trait_); for (_, assoc_item) in &trait_data.items { dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?; } @@ -166,7 +166,7 @@ fn predicates_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool { // Same as the above, `predicates_reference_self` fn bounds_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool { - let trait_data = db.trait_data(trait_); + let trait_data = db.trait_items(trait_); trait_data .items .iter() diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 556091c404614..9a4b7af85d8f9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -1723,7 +1723,7 @@ impl<'a> InferenceContext<'a> { fn resolve_output_on(&self, trait_: TraitId) -> Option { self.db - .trait_data(trait_) + .trait_items(trait_) .associated_type_by_name(&Name::new_symbol_root(sym::Output.clone())) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index 50cac034e493f..ef02762c80a53 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -815,7 +815,7 @@ impl InferenceContext<'_> { { if let Some(deref_fn) = self .db - .trait_data(deref_trait) + .trait_items(deref_trait) .method_by_name(&Name::new_symbol_root(sym::deref_mut.clone())) { break 'b deref_fn == f; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 131e98d729651..d0936185957f1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -772,7 +772,7 @@ impl InferenceContext<'_> { if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) { if let Some(deref_fn) = self .db - .trait_data(deref_trait) + .trait_items(deref_trait) .method_by_name(&Name::new_symbol_root(sym::deref.clone())) { // FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that @@ -930,7 +930,7 @@ impl InferenceContext<'_> { self.write_expr_adj(*base, adj); if let Some(func) = self .db - .trait_data(index_trait) + .trait_items(index_trait) .method_by_name(&Name::new_symbol_root(sym::index.clone())) { let subst = TyBuilder::subst_for_def(self.db, index_trait, None); @@ -1258,7 +1258,7 @@ impl InferenceContext<'_> { let Some(trait_) = fn_x.get_id(self.db, self.table.trait_env.krate) else { return; }; - let trait_data = self.db.trait_data(trait_); + let trait_data = self.db.trait_items(trait_); if let Some(func) = trait_data.method_by_name(&fn_x.method_name()) { let subst = TyBuilder::subst_for_def(self.db, trait_, None) .push(callee_ty.clone()) @@ -1426,7 +1426,7 @@ impl InferenceContext<'_> { let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| { let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?; - let func = self.db.trait_data(trait_id).method_by_name(&name)?; + let func = self.db.trait_items(trait_id).method_by_name(&name)?; Some((trait_id, func)) }); let (trait_, func) = match trait_func { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index d74a383f44ef4..96d84cad9394c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -134,7 +134,7 @@ impl InferenceContext<'_> { { if let Some(index_fn) = self .db - .trait_data(index_trait) + .trait_items(index_trait) .method_by_name(&Name::new_symbol_root(sym::index_mut.clone())) { *f = index_fn; @@ -201,7 +201,7 @@ impl InferenceContext<'_> { mutability = Mutability::Not; } else if let Some(deref_fn) = self .db - .trait_data(deref_trait) + .trait_items(deref_trait) .method_by_name(&Name::new_symbol_root(sym::deref_mut.clone())) { *f = deref_fn; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs index 6254bc12392b0..29f455a61b941 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs @@ -277,7 +277,7 @@ impl InferenceContext<'_> { ) -> Option<(ValueNs, Substitution)> { let trait_ = trait_ref.hir_trait_id(); let item = - self.db.trait_data(trait_).items.iter().map(|(_name, id)| *id).find_map(|item| { + self.db.trait_items(trait_).items.iter().map(|(_name, id)| *id).find_map(|item| { match item { AssocItemId::FunctionId(func) => { if segment.name == &self.db.function_data(func).name { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 8a8992cf372da..a9332a5a96374 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -801,7 +801,7 @@ impl<'a> InferenceTable<'a> { ] { let krate = self.trait_env.krate; let fn_trait = fn_trait_name.get_id(self.db, krate)?; - let trait_data = self.db.trait_data(fn_trait); + let trait_data = self.db.trait_items(fn_trait); let output_assoc_type = trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index f35298846a858..836319431dfb4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -906,7 +906,7 @@ pub fn callable_sig_from_fn_trait( let krate = trait_env.krate; let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?; let output_assoc_type = db - .trait_data(fn_once_trait) + .trait_items(fn_once_trait) .associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?; let mut table = InferenceTable::new(db, trait_env.clone()); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 29ab0251f8360..33e852aaee46c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -898,7 +898,7 @@ fn named_associated_type_shorthand_candidates( ) -> Option { let mut search = |t| { all_super_trait_refs(db, t, |t| { - let data = db.trait_data(t.hir_trait_id()); + let data = db.trait_items(t.hir_trait_id()); for (name, assoc_id) in &data.items { if let AssocItemId::TypeAliasId(alias) = assoc_id { @@ -1068,7 +1068,7 @@ pub(crate) fn generic_predicates_for_param_query( }; all_super_traits(db.upcast(), tr).iter().any(|tr| { - db.trait_data(*tr).items.iter().any(|(name, item)| { + db.trait_items(*tr).items.iter().any(|(name, item)| { matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name }) }) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs index a165932ddcc8c..a9e9e83e871ff 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs @@ -169,7 +169,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { self.skip_resolved_segment(); let segment = self.current_or_prev_segment; let found = - self.ctx.db.trait_data(trait_).associated_type_by_name(segment.name); + self.ctx.db.trait_items(trait_).associated_type_by_name(segment.name); match found { Some(associated_ty) => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index 50b0fce62f76e..bb3aaef20b76c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -8,8 +8,8 @@ use arrayvec::ArrayVec; use base_db::Crate; use chalk_ir::{cast::Cast, UniverseIndex, WithKind}; use hir_def::{ - data::{adt::StructFlags, ImplData, TraitFlags}, - nameres::DefMap, + data::{adt::StructFlags, TraitFlags}, + nameres::{assoc::ImplItems, DefMap}, AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleId, TraitId, }; @@ -325,7 +325,7 @@ impl InherentImpls { let self_ty = db.impl_self_ty(impl_id); let self_ty = self_ty.skip_binders(); - match is_inherent_impl_coherent(db, def_map, &data, self_ty) { + match is_inherent_impl_coherent(db, def_map, impl_id, self_ty) { true => { // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution) if let Some(fp) = TyFingerprint::for_inherent_impl(self_ty) { @@ -765,11 +765,10 @@ fn find_matching_impl( mut impls: impl Iterator, mut table: InferenceTable<'_>, actual_trait_ref: TraitRef, -) -> Option<(Arc, Substitution)> { +) -> Option<(Arc, Substitution)> { let db = table.db; impls.find_map(|impl_| { table.run_in_snapshot(|table| { - let impl_data = db.impl_data(impl_); let impl_substs = TyBuilder::subst_for_def(db, impl_, None).fill_with_inference_vars(table).build(); let trait_ref = db @@ -787,7 +786,7 @@ fn find_matching_impl( let goal = crate::Goal::all(Interner, wcs); table.try_obligation(goal.clone())?; table.register_obligation(goal); - Some((impl_data, table.resolve_completely(impl_substs))) + Some((db.impl_items(impl_), table.resolve_completely(impl_substs))) }) }) } @@ -795,7 +794,7 @@ fn find_matching_impl( fn is_inherent_impl_coherent( db: &dyn HirDatabase, def_map: &DefMap, - impl_data: &ImplData, + impl_id: ImplId, self_ty: &Ty, ) -> bool { let self_ty = self_ty.kind(Interner); @@ -848,9 +847,10 @@ fn is_inherent_impl_coherent( _ => false, }; + let items = db.impl_items(impl_id); rustc_has_incoherent_inherent_impls - && !impl_data.items.is_empty() - && impl_data.items.iter().all(|&(_, assoc)| match assoc { + && !items.items.is_empty() + && items.items.iter().all(|&(_, assoc)| match assoc { AssocItemId::FunctionId(it) => db.function_data(it).rustc_allow_incoherent_impl, AssocItemId::ConstId(it) => db.const_data(it).rustc_allow_incoherent_impl, AssocItemId::TypeAliasId(it) => db.type_alias_data(it).rustc_allow_incoherent_impl, @@ -1241,7 +1241,7 @@ fn iterate_trait_method_candidates( // trait, but if we find out it doesn't, we'll skip the rest of the // iteration let mut known_implemented = false; - for &(_, item) in data.items.iter() { + for &(_, item) in db.trait_items(t).items.iter() { // Don't pass a `visible_from_module` down to `is_valid_candidate`, // since only inherent methods should be included into visibility checking. let visible = @@ -1368,7 +1368,7 @@ fn iterate_inherent_methods( ) -> ControlFlow<()> { let db = table.db; for t in traits { - let data = db.trait_data(t); + let data = db.trait_items(t); for &(_, item) in data.items.iter() { // We don't pass `visible_from_module` as all trait items should be visible. let visible = match is_valid_trait_method_candidate( @@ -1401,7 +1401,7 @@ fn iterate_inherent_methods( callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, ) -> ControlFlow<()> { for &impl_id in impls.for_self_ty(self_ty) { - for &(ref item_name, item) in table.db.impl_data(impl_id).items.iter() { + for &(ref item_name, item) in table.db.impl_items(impl_id).items.iter() { let visible = match is_valid_impl_method_candidate( table, self_ty, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 597e6a3ef0bf1..97710aab06c76 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -661,19 +661,19 @@ impl Evaluator<'_> { .lang_item(crate_id, LangItem::Fn) .and_then(|x| x.as_trait()) .and_then(|x| { - db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call.clone())) + db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call.clone())) }), cached_fn_mut_trait_func: db .lang_item(crate_id, LangItem::FnMut) .and_then(|x| x.as_trait()) .and_then(|x| { - db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_mut.clone())) + db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut.clone())) }), cached_fn_once_trait_func: db .lang_item(crate_id, LangItem::FnOnce) .and_then(|x| x.as_trait()) .and_then(|x| { - db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_once.clone())) + db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once.clone())) }), }) } @@ -2818,7 +2818,9 @@ impl Evaluator<'_> { ) -> Result<()> { let Some(drop_fn) = (|| { let drop_trait = self.db.lang_item(self.crate_id, LangItem::Drop)?.as_trait()?; - self.db.trait_data(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop.clone())) + self.db + .trait_items(drop_trait) + .method_by_name(&Name::new_symbol_root(sym::drop.clone())) })() else { // in some tests we don't have drop trait in minicore, and // we can ignore drop in them. @@ -2928,7 +2930,7 @@ pub fn render_const_using_debug_impl( not_supported!("core::fmt::Debug not found"); }; let Some(debug_fmt_fn) = - db.trait_data(debug_trait).method_by_name(&Name::new_symbol_root(sym::fmt.clone())) + db.trait_items(debug_trait).method_by_name(&Name::new_symbol_root(sym::fmt.clone())) else { not_supported!("core::fmt::Debug::fmt not found"); }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 346dea82526fb..edd028cdeb26c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -1261,7 +1261,7 @@ impl Evaluator<'_> { if let Some(target) = self.db.lang_item(self.crate_id, LangItem::FnOnce) { if let Some(def) = target.as_trait().and_then(|it| { self.db - .trait_data(it) + .trait_items(it) .method_by_name(&Name::new_symbol_root(sym::call_once.clone())) }) { self.exec_fn_trait( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs index 420f2aaff46d6..7b0ee22d51fcf 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs @@ -195,7 +195,7 @@ impl MirLowerCtx<'_> { self.resolve_lang_item(LangItem::DerefMut)?.as_trait() { if let Some(deref_fn) = - self.db.trait_data(deref_trait).method_by_name( + self.db.trait_items(deref_trait).method_by_name( &Name::new_symbol_root(sym::deref_mut.clone()), ) { @@ -353,7 +353,7 @@ impl MirLowerCtx<'_> { .ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?; let deref_fn = self .db - .trait_data(deref_trait) + .trait_items(deref_trait) .method_by_name(&trait_method_name) .ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?; let deref_fn_op = Operand::const_zst( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index cdb9e9edf8831..9ad07922fac71 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -439,7 +439,7 @@ pub(crate) fn visit_module( ) { visit_scope(db, crate_def_map, &crate_def_map[module_id].scope, cb); for impl_id in crate_def_map[module_id].scope.impls() { - let impl_data = db.impl_data(impl_id); + let impl_data = db.impl_items(impl_id); for &(_, item) in impl_data.items.iter() { match item { AssocItemId::FunctionId(it) => { @@ -488,7 +488,7 @@ pub(crate) fn visit_module( }); } ModuleDefId::TraitId(it) => { - let trait_data = db.trait_data(it); + let trait_data = db.trait_items(it); for &(_, item) in trait_data.items.iter() { match item { AssocItemId::FunctionId(it) => cb(it.into()), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index b90f4e4d7faaa..cbb78ef40d84e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -226,7 +226,7 @@ pub(super) fn associated_type_by_name_including_super_traits( name: &Name, ) -> Option<(TraitRef, TypeAliasId)> { all_super_trait_refs(db, trait_ref, |t| { - let assoc_type = db.trait_data(t.hir_trait_id()).associated_type_by_name(name)?; + let assoc_type = db.trait_items(t.hir_trait_id()).associated_type_by_name(name)?; Some((t, assoc_type)) }) } diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index 4351a34e82282..1c88e79933fba 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -194,7 +194,7 @@ fn resolve_assoc_or_field( // Doc paths in this context may only resolve to an item of this trait // (i.e. no items of its supertraits), so we need to handle them here // independently of others. - return db.trait_data(id).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| { + return db.trait_items(id).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| { let def = match *assoc_id { AssocItemId::FunctionId(it) => ModuleDef::Function(it.into()), AssocItemId::ConstId(it) => ModuleDef::Const(it.into()), diff --git a/src/tools/rust-analyzer/crates/hir/src/db.rs b/src/tools/rust-analyzer/crates/hir/src/db.rs index 9e8e87ecff001..64d97b3f2a238 100644 --- a/src/tools/rust-analyzer/crates/hir/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir/src/db.rs @@ -11,7 +11,7 @@ pub use hir_def::db::DefDatabase; // ExpandProcAttrMacrosQuery, ExprScopesQuery, ExternCrateDeclDataQuery, FieldVisibilitiesQuery, // FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery, FileItemTreeWithSourceMapQuery, // FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery, -// GenericParamsWithSourceMapQuery, ImplDataWithDiagnosticsQuery, ImportMapQuery, +// GenericParamsWithSourceMapQuery, ImplItemsWithDiagnosticsQuery, ImportMapQuery, // IncludeMacroInvocQuery, InternAnonymousConstQuery, InternBlockQuery, InternConstQuery, // InternDatabase, InternDatabaseStorage, InternEnumQuery, InternExternBlockQuery, // InternExternCrateQuery, InternFunctionQuery, InternImplQuery, InternInTypeConstQuery, @@ -19,7 +19,7 @@ pub use hir_def::db::DefDatabase; // InternStructQuery, InternTraitAliasQuery, InternTraitQuery, InternTypeAliasQuery, // InternUnionQuery, InternUseQuery, LangItemQuery, Macro2DataQuery, MacroDefQuery, // MacroRulesDataQuery, NotableTraitsInDepsQuery, ProcMacroDataQuery, StaticDataQuery, -// StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitDataWithDiagnosticsQuery, +// StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitItemsWithDiagnosticsQuery, // TypeAliasDataQuery, UnionDataWithDiagnosticsQuery, // }; pub use hir_expand::db::ExpandDatabase; diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 5da2b5ed09361..5cc330fb38f3b 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -636,7 +636,7 @@ impl Module { acc.extend(def.diagnostics(db, style_lints)) } ModuleDef::Trait(t) => { - for diag in db.trait_data_with_diagnostics(t.id).1.iter() { + for diag in db.trait_items_with_diagnostics(t.id).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } @@ -743,7 +743,7 @@ impl Module { let ast_id_map = db.ast_id_map(file_id); - for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() { + for diag in db.impl_items_with_diagnostics(impl_def.id).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } @@ -801,13 +801,13 @@ impl Module { // Negative impls can't have items, don't emit missing items diagnostic for them if let (false, Some(trait_)) = (impl_is_negative, trait_) { - let items = &db.trait_data(trait_.into()).items; + let items = &db.trait_items(trait_.into()).items; let required_items = items.iter().filter(|&(_, assoc)| match *assoc { AssocItemId::FunctionId(it) => !db.function_data(it).has_body(), AssocItemId::ConstId(id) => !db.const_data(id).has_body, AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(), }); - impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().cloned()); + impl_assoc_items_scratch.extend(db.impl_items(impl_def.id).items.iter().cloned()); let redundant = impl_assoc_items_scratch .iter() @@ -863,7 +863,7 @@ impl Module { source_map, ); - for &(_, item) in db.impl_data(impl_def.id).items.iter() { + for &(_, item) in db.impl_items(impl_def.id).items.iter() { AssocItem::from(item).diagnostics(db, acc, style_lints); } } @@ -2868,16 +2868,15 @@ impl Trait { } pub fn function(self, db: &dyn HirDatabase, name: impl PartialEq) -> Option { - db.trait_data(self.id).items.iter().find(|(n, _)| name == *n).and_then( - |&(_, it)| match it { - AssocItemId::FunctionId(id) => Some(Function { id }), - _ => None, - }, - ) + db.trait_items(self.id).items.iter().find(|(n, _)| name == *n).and_then(|&(_, it)| match it + { + AssocItemId::FunctionId(id) => Some(Function { id }), + _ => None, + }) } pub fn items(self, db: &dyn HirDatabase) -> Vec { - db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect() + db.trait_items(self.id).items.iter().map(|(_name, it)| (*it).into()).collect() } pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec { @@ -2921,7 +2920,7 @@ impl Trait { } fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId, MacroCallId)]> { - db.trait_data(self.id) + db.trait_items(self.id) .macro_calls .as_ref() .map(|it| it.as_ref().clone().into_boxed_slice()) @@ -4428,7 +4427,7 @@ impl Impl { } pub fn items(self, db: &dyn HirDatabase) -> Vec { - db.impl_data(self.id).items.iter().map(|&(_, it)| it.into()).collect() + db.impl_items(self.id).items.iter().map(|&(_, it)| it.into()).collect() } pub fn is_negative(self, db: &dyn HirDatabase) -> bool { @@ -4478,7 +4477,7 @@ impl Impl { } fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId, MacroCallId)]> { - db.impl_data(self.id) + db.impl_items(self.id) .macro_calls .as_ref() .map(|it| it.as_ref().clone().into_boxed_slice()) @@ -4959,7 +4958,7 @@ impl Type { } let output_assoc_type = db - .trait_data(trait_) + .trait_items(trait_) .associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?; self.normalize_trait_assoc_type(db, &[], output_assoc_type.into()) } @@ -4975,7 +4974,7 @@ impl Type { pub fn iterator_item(self, db: &dyn HirDatabase) -> Option { let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?; let iterator_item = db - .trait_data(iterator_trait) + .trait_items(iterator_trait) .associated_type_by_name(&Name::new_symbol_root(sym::Item.clone()))?; self.normalize_trait_assoc_type(db, &[], iterator_item.into()) } @@ -5007,7 +5006,7 @@ impl Type { } let into_iter_assoc_type = db - .trait_data(trait_) + .trait_items(trait_) .associated_type_by_name(&Name::new_symbol_root(sym::IntoIter.clone()))?; self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into()) } @@ -5301,7 +5300,7 @@ impl Type { let impls = db.inherent_impls_in_crate(krate); for impl_def in impls.for_self_ty(&self.ty) { - for &(_, item) in db.impl_data(*impl_def).items.iter() { + for &(_, item) in db.impl_items(*impl_def).items.iter() { if callback(item) { return; } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index da9bb8b15c8c0..556b21124dd5c 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -34,7 +34,7 @@ pub(crate) trait ChildBySource { impl ChildBySource for TraitId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { - let data = db.trait_data(*self); + let data = db.trait_items(*self); data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( |(ast_id, call_id)| { @@ -49,7 +49,7 @@ impl ChildBySource for TraitId { impl ChildBySource for ImplId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { - let data = db.impl_data(*self); + let data = db.impl_items(*self); // FIXME: Macro calls data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( |(ast_id, call_id)| { diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index aa0eac9478a22..e390fb0b935ff 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -1291,7 +1291,7 @@ impl SourceAnalyzer { method_name: &Name, ) -> Option<(TraitId, FunctionId)> { let trait_id = db.lang_item(self.resolver.krate(), lang_trait)?.as_trait()?; - let fn_id = db.trait_data(trait_id).method_by_name(method_name)?; + let fn_id = db.trait_items(trait_id).method_by_name(method_name)?; Some((trait_id, fn_id)) } @@ -1453,7 +1453,7 @@ fn resolve_hir_path_( // within the trait's associated types. if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) { if let Some(type_alias_id) = - db.trait_data(trait_id).associated_type_by_name(unresolved.name) + db.trait_items(trait_id).associated_type_by_name(unresolved.name) { return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); } @@ -1586,7 +1586,7 @@ fn resolve_hir_path_qualifier( // within the trait's associated types. if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) { if let Some(type_alias_id) = - db.trait_data(trait_id).associated_type_by_name(unresolved.name) + db.trait_items(trait_id).associated_type_by_name(unresolved.name) { return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); } diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index 2a6c15207a337..853df7ee2d88a 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -313,7 +313,7 @@ impl<'a> SymbolCollector<'a> { .to_smolstr(), ); self.with_container_name(impl_name, |s| { - for &(ref name, assoc_item_id) in &impl_data.items { + for &(ref name, assoc_item_id) in &self.db.impl_items(impl_id).items { s.push_assoc_item(assoc_item_id, name) } }) @@ -322,7 +322,7 @@ impl<'a> SymbolCollector<'a> { fn collect_from_trait(&mut self, trait_id: TraitId) { let trait_data = self.db.trait_data(trait_id); self.with_container_name(Some(trait_data.name.as_str().into()), |s| { - for &(ref name, assoc_item_id) in &trait_data.items { + for &(ref name, assoc_item_id) in &self.db.trait_items(trait_id).items { s.push_assoc_item(assoc_item_id, name); } }); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs index 4c8940db95cc7..6b08ada34b609 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs @@ -162,7 +162,7 @@ impl RootDatabase { // hir::db::FunctionVisibilityQuery // hir::db::GenericParamsQuery // hir::db::GenericParamsWithSourceMapQuery - // hir::db::ImplDataWithDiagnosticsQuery + // hir::db::ImplItemsWithDiagnosticsQuery // hir::db::ImportMapQuery // hir::db::IncludeMacroInvocQuery // hir::db::InternAnonymousConstQuery @@ -193,7 +193,7 @@ impl RootDatabase { // hir::db::StaticDataQuery // hir::db::StructDataWithDiagnosticsQuery // hir::db::TraitAliasDataQuery - // hir::db::TraitDataWithDiagnosticsQuery + // hir::db::TraitItemsWithDiagnosticsQuery // hir::db::TypeAliasDataQuery // hir::db::UnionDataWithDiagnosticsQuery From 1835bc2a874b6f55af759dbf7361370a65294b62 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 26 Feb 2025 07:55:00 +0100 Subject: [PATCH 0119/2248] Move attribute parsing out of data module --- .../rust-analyzer/crates/hir-def/src/attr.rs | 125 ++++++++++++++++++ .../rust-analyzer/crates/hir-def/src/data.rs | 33 +---- .../crates/hir-def/src/data/adt.rs | 94 +------------ 3 files changed, 128 insertions(+), 124 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 579ea12e6ae03..030d064584cd6 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -12,6 +12,7 @@ use hir_expand::{ use intern::{sym, Symbol}; use la_arena::{ArenaMap, Idx, RawIdx}; use mbe::DelimiterKind; +use rustc_abi::ReprOptions; use syntax::{ ast::{self, HasAttrs}, AstPtr, @@ -221,6 +222,130 @@ impl Attrs { pub fn is_unstable(&self) -> bool { self.by_key(&sym::unstable).exists() } + + pub fn rustc_legacy_const_generics(&self) -> Option>> { + self.by_key(&sym::rustc_legacy_const_generics) + .tt_values() + .next() + .map(parse_rustc_legacy_const_generics) + .filter(|it| !it.is_empty()) + .map(Box::new) + } + + pub fn repr(&self) -> Option { + self.by_key(&sym::repr).tt_values().find_map(parse_repr_tt) + } +} + +fn parse_rustc_legacy_const_generics(tt: &crate::tt::TopSubtree) -> Box<[u32]> { + let mut indices = Vec::new(); + let mut iter = tt.iter(); + while let (Some(first), second) = (iter.next(), iter.next()) { + match first { + TtElement::Leaf(tt::Leaf::Literal(lit)) => match lit.symbol.as_str().parse() { + Ok(index) => indices.push(index), + Err(_) => break, + }, + _ => break, + } + + if let Some(comma) = second { + match comma { + TtElement::Leaf(tt::Leaf::Punct(punct)) if punct.char == ',' => {} + _ => break, + } + } + } + + indices.into_boxed_slice() +} + +fn parse_repr_tt(tt: &crate::tt::TopSubtree) -> Option { + use crate::builtin_type::{BuiltinInt, BuiltinUint}; + use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; + + match tt.top_subtree().delimiter { + tt::Delimiter { kind: DelimiterKind::Parenthesis, .. } => {} + _ => return None, + } + + let mut flags = ReprFlags::empty(); + let mut int = None; + let mut max_align: Option = None; + let mut min_pack: Option = None; + + let mut tts = tt.iter(); + while let Some(tt) = tts.next() { + if let TtElement::Leaf(tt::Leaf::Ident(ident)) = tt { + flags.insert(match &ident.sym { + s if *s == sym::packed => { + let pack = if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { + tts.next(); + if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() { + lit.symbol.as_str().parse().unwrap_or_default() + } else { + 0 + } + } else { + 0 + }; + let pack = Align::from_bytes(pack).unwrap_or(Align::ONE); + min_pack = + Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack }); + ReprFlags::empty() + } + s if *s == sym::align => { + if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { + tts.next(); + if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() { + if let Ok(align) = lit.symbol.as_str().parse() { + let align = Align::from_bytes(align).ok(); + max_align = max_align.max(align); + } + } + } + ReprFlags::empty() + } + s if *s == sym::C => ReprFlags::IS_C, + s if *s == sym::transparent => ReprFlags::IS_TRANSPARENT, + s if *s == sym::simd => ReprFlags::IS_SIMD, + repr => { + if let Some(builtin) = BuiltinInt::from_suffix_sym(repr) + .map(Either::Left) + .or_else(|| BuiltinUint::from_suffix_sym(repr).map(Either::Right)) + { + int = Some(match builtin { + Either::Left(bi) => match bi { + BuiltinInt::Isize => IntegerType::Pointer(true), + BuiltinInt::I8 => IntegerType::Fixed(Integer::I8, true), + BuiltinInt::I16 => IntegerType::Fixed(Integer::I16, true), + BuiltinInt::I32 => IntegerType::Fixed(Integer::I32, true), + BuiltinInt::I64 => IntegerType::Fixed(Integer::I64, true), + BuiltinInt::I128 => IntegerType::Fixed(Integer::I128, true), + }, + Either::Right(bu) => match bu { + BuiltinUint::Usize => IntegerType::Pointer(false), + BuiltinUint::U8 => IntegerType::Fixed(Integer::I8, false), + BuiltinUint::U16 => IntegerType::Fixed(Integer::I16, false), + BuiltinUint::U32 => IntegerType::Fixed(Integer::I32, false), + BuiltinUint::U64 => IntegerType::Fixed(Integer::I64, false), + BuiltinUint::U128 => IntegerType::Fixed(Integer::I128, false), + }, + }); + } + ReprFlags::empty() + } + }) + } + } + + Some(ReprOptions { + int, + align: max_align, + pack: min_pack, + flags, + field_shuffle_seed: rustc_hashes::Hash64::ZERO, + }) } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index 8a1f07c92efff..1a6bed6cabbdd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -7,7 +7,6 @@ use hir_expand::name::Name; use intern::{sym, Symbol}; use la_arena::{Idx, RawIdx}; use triomphe::Arc; -use tt::iter::TtElement; use crate::{ db::DefDatabase, @@ -73,13 +72,6 @@ impl FunctionData { } let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); - let legacy_const_generics_indices = attrs - .by_key(&sym::rustc_legacy_const_generics) - .tt_values() - .next() - .map(parse_rustc_legacy_const_generics) - .filter(|it| !it.is_empty()) - .map(Box::new); let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists(); if flags.contains(FnFlags::HAS_UNSAFE_KW) && attrs.by_key(&sym::rustc_deprecated_safe_2024).exists() @@ -106,7 +98,7 @@ impl FunctionData { ret_type: func.ret_type, visibility, abi: func.abi.clone(), - legacy_const_generics_indices, + legacy_const_generics_indices: attrs.rustc_legacy_const_generics(), types_map: func.types_map.clone(), flags, rustc_allow_incoherent_impl, @@ -156,29 +148,6 @@ impl FunctionData { } } -fn parse_rustc_legacy_const_generics(tt: &crate::tt::TopSubtree) -> Box<[u32]> { - let mut indices = Vec::new(); - let mut iter = tt.iter(); - while let (Some(first), second) = (iter.next(), iter.next()) { - match first { - TtElement::Leaf(tt::Leaf::Literal(lit)) => match lit.symbol.as_str().parse() { - Ok(index) => indices.push(index), - Err(_) => break, - }, - _ => break, - } - - if let Some(comma) = second { - match comma { - TtElement::Leaf(tt::Leaf::Punct(punct)) if punct.char == ',' => {} - _ => break, - } - } - } - - indices.into_boxed_slice() -} - #[derive(Debug, Clone, PartialEq, Eq)] pub struct TypeAliasData { pub name: Name, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index bf8f5024c2d6a..161b205c80941 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -3,18 +3,14 @@ use base_db::Crate; use bitflags::bitflags; use cfg::CfgOptions; -use either::Either; use hir_expand::name::Name; use intern::sym; use la_arena::Arena; -use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; -use rustc_hashes::Hash64; +use rustc_abi::{IntegerType, ReprOptions}; use triomphe::Arc; -use tt::iter::TtElement; use crate::{ - builtin_type::{BuiltinInt, BuiltinUint}, db::DefDatabase, hir::Expr, item_tree::{ @@ -22,7 +18,6 @@ use crate::{ }, lang_item::LangItem, nameres::diagnostics::{DefDiagnostic, DefDiagnostics}, - tt::{Delimiter, DelimiterKind, Leaf, TopSubtree}, type_ref::{TypeRefId, TypesMap}, visibility::RawVisibility, EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId, @@ -94,92 +89,7 @@ fn repr_from_value( item_tree: &ItemTree, of: AttrOwner, ) -> Option { - item_tree.attrs(db, krate, of).by_key(&sym::repr).tt_values().find_map(parse_repr_tt) -} - -fn parse_repr_tt(tt: &TopSubtree) -> Option { - match tt.top_subtree().delimiter { - Delimiter { kind: DelimiterKind::Parenthesis, .. } => {} - _ => return None, - } - - let mut flags = ReprFlags::empty(); - let mut int = None; - let mut max_align: Option = None; - let mut min_pack: Option = None; - - let mut tts = tt.iter(); - while let Some(tt) = tts.next() { - if let TtElement::Leaf(Leaf::Ident(ident)) = tt { - flags.insert(match &ident.sym { - s if *s == sym::packed => { - let pack = if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { - tts.next(); - if let Some(TtElement::Leaf(Leaf::Literal(lit))) = tt_iter.next() { - lit.symbol.as_str().parse().unwrap_or_default() - } else { - 0 - } - } else { - 0 - }; - let pack = Align::from_bytes(pack).unwrap_or(Align::ONE); - min_pack = - Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack }); - ReprFlags::empty() - } - s if *s == sym::align => { - if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { - tts.next(); - if let Some(TtElement::Leaf(Leaf::Literal(lit))) = tt_iter.next() { - if let Ok(align) = lit.symbol.as_str().parse() { - let align = Align::from_bytes(align).ok(); - max_align = max_align.max(align); - } - } - } - ReprFlags::empty() - } - s if *s == sym::C => ReprFlags::IS_C, - s if *s == sym::transparent => ReprFlags::IS_TRANSPARENT, - s if *s == sym::simd => ReprFlags::IS_SIMD, - repr => { - if let Some(builtin) = BuiltinInt::from_suffix_sym(repr) - .map(Either::Left) - .or_else(|| BuiltinUint::from_suffix_sym(repr).map(Either::Right)) - { - int = Some(match builtin { - Either::Left(bi) => match bi { - BuiltinInt::Isize => IntegerType::Pointer(true), - BuiltinInt::I8 => IntegerType::Fixed(Integer::I8, true), - BuiltinInt::I16 => IntegerType::Fixed(Integer::I16, true), - BuiltinInt::I32 => IntegerType::Fixed(Integer::I32, true), - BuiltinInt::I64 => IntegerType::Fixed(Integer::I64, true), - BuiltinInt::I128 => IntegerType::Fixed(Integer::I128, true), - }, - Either::Right(bu) => match bu { - BuiltinUint::Usize => IntegerType::Pointer(false), - BuiltinUint::U8 => IntegerType::Fixed(Integer::I8, false), - BuiltinUint::U16 => IntegerType::Fixed(Integer::I16, false), - BuiltinUint::U32 => IntegerType::Fixed(Integer::I32, false), - BuiltinUint::U64 => IntegerType::Fixed(Integer::I64, false), - BuiltinUint::U128 => IntegerType::Fixed(Integer::I128, false), - }, - }); - } - ReprFlags::empty() - } - }) - } - } - - Some(ReprOptions { - int, - align: max_align, - pack: min_pack, - flags, - field_shuffle_seed: Hash64::ZERO, - }) + item_tree.attrs(db, krate, of).repr() } impl StructData { From 176981ef495ebd9117f15a1520c470661c4d10da Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 26 Feb 2025 08:02:53 +0100 Subject: [PATCH 0120/2248] Split enum variants out of `enum_data` query --- .../crates/hir-def/src/data/adt.rs | 60 ++++++++++++------- .../rust-analyzer/crates/hir-def/src/db.rs | 5 +- .../crates/hir-ty/src/chalk_db.rs | 2 +- .../crates/hir-ty/src/consteval.rs | 2 +- .../hir-ty/src/diagnostics/decl_check.rs | 2 +- .../crates/hir-ty/src/diagnostics/expr.rs | 2 +- .../diagnostics/match_check/pat_analysis.rs | 4 +- .../rust-analyzer/crates/hir-ty/src/drop.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/infer.rs | 4 +- .../crates/hir-ty/src/infer/cast.rs | 2 +- .../crates/hir-ty/src/infer/closure.rs | 2 +- .../crates/hir-ty/src/infer/path.rs | 2 +- .../crates/hir-ty/src/inhabitedness.rs | 2 +- .../crates/hir-ty/src/layout/adt.rs | 8 +-- .../crates/hir-ty/src/mir/eval.rs | 5 +- .../rust-analyzer/crates/hir-ty/src/tests.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/utils.rs | 6 +- .../crates/hir-ty/src/variance.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 6 +- .../hir/src/semantics/child_by_source.rs | 2 +- .../ide-completion/src/completions/pattern.rs | 4 +- 21 files changed, 74 insertions(+), 52 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index 161b205c80941..c8429d8b6897f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -56,12 +56,16 @@ bitflags! { #[derive(Debug, Clone, PartialEq, Eq)] pub struct EnumData { pub name: Name, - pub variants: Box<[(EnumVariantId, Name)]>, pub repr: Option, pub visibility: RawVisibility, pub rustc_has_incoherent_inherent_impls: bool, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct EnumVariants { + pub variants: Box<[(EnumVariantId, Name)]>, +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct EnumVariantData { pub name: Name, @@ -203,28 +207,16 @@ impl StructData { } } -impl EnumData { - pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc { +impl EnumVariants { + pub(crate) fn enum_variants_query(db: &dyn DefDatabase, e: EnumId) -> Arc { let loc = e.lookup(db); - let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); - let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); - let rustc_has_incoherent_inherent_impls = item_tree - .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()) - .by_key(&sym::rustc_has_incoherent_inherent_impls) - .exists(); - - let enum_ = &item_tree[loc.id.value]; - Arc::new(EnumData { - name: enum_.name.clone(), + Arc::new(EnumVariants { variants: loc.container.def_map(db).enum_definitions[&e] .iter() .map(|&id| (id, item_tree[id.lookup(db).id.value].name.clone())) .collect(), - repr, - visibility: item_tree[enum_.visibility].clone(), - rustc_has_incoherent_inherent_impls, }) } @@ -233,13 +225,6 @@ impl EnumData { Some(id) } - pub fn variant_body_type(&self) -> IntegerType { - match self.repr { - Some(ReprOptions { int: Some(builtin), .. }) => builtin, - _ => IntegerType::Pointer(true), - } - } - // [Adopted from rustc](https://github.com/rust-lang/rust/blob/bd53aa3bf7a24a70d763182303bd75e5fc51a9af/compiler/rustc_middle/src/ty/adt.rs#L446-L448) pub fn is_payload_free(&self, db: &dyn DefDatabase) -> bool { self.variants.iter().all(|(v, _)| { @@ -262,6 +247,35 @@ impl EnumData { } } +impl EnumData { + pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc { + let loc = e.lookup(db); + let krate = loc.container.krate; + let item_tree = loc.id.item_tree(db); + let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); + let rustc_has_incoherent_inherent_impls = item_tree + .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()) + .by_key(&sym::rustc_has_incoherent_inherent_impls) + .exists(); + + let enum_ = &item_tree[loc.id.value]; + + Arc::new(EnumData { + name: enum_.name.clone(), + repr, + visibility: item_tree[enum_.visibility].clone(), + rustc_has_incoherent_inherent_impls, + }) + } + + pub fn variant_body_type(&self) -> IntegerType { + match self.repr { + Some(ReprOptions { int: Some(builtin), .. }) => builtin, + _ => IntegerType::Pointer(true), + } + } +} + impl EnumVariantData { #[inline] pub(crate) fn enum_variant_data_query( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index ff33056538071..bc9fc8e079306 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -11,7 +11,7 @@ use triomphe::Arc; use crate::{ attr::{Attrs, AttrsWithOwner}, data::{ - adt::{EnumData, EnumVariantData, StructData, VariantData}, + adt::{EnumData, EnumVariantData, EnumVariants, StructData, VariantData}, ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData, ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData, }, @@ -167,6 +167,9 @@ pub trait DefDatabase: #[salsa::invoke_actual(EnumData::enum_data_query)] fn enum_data(&self, e: EnumId) -> Arc; + #[salsa::invoke_actual(EnumVariants::enum_variants_query)] + fn enum_variants(&self, e: EnumId) -> Arc; + #[salsa::transparent] #[salsa::invoke_actual(EnumVariantData::enum_variant_data_query)] fn enum_variant_data(&self, id: EnumVariantId) -> Arc; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index e5751a394dae5..ac4d1babd62b4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -801,7 +801,7 @@ pub(crate) fn adt_datum_query( } hir_def::AdtId::EnumId(id) => { let variants = db - .enum_data(id) + .enum_variants(id) .variants .iter() .map(|&(variant_id, _)| variant_id_to_fields(variant_id.into())) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index 525672bc39951..ec8f9b7c31186 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -309,7 +309,7 @@ pub(crate) fn const_eval_discriminant_variant( let value = match prev_idx { Some(prev_idx) => { 1 + db.const_eval_discriminant( - db.enum_data(loc.parent).variants[prev_idx as usize].0, + db.enum_variants(loc.parent).variants[prev_idx as usize].0, )? } _ => 0, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index a0b1fe32ce52d..0b21ae7ade377 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -394,7 +394,7 @@ impl<'a> DeclValidator<'a> { /// Check incorrect names for enum variants. fn validate_enum_variants(&mut self, enum_id: EnumId) { - let data = self.db.enum_data(enum_id); + let data = self.db.enum_variants(enum_id); for (variant_id, _) in data.variants.iter() { self.validate_enum_variant_fields(*variant_id); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 1035651692ec8..6096439565cba 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -642,7 +642,7 @@ fn missing_match_arms<'p>( } let non_empty_enum = match scrut_ty.as_adt() { - Some((AdtId::EnumId(e), _)) => !cx.db.enum_data(e).variants.is_empty(), + Some((AdtId::EnumId(e), _)) => !cx.db.enum_variants(e).variants.is_empty(), _ => false, }; let display_target = DisplayTarget::from_crate(cx.db, krate); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index 91eb59fb3140f..b7f8a0c610c54 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -49,7 +49,7 @@ impl EnumVariantContiguousIndex { } fn to_enum_variant_id(self, db: &dyn HirDatabase, eid: EnumId) -> EnumVariantId { - db.enum_data(eid).variants[self.0].0 + db.enum_variants(eid).variants[self.0].0 } } @@ -449,7 +449,7 @@ impl PatCx for MatchCheckCtx<'_> { TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(), TyKind::Array(..) | TyKind::Slice(..) => unhandled(), &TyKind::Adt(AdtId(adt @ hir_def::AdtId::EnumId(enum_id)), ref subst) => { - let enum_data = cx.db.enum_data(enum_id); + let enum_data = cx.db.enum_variants(enum_id); let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive(adt); if enum_data.variants.is_empty() && !is_declared_nonexhaustive { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs index 4ad16cf8bcf7e..ab17f86b5b2cb 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs @@ -72,7 +72,7 @@ pub(crate) fn has_drop_glue(db: &dyn HirDatabase, ty: Ty, env: Arc DropGlue::None, AdtId::EnumId(id) => db - .enum_data(id) + .enum_variants(id) .variants .iter() .map(|&(variant, _)| { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 9a4b7af85d8f9..ecadfccf00299 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -1587,7 +1587,7 @@ impl<'a> InferenceContext<'a> { // If we can resolve to an enum variant, it takes priority over associated type // of the same name. if let Some((AdtId::EnumId(id), _)) = ty.as_adt() { - let enum_data = self.db.enum_data(id); + let enum_data = self.db.enum_variants(id); if let Some(variant) = enum_data.variant(current_segment.name) { return if remaining_segments.len() == 1 { (ty, Some(variant.into())) @@ -1701,7 +1701,7 @@ impl<'a> InferenceContext<'a> { let segment = path.segments().last().unwrap(); // this could be an enum variant or associated type if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { - let enum_data = self.db.enum_data(enum_id); + let enum_data = self.db.enum_variants(enum_id); if let Some(variant) = enum_data.variant(segment) { return (ty, Some(variant.into())); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs index eb193686e967f..6c0e0b0273761 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs @@ -43,7 +43,7 @@ impl CastTy { let (AdtId::EnumId(id), _) = t.as_adt()? else { return None; }; - let enum_data = table.db.enum_data(id); + let enum_data = table.db.enum_variants(id); if enum_data.is_payload_free(table.db.upcast()) { Some(Self::Int(Int::CEnum)) } else { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index ef02762c80a53..6c50f056c18af 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -963,7 +963,7 @@ impl InferenceContext<'_> { if let Some(variant) = self.result.variant_resolution_for_pat(p) { let adt = variant.adt_id(self.db.upcast()); let is_multivariant = match adt { - hir_def::AdtId::EnumId(e) => self.db.enum_data(e).variants.len() != 1, + hir_def::AdtId::EnumId(e) => self.db.enum_variants(e).variants.len() != 1, _ => false, }; if is_multivariant { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs index 29f455a61b941..8ff0cf308224c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs @@ -398,7 +398,7 @@ impl InferenceContext<'_> { Some((AdtId::EnumId(e), subst)) => (e, subst), _ => return None, }; - let enum_data = self.db.enum_data(enum_id); + let enum_data = self.db.enum_variants(enum_id); let variant = enum_data.variant(name)?; self.write_variant_resolution(id, variant.into()); Some((ValueNs::EnumVariantId(variant), subst.clone())) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs index d6039c548b6f5..800ba0d454490 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs @@ -98,7 +98,7 @@ impl UninhabitedFrom<'_> { AdtId::UnionId(_) => CONTINUE_OPAQUELY_INHABITED, AdtId::StructId(s) => self.visit_variant(s.into(), subst), AdtId::EnumId(e) => { - let enum_data = self.db.enum_data(e); + let enum_data = self.db.enum_variants(e); for &(variant, _) in enum_data.variants.iter() { let variant_inhabitedness = self.visit_variant(variant.into(), subst); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs index ab9c07779c07a..40a1d4e6707ab 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs @@ -54,13 +54,13 @@ pub fn layout_of_adt_query( (r, data.repr.unwrap_or_default()) } AdtId::EnumId(e) => { - let data = db.enum_data(e); - let r = data + let variants = db.enum_variants(e); + let r = variants .variants .iter() .map(|&(v, _)| handle_variant(v.into(), &db.enum_variant_data(v).variant_data)) .collect::, _>>()?; - (r, data.repr.unwrap_or_default()) + (r, db.enum_data(e).repr.unwrap_or_default()) } }; let variants = variants @@ -80,7 +80,7 @@ pub fn layout_of_adt_query( |min, max| repr_discr(dl, &repr, min, max).unwrap_or((Integer::I8, false)), variants.iter_enumerated().filter_map(|(id, _)| { let AdtId::EnumId(e) = def else { return None }; - let d = db.const_eval_discriminant(db.enum_data(e).variants[id.0].0).ok()?; + let d = db.const_eval_discriminant(db.enum_variants(e).variants[id.0].0).ok()?; Some((id, d)) }), // FIXME: The current code for niche-filling relies on variant indices diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 97710aab06c76..25aa2606558c1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -1641,7 +1641,8 @@ impl Evaluator<'_> { match &layout.variants { Variants::Empty => unreachable!(), Variants::Single { index } => { - let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?; + let r = + self.const_eval_discriminant(self.db.enum_variants(e).variants[index.0].0)?; Ok(r) } Variants::Multiple { tag, tag_encoding, variants, .. } => { @@ -1666,7 +1667,7 @@ impl Evaluator<'_> { .unwrap_or(*untagged_variant) .0; let result = - self.const_eval_discriminant(self.db.enum_data(e).variants[idx].0)?; + self.const_eval_discriminant(self.db.enum_variants(e).variants[idx].0)?; Ok(result) } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index 9ad07922fac71..13d74264c560d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -481,7 +481,7 @@ pub(crate) fn visit_module( visit_body(db, &body, cb); } ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => { - db.enum_data(it).variants.iter().for_each(|&(it, _)| { + db.enum_variants(it).variants.iter().for_each(|&(it, _)| { let body = db.body(it.into()); cb(it.into()); visit_body(db, &body, cb); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index cbb78ef40d84e..3bd04b21b285d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -369,7 +369,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( let (var_id, var_layout) = match &layout.variants { hir_def::layout::Variants::Empty => unreachable!(), hir_def::layout::Variants::Single { index } => { - (db.enum_data(e).variants[index.0].0, layout) + (db.enum_variants(e).variants[index.0].0, layout) } hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => { let size = tag.size(target_data_layout).bytes_usize(); @@ -379,7 +379,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( TagEncoding::Direct => { let (var_idx, layout) = variants.iter_enumerated().find_map(|(var_idx, v)| { - let def = db.enum_data(e).variants[var_idx.0].0; + let def = db.enum_variants(e).variants[var_idx.0].0; (db.const_eval_discriminant(def) == Ok(tag)).then_some((def, v)) })?; (var_idx, layout) @@ -392,7 +392,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( .filter(|x| x != untagged_variant) .nth(candidate_tag) .unwrap_or(*untagged_variant); - (db.enum_data(e).variants[variant.0].0, &variants[variant]) + (db.enum_variants(e).variants[variant.0].0, &variants[variant]) } } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index 425196d92f79a..ab3d098908893 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -206,7 +206,7 @@ impl Context<'_> { AdtId::StructId(s) => add_constraints_from_variant(VariantId::StructId(s)), AdtId::UnionId(u) => add_constraints_from_variant(VariantId::UnionId(u)), AdtId::EnumId(e) => { - db.enum_data(e).variants.iter().for_each(|&(variant, _)| { + db.enum_variants(e).variants.iter().for_each(|&(variant, _)| { add_constraints_from_variant(VariantId::EnumVariantId(variant)) }); } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 5cc330fb38f3b..f78b7a5c435cb 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -1519,7 +1519,11 @@ impl Enum { } pub fn variants(self, db: &dyn HirDatabase) -> Vec { - db.enum_data(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect() + db.enum_variants(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect() + } + + pub fn num_variants(self, db: &dyn HirDatabase) -> usize { + db.enum_variants(self.id).variants.len() } pub fn repr(self, db: &dyn HirDatabase) -> Option { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index 556b21124dd5c..b89d332238b65 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -182,7 +182,7 @@ impl ChildBySource for EnumId { let tree = loc.id.item_tree(db); let ast_id_map = db.ast_id_map(loc.id.file_id()); - db.enum_data(*self).variants.iter().for_each(|&(variant, _)| { + db.enum_variants(*self).variants.iter().for_each(|&(variant, _)| { res[keys::ENUM_VARIANT] .insert(ast_id_map.get(tree[variant.lookup(db).id.value].ast_id), variant); }); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs index 8f38e02ed7685..9df13c5a4ef53 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs @@ -1,6 +1,6 @@ //! Completes constants and paths in unqualified patterns. -use hir::{db::DefDatabase, AssocItem, ScopeDef}; +use hir::{AssocItem, ScopeDef}; use ide_db::syntax_helpers::suggest_name; use syntax::ast::Pat; @@ -60,7 +60,7 @@ pub(crate) fn complete_pattern( } let refutable = pattern_ctx.refutability == PatternRefutability::Refutable; - let single_variant_enum = |enum_: hir::Enum| ctx.db.enum_data(enum_.into()).variants.len() == 1; + let single_variant_enum = |enum_: hir::Enum| enum_.num_variants(ctx.db) == 1; if let Some(hir::Adt::Enum(e)) = ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) From 2e83e8a84d614292e126728eab28d1492f35382e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 27 Feb 2025 11:22:29 +0100 Subject: [PATCH 0121/2248] Split `variant_data` into its own query --- .../rust-analyzer/crates/hir-def/src/attr.rs | 2 +- .../crates/hir-def/src/data/adt.rs | 215 +++++++++--------- .../rust-analyzer/crates/hir-def/src/db.rs | 24 +- .../crates/hir-def/src/expr_store/lower.rs | 2 +- .../crates/hir-def/src/item_tree.rs | 2 +- .../crates/hir-def/src/item_tree/lower.rs | 2 +- .../crates/hir-def/src/item_tree/pretty.rs | 7 +- .../rust-analyzer/crates/hir-def/src/lib.rs | 6 +- .../crates/hir-def/src/resolver.rs | 9 +- .../rust-analyzer/crates/hir-def/src/src.rs | 2 +- .../crates/hir-ty/src/chalk_db.rs | 2 +- .../hir-ty/src/diagnostics/decl_check.rs | 8 +- .../crates/hir-ty/src/display.rs | 4 +- .../crates/hir-ty/src/infer/cast.rs | 4 +- .../crates/hir-ty/src/infer/closure.rs | 4 +- .../crates/hir-ty/src/infer/expr.rs | 12 +- .../crates/hir-ty/src/infer/unify.rs | 5 +- .../rust-analyzer/crates/hir-ty/src/layout.rs | 8 +- .../crates/hir-ty/src/layout/adt.rs | 6 +- .../rust-analyzer/crates/hir-ty/src/lower.rs | 26 +-- .../crates/hir-ty/src/mir/eval.rs | 10 +- .../crates/hir-ty/src/mir/eval/shim/simd.rs | 4 +- .../crates/hir-ty/src/mir/lower.rs | 5 +- .../hir-ty/src/mir/lower/pattern_matching.rs | 4 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 23 +- .../crates/ide-db/src/apply_change.rs | 4 +- 26 files changed, 189 insertions(+), 211 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 030d064584cd6..2775e1398c28d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -84,7 +84,7 @@ impl Attrs { let krate = loc.parent.lookup(db).container.krate; item_tree = loc.id.item_tree(db); let variant = &item_tree[loc.id.value]; - (FieldParent::Variant(loc.id.value), &variant.fields, krate) + (FieldParent::EnumVariant(loc.id.value), &variant.fields, krate) } VariantId::StructId(it) => { let loc = it.lookup(db); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index c8429d8b6897f..9db66d6e91c99 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -27,7 +27,6 @@ use crate::{ #[derive(Debug, Clone, PartialEq, Eq)] pub struct StructData { pub name: Name, - pub variant_data: Arc, pub repr: Option, pub visibility: RawVisibility, pub flags: StructFlags, @@ -69,7 +68,6 @@ pub struct EnumVariants { #[derive(Debug, Clone, PartialEq, Eq)] pub struct EnumVariantData { pub name: Name, - pub variant_data: Arc, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -79,6 +77,94 @@ pub enum VariantData { Unit, } +impl VariantData { + #[inline] + pub(crate) fn variant_data_query(db: &dyn DefDatabase, id: VariantId) -> Arc { + db.variant_data_with_diagnostics(id).0 + } + + pub(crate) fn variant_data_with_diagnostics_query( + db: &dyn DefDatabase, + id: VariantId, + ) -> (Arc, DefDiagnostics) { + let (shape, types_map, (fields, diagnostics)) = match id { + VariantId::EnumVariantId(id) => { + let loc = id.lookup(db); + let item_tree = loc.id.item_tree(db); + let parent = loc.parent.lookup(db); + let krate = parent.container.krate; + let variant = &item_tree[loc.id.value]; + ( + variant.shape, + variant.types_map.clone(), + lower_fields( + db, + krate, + parent.container.local_id, + loc.id.tree_id(), + &item_tree, + krate.cfg_options(db), + FieldParent::EnumVariant(loc.id.value), + &variant.fields, + Some(item_tree[parent.id.value].visibility), + ), + ) + } + VariantId::StructId(id) => { + let loc = id.lookup(db); + let item_tree = loc.id.item_tree(db); + let krate = loc.container.krate; + let strukt = &item_tree[loc.id.value]; + ( + strukt.shape, + strukt.types_map.clone(), + lower_fields( + db, + krate, + loc.container.local_id, + loc.id.tree_id(), + &item_tree, + krate.cfg_options(db), + FieldParent::Struct(loc.id.value), + &strukt.fields, + None, + ), + ) + } + VariantId::UnionId(id) => { + let loc = id.lookup(db); + let item_tree = loc.id.item_tree(db); + let krate = loc.container.krate; + let union = &item_tree[loc.id.value]; + ( + FieldsShape::Record, + union.types_map.clone(), + lower_fields( + db, + krate, + loc.container.local_id, + loc.id.tree_id(), + &item_tree, + krate.cfg_options(db), + FieldParent::Union(loc.id.value), + &union.fields, + None, + ), + ) + } + }; + + ( + Arc::new(match shape { + FieldsShape::Record => VariantData::Record { fields, types_map }, + FieldsShape::Tuple => VariantData::Tuple { fields, types_map }, + FieldsShape::Unit => VariantData::Unit, + }), + DefDiagnostics::new(diagnostics), + ) + } +} + /// A single field of an enum variant or struct #[derive(Debug, Clone, PartialEq, Eq)] pub struct FieldData { @@ -99,13 +185,6 @@ fn repr_from_value( impl StructData { #[inline] pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc { - db.struct_data_with_diagnostics(id).0 - } - - pub(crate) fn struct_data_with_diagnostics_query( - db: &dyn DefDatabase, - id: StructId, - ) -> (Arc, DefDiagnostics) { let loc = id.lookup(db); let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); @@ -130,44 +209,16 @@ impl StructData { } let strukt = &item_tree[loc.id.value]; - let (fields, diagnostics) = lower_fields( - db, - krate, - loc.container.local_id, - loc.id.tree_id(), - &item_tree, - krate.cfg_options(db), - FieldParent::Struct(loc.id.value), - &strukt.fields, - None, - ); - let types_map = strukt.types_map.clone(); - - ( - Arc::new(StructData { - name: strukt.name.clone(), - variant_data: Arc::new(match strukt.shape { - FieldsShape::Record => VariantData::Record { fields, types_map }, - FieldsShape::Tuple => VariantData::Tuple { fields, types_map }, - FieldsShape::Unit => VariantData::Unit, - }), - repr, - visibility: item_tree[strukt.visibility].clone(), - flags, - }), - DefDiagnostics::new(diagnostics), - ) + Arc::new(StructData { + name: strukt.name.clone(), + repr, + visibility: item_tree[strukt.visibility].clone(), + flags, + }) } #[inline] pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc { - db.union_data_with_diagnostics(id).0 - } - - pub(crate) fn union_data_with_diagnostics_query( - db: &dyn DefDatabase, - id: UnionId, - ) -> (Arc, DefDiagnostics) { let loc = id.lookup(db); let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); @@ -182,28 +233,13 @@ impl StructData { } let union = &item_tree[loc.id.value]; - let (fields, diagnostics) = lower_fields( - db, - krate, - loc.container.local_id, - loc.id.tree_id(), - &item_tree, - krate.cfg_options(db), - FieldParent::Union(loc.id.value), - &union.fields, - None, - ); - let types_map = union.types_map.clone(); - ( - Arc::new(StructData { - name: union.name.clone(), - variant_data: Arc::new(VariantData::Record { fields, types_map }), - repr, - visibility: item_tree[union.visibility].clone(), - flags, - }), - DefDiagnostics::new(diagnostics), - ) + + Arc::new(StructData { + name: union.name.clone(), + repr, + visibility: item_tree[union.visibility].clone(), + flags, + }) } } @@ -227,16 +263,16 @@ impl EnumVariants { // [Adopted from rustc](https://github.com/rust-lang/rust/blob/bd53aa3bf7a24a70d763182303bd75e5fc51a9af/compiler/rustc_middle/src/ty/adt.rs#L446-L448) pub fn is_payload_free(&self, db: &dyn DefDatabase) -> bool { - self.variants.iter().all(|(v, _)| { + self.variants.iter().all(|&(v, _)| { // The condition check order is slightly modified from rustc // to improve performance by early returning with relatively fast checks - let variant = &db.enum_variant_data(*v).variant_data; + let variant = &db.variant_data(v.into()); if !variant.fields().is_empty() { return false; } // The outer if condition is whether this variant has const ctor or not if !matches!(variant.kind(), StructKind::Unit) { - let body = db.body((*v).into()); + let body = db.body(v.into()); // A variant with explicit discriminant if body.exprs[body.body_expr] != Expr::Missing { return false; @@ -282,43 +318,11 @@ impl EnumVariantData { db: &dyn DefDatabase, e: EnumVariantId, ) -> Arc { - db.enum_variant_data_with_diagnostics(e).0 - } - - pub(crate) fn enum_variant_data_with_diagnostics_query( - db: &dyn DefDatabase, - e: EnumVariantId, - ) -> (Arc, DefDiagnostics) { let loc = e.lookup(db); - let container = loc.parent.lookup(db).container; - let krate = container.krate; let item_tree = loc.id.item_tree(db); let variant = &item_tree[loc.id.value]; - let (fields, diagnostics) = lower_fields( - db, - krate, - container.local_id, - loc.id.tree_id(), - &item_tree, - krate.cfg_options(db), - FieldParent::Variant(loc.id.value), - &variant.fields, - Some(item_tree[loc.parent.lookup(db).id.value].visibility), - ); - let types_map = variant.types_map.clone(); - - ( - Arc::new(EnumVariantData { - name: variant.name.clone(), - variant_data: Arc::new(match variant.shape { - FieldsShape::Record => VariantData::Record { fields, types_map }, - FieldsShape::Tuple => VariantData::Tuple { fields, types_map }, - FieldsShape::Unit => VariantData::Unit, - }), - }), - DefDiagnostics::new(diagnostics), - ) + Arc::new(EnumVariantData { name: variant.name.clone() }) } } @@ -352,15 +356,6 @@ impl VariantData { VariantData::Unit => StructKind::Unit, } } - - #[allow(clippy::self_named_constructors)] - pub(crate) fn variant_data(db: &dyn DefDatabase, id: VariantId) -> Arc { - match id { - VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), - VariantId::EnumVariantId(it) => db.enum_variant_data(it).variant_data.clone(), - VariantId::UnionId(it) => db.union_data(it).variant_data.clone(), - } - } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index bc9fc8e079306..108968fe52e2a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -151,39 +151,27 @@ pub trait DefDatabase: // region:data #[salsa::transparent] + #[salsa::invoke_actual(VariantData::variant_data_query)] + fn variant_data(&self, id: VariantId) -> Arc; + + #[salsa::invoke_actual(VariantData::variant_data_with_diagnostics_query)] + fn variant_data_with_diagnostics(&self, id: VariantId) -> (Arc, DefDiagnostics); + #[salsa::invoke_actual(StructData::struct_data_query)] fn struct_data(&self, id: StructId) -> Arc; - #[salsa::invoke_actual(StructData::struct_data_with_diagnostics_query)] - fn struct_data_with_diagnostics(&self, id: StructId) -> (Arc, DefDiagnostics); - - #[salsa::transparent] #[salsa::invoke_actual(StructData::union_data_query)] fn union_data(&self, id: UnionId) -> Arc; - #[salsa::invoke_actual(StructData::union_data_with_diagnostics_query)] - fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc, DefDiagnostics); - #[salsa::invoke_actual(EnumData::enum_data_query)] fn enum_data(&self, e: EnumId) -> Arc; #[salsa::invoke_actual(EnumVariants::enum_variants_query)] fn enum_variants(&self, e: EnumId) -> Arc; - #[salsa::transparent] #[salsa::invoke_actual(EnumVariantData::enum_variant_data_query)] fn enum_variant_data(&self, id: EnumVariantId) -> Arc; - #[salsa::invoke_actual(EnumVariantData::enum_variant_data_with_diagnostics_query)] - fn enum_variant_data_with_diagnostics( - &self, - id: EnumVariantId, - ) -> (Arc, DefDiagnostics); - - #[salsa::transparent] - #[salsa::invoke_actual(VariantData::variant_data)] - fn variant_data(&self, id: VariantId) -> Arc; - #[salsa::invoke_actual(ImplData::impl_data_query)] fn impl_data(&self, e: ImplId) -> Arc; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index c346cec242eb6..b9b00108dcd24 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -1631,7 +1631,7 @@ impl ExprCollector<'_> { (None, Pat::Path(name.into())) } Some(ModuleDefId::AdtId(AdtId::StructId(s))) - if self.db.struct_data(s).variant_data.kind() != StructKind::Record => + if self.db.variant_data(s.into()).kind() != StructKind::Record => { (None, Pat::Path(name.into())) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 9acf98e62cd5c..d42104faa2e04 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -506,7 +506,7 @@ impl AttrOwner { pub enum FieldParent { Struct(FileItemTreeId), Union(FileItemTreeId), - Variant(FileItemTreeId), + EnumVariant(FileItemTreeId), } pub type ItemTreeParamId = Idx; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index b0546d4f33fde..05b99ae31f423 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -428,7 +428,7 @@ impl<'a> Ctx<'a> { for (idx, attr) in attrs { self.add_attrs( AttrOwner::Field( - FieldParent::Variant(FileItemTreeId(id)), + FieldParent::EnumVariant(FileItemTreeId(id)), Idx::from_raw(RawIdx::from_u32(idx as u32)), ), attr, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index d113a500ef76f..e666b1ea6bc29 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -382,7 +382,12 @@ impl Printer<'_> { this.print_ast_id(ast_id.erase()); this.print_attrs_of(variant, "\n"); w!(this, "{}", name.display(self.db.upcast(), edition)); - this.print_fields(FieldParent::Variant(variant), *kind, fields, types_map); + this.print_fields( + FieldParent::EnumVariant(variant), + *kind, + fields, + types_map, + ); wln!(this, ","); } }); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index fbbeb4beb99b9..5f8cd0fde04ab 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -1104,11 +1104,7 @@ impl_from!(EnumVariantId, StructId, UnionId for VariantId); impl VariantId { pub fn variant_data(self, db: &dyn DefDatabase) -> Arc { - match self { - VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), - VariantId::UnionId(it) => db.union_data(it).variant_data.clone(), - VariantId::EnumVariantId(it) => db.enum_variant_data(it).variant_data.clone(), - } + db.variant_data(self) } pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 72723499fc973..0ed26ca853e80 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -276,11 +276,16 @@ impl Resolver { db: &dyn DefDatabase, visibility: &RawVisibility, ) -> Option { - let within_impl = self.scopes().any(|scope| matches!(scope, Scope::ImplDefScope(_))); match visibility { RawVisibility::Module(_, _) => { let (item_map, item_local_map, module) = self.item_scope(); - item_map.resolve_visibility(item_local_map, db, module, visibility, within_impl) + item_map.resolve_visibility( + item_local_map, + db, + module, + visibility, + self.scopes().any(|scope| matches!(scope, Scope::ImplDefScope(_))), + ) } RawVisibility::Public => Some(Visibility::Public), } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/src.rs b/src/tools/rust-analyzer/crates/hir-def/src/src.rs index 43d31aa503ce0..347c4803be1cc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/src.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/src.rs @@ -131,7 +131,7 @@ impl HasChildSource for VariantId { item_tree = lookup.id.item_tree(db); ( lookup.source(db).map(|it| it.kind()), - FieldParent::Variant(lookup.id.value), + FieldParent::EnumVariant(lookup.id.value), lookup.parent.lookup(db).container, ) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index ac4d1babd62b4..acaca24f54f9b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -137,7 +137,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS, Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS, - _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]), + _ => self_ty_fp.as_slice(), }; let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index 0b21ae7ade377..5106056d40971 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -307,8 +307,8 @@ impl<'a> DeclValidator<'a> { /// Check incorrect names for struct fields. fn validate_struct_fields(&mut self, struct_id: StructId) { - let data = self.db.struct_data(struct_id); - let VariantData::Record { fields, .. } = data.variant_data.as_ref() else { + let data = self.db.variant_data(struct_id.into()); + let VariantData::Record { fields, .. } = data.as_ref() else { return; }; let edition = self.edition(struct_id); @@ -467,8 +467,8 @@ impl<'a> DeclValidator<'a> { /// Check incorrect names for fields of enum variant. fn validate_enum_variant_fields(&mut self, variant_id: EnumVariantId) { - let variant_data = self.db.enum_variant_data(variant_id); - let VariantData::Record { fields, .. } = variant_data.variant_data.as_ref() else { + let variant_data = self.db.variant_data(variant_id.into()); + let VariantData::Record { fields, .. } = variant_data.as_ref() else { return; }; let edition = self.edition(variant_id); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index be590b6101d6a..7bce23f398a60 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -846,7 +846,7 @@ fn render_const_scalar( write!(f, "{}", data.name.display(f.db.upcast(), f.edition()))?; let field_types = f.db.field_types(s.into()); render_variant_after_name( - &data.variant_data, + &f.db.variant_data(s.into()), f, &field_types, f.db.trait_environment(adt.0.into()), @@ -872,7 +872,7 @@ fn render_const_scalar( write!(f, "{}", data.name.display(f.db.upcast(), f.edition()))?; let field_types = f.db.field_types(var_id.into()); render_variant_after_name( - &data.variant_data, + &f.db.variant_data(var_id.into()), f, &field_types, f.db.trait_environment(adt.0.into()), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs index 6c0e0b0273761..8b43d0188a9de 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs @@ -389,8 +389,8 @@ fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result { self.consume_place(place) } VariantId::StructId(s) => { - let vd = &*self.db.struct_data(s).variant_data; + let vd = &*self.db.variant_data(s.into()); for field_pat in args.iter() { let arg = field_pat.pat; let Some(local_id) = vd.field(&field_pat.name) else { @@ -1211,7 +1211,7 @@ impl InferenceContext<'_> { self.consume_place(place) } VariantId::StructId(s) => { - let vd = &*self.db.struct_data(s).variant_data; + let vd = &*self.db.variant_data(s.into()); let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize)); let fields = vd.fields().iter(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index d0936185957f1..d0cbce70a2f14 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -1681,14 +1681,14 @@ impl InferenceContext<'_> { }) }); } - TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { - let local_id = self.db.struct_data(*s).variant_data.field(name)?; - let field = FieldId { parent: (*s).into(), local_id }; + &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref parameters) => { + let local_id = self.db.variant_data(s.into()).field(name)?; + let field = FieldId { parent: s.into(), local_id }; (field, parameters.clone()) } - TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { - let local_id = self.db.union_data(*u).variant_data.field(name)?; - let field = FieldId { parent: (*u).into(), local_id }; + &TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), ref parameters) => { + let local_id = self.db.variant_data(u.into()).field(name)?; + let field = FieldId { parent: u.into(), local_id }; (field, parameters.clone()) } _ => return None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index a9332a5a96374..e55fc0a9b83d9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -928,9 +928,8 @@ impl<'a> InferenceTable<'a> { // Must use a loop here and not recursion because otherwise users will conduct completely // artificial examples of structs that have themselves as the tail field and complain r-a crashes. while let Some((AdtId::StructId(id), subst)) = ty.as_adt() { - let struct_data = self.db.struct_data(id); - if let Some((last_field, _)) = struct_data.variant_data.fields().iter().next_back() - { + let struct_data = self.db.variant_data(id.into()); + if let Some((last_field, _)) = struct_data.fields().iter().next_back() { let last_field_ty = self.db.field_types(id.into())[last_field] .clone() .substitute(Interner, subst); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index 167dcec3bb3f8..2f7ad2b99d25b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -377,12 +377,12 @@ pub(crate) fn layout_of_ty_recover( fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty { match pointee.kind(Interner) { - TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), subst) => { - let data = db.struct_data(*i); - let mut it = data.variant_data.fields().iter().rev(); + &TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), ref subst) => { + let data = db.variant_data(i.into()); + let mut it = data.fields().iter().rev(); match it.next() { Some((f, _)) => { - let last_field_ty = field_ty(db, (*i).into(), f, subst); + let last_field_ty = field_ty(db, i.into(), f, subst); struct_tail_erasing_lifetimes(db, last_field_ty) } None => pointee, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs index 40a1d4e6707ab..9f453162e30c5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs @@ -44,13 +44,13 @@ pub fn layout_of_adt_query( AdtId::StructId(s) => { let data = db.struct_data(s); let mut r = SmallVec::<[_; 1]>::new(); - r.push(handle_variant(s.into(), &data.variant_data)?); + r.push(handle_variant(s.into(), &db.variant_data(s.into()))?); (r, data.repr.unwrap_or_default()) } AdtId::UnionId(id) => { let data = db.union_data(id); let mut r = SmallVec::new(); - r.push(handle_variant(id.into(), &data.variant_data)?); + r.push(handle_variant(id.into(), &db.variant_data(id.into()))?); (r, data.repr.unwrap_or_default()) } AdtId::EnumId(e) => { @@ -58,7 +58,7 @@ pub fn layout_of_adt_query( let r = variants .variants .iter() - .map(|&(v, _)| handle_variant(v.into(), &db.enum_variant_data(v).variant_data)) + .map(|&(v, _)| handle_variant(v.into(), &db.variant_data(v.into()))) .collect::, _>>()?; (r, db.enum_data(e).repr.unwrap_or_default()) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 33e852aaee46c..12f3a1138fcc0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -1491,16 +1491,12 @@ fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> Binders { } fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnSig { - let struct_data = db.struct_data(def); - let fields = struct_data.variant_data.fields(); + let struct_data = db.variant_data(def.into()); + let fields = struct_data.fields(); let resolver = def.resolver(db.upcast()); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - struct_data.variant_data.types_map(), - AdtId::from(def).into(), - ) - .with_type_param_mode(ParamLoweringMode::Variable); + let mut ctx = + TyLoweringContext::new(db, &resolver, struct_data.types_map(), AdtId::from(def).into()) + .with_type_param_mode(ParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| ctx.lower_ty(field.type_ref)); let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders(); Binders::new( @@ -1511,8 +1507,8 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS /// Build the type of a tuple struct constructor. fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option> { - let struct_data = db.struct_data(def); - match struct_data.variant_data.kind() { + let struct_data = db.variant_data(def.into()); + match struct_data.kind() { StructKind::Record => None, StructKind::Unit => Some(type_for_adt(db, def.into())), StructKind::Tuple => { @@ -1528,13 +1524,13 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option PolyFnSig { - let var_data = db.enum_variant_data(def); - let fields = var_data.variant_data.fields(); + let var_data = db.variant_data(def.into()); + let fields = var_data.fields(); let resolver = def.resolver(db.upcast()); let mut ctx = TyLoweringContext::new( db, &resolver, - var_data.variant_data.types_map(), + var_data.types_map(), DefWithBodyId::VariantId(def).into(), ) .with_type_param_mode(ParamLoweringMode::Variable); @@ -1553,7 +1549,7 @@ fn type_for_enum_variant_constructor( def: EnumVariantId, ) -> Option> { let e = def.lookup(db.upcast()).parent; - match db.enum_variant_data(def).variant_data.kind() { + match db.variant_data(def.into()).kind() { StructKind::Record => None, StructKind::Unit => Some(type_for_adt(db, e.into())), StructKind::Tuple => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 25aa2606558c1..45b4385568196 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -1761,7 +1761,7 @@ impl Evaluator<'_> { AdtId::EnumId(_) => not_supported!("unsizing enums"), }; let Some((last_field, _)) = - self.db.struct_data(id).variant_data.fields().iter().next_back() + self.db.variant_data(id.into()).fields().iter().next_back() else { not_supported!("unsizing struct without field"); }; @@ -2243,10 +2243,10 @@ impl Evaluator<'_> { } chalk_ir::TyKind::Adt(adt, subst) => match adt.0 { AdtId::StructId(s) => { - let data = this.db.struct_data(s); + let data = this.db.variant_data(s.into()); let layout = this.layout(ty)?; let field_types = this.db.field_types(s.into()); - for (f, _) in data.variant_data.fields().iter() { + for (f, _) in data.fields().iter() { let offset = layout .fields .offset(u32::from(f.into_raw()) as usize) @@ -2272,7 +2272,7 @@ impl Evaluator<'_> { bytes, e, ) { - let data = &this.db.enum_variant_data(v).variant_data; + let data = &this.db.variant_data(v.into()); let field_types = this.db.field_types(v.into()); for (f, _) in data.fields().iter() { let offset = @@ -2851,7 +2851,7 @@ impl Evaluator<'_> { return Ok(()); } let layout = self.layout_adt(id.0, subst.clone())?; - match data.variant_data.as_ref() { + match self.db.variant_data(s.into()).as_ref() { VariantData::Record { fields, .. } | VariantData::Tuple { fields, .. } => { let field_types = self.db.field_types(s.into()); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs index e229a4ab31727..829ed9efa2bc1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs @@ -31,8 +31,8 @@ impl Evaluator<'_> { Some(len) => len, _ => { if let AdtId::StructId(id) = id.0 { - let struct_data = self.db.struct_data(id); - let fields = struct_data.variant_data.fields(); + let struct_data = self.db.variant_data(id.into()); + let fields = struct_data.fields(); let Some((first_field, _)) = fields.iter().next() else { not_supported!("simd type with no field"); }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 57d4baa137cee..102048b3f4dca 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -499,7 +499,7 @@ impl<'ctx> MirLowerCtx<'ctx> { Ok(Some(current)) } ValueNs::EnumVariantId(variant_id) => { - let variant_data = &self.db.enum_variant_data(variant_id).variant_data; + let variant_data = &self.db.variant_data(variant_id.into()); if variant_data.kind() == StructKind::Unit { let ty = self.infer.type_of_expr[expr_id].clone(); current = self.lower_enum_variant( @@ -1165,8 +1165,7 @@ impl<'ctx> MirLowerCtx<'ctx> { Rvalue::Aggregate( AggregateKind::Adt(st.into(), subst.clone()), self.db - .struct_data(st) - .variant_data + .variant_data(st.into()) .fields() .iter() .map(|it| { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs index 783f92b2043f6..1c6dc4fecd81e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -597,7 +597,7 @@ impl MirLowerCtx<'_> { } self.pattern_matching_variant_fields( shape, - &self.db.enum_variant_data(v).variant_data, + &self.db.variant_data(v.into()), variant, current, current_else, @@ -607,7 +607,7 @@ impl MirLowerCtx<'_> { } VariantId::StructId(s) => self.pattern_matching_variant_fields( shape, - &self.db.struct_data(s).variant_data, + &self.db.variant_data(s.into()), variant, current, current_else, diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index f78b7a5c435cb..9f91f155ea77b 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -661,8 +661,7 @@ impl Module { db.field_types_with_diagnostics(s.id.into()).1, tree_source_maps.strukt(tree_id.value).item(), ); - - for diag in db.struct_data_with_diagnostics(s.id).1.iter() { + for diag in db.variant_data_with_diagnostics(s.id.into()).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } } @@ -675,8 +674,7 @@ impl Module { db.field_types_with_diagnostics(u.id.into()).1, tree_source_maps.union(tree_id.value).item(), ); - - for diag in db.union_data_with_diagnostics(u.id).1.iter() { + for diag in db.variant_data_with_diagnostics(u.id.into()).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } } @@ -692,7 +690,7 @@ impl Module { tree_source_maps.variant(tree_id.value), ); acc.extend(ModuleDef::Variant(v).diagnostics(db, style_lints)); - for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() { + for diag in db.variant_data_with_diagnostics(v.id.into()).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } } @@ -1059,7 +1057,7 @@ fn emit_def_diagnostic_( AttrOwner::Variant(it) => { ast_id_map.get(item_tree[it].ast_id).syntax_node_ptr() } - AttrOwner::Field(FieldParent::Variant(parent), idx) => process_field_list( + AttrOwner::Field(FieldParent::EnumVariant(parent), idx) => process_field_list( ast_id_map .get(item_tree[parent].ast_id) .to_node(&db.parse_or_expand(tree.file_id())) @@ -1392,6 +1390,7 @@ impl HasVisibility for Field { let variant_data = self.parent.variant_data(db); let visibility = &variant_data.fields()[self.id].visibility; let parent_id: hir_def::VariantId = self.parent.into(); + // FIXME: RawVisibility::Public doesn't need to construct a resolver visibility.resolve(db.upcast(), &parent_id.resolver(db.upcast())) } } @@ -1411,8 +1410,7 @@ impl Struct { } pub fn fields(self, db: &dyn HirDatabase) -> Vec { - db.struct_data(self.id) - .variant_data + db.variant_data(self.id.into()) .fields() .iter() .map(|(id, _)| Field { parent: self.into(), id }) @@ -1440,7 +1438,7 @@ impl Struct { } fn variant_data(self, db: &dyn HirDatabase) -> Arc { - db.struct_data(self.id).variant_data.clone() + db.variant_data(self.id.into()).clone() } pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { @@ -1481,8 +1479,7 @@ impl Union { } pub fn fields(self, db: &dyn HirDatabase) -> Vec { - db.union_data(self.id) - .variant_data + db.variant_data(self.id.into()) .fields() .iter() .map(|(id, _)| Field { parent: self.into(), id }) @@ -1490,7 +1487,7 @@ impl Union { } fn variant_data(self, db: &dyn HirDatabase) -> Arc { - db.union_data(self.id).variant_data.clone() + db.variant_data(self.id.into()).clone() } pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { @@ -1633,7 +1630,7 @@ impl Variant { } pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc { - db.enum_variant_data(self.id).variant_data.clone() + db.variant_data(self.id.into()).clone() } pub fn value(self, db: &dyn HirDatabase) -> Option { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs index 6b08ada34b609..4e058bb0106a2 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs @@ -149,7 +149,6 @@ impl RootDatabase { // hir::db::CrateNotableTraitsQuery // hir::db::CrateSupportsNoStdQuery // hir::db::EnumDataQuery - // hir::db::EnumVariantDataWithDiagnosticsQuery // hir::db::ExpandProcAttrMacrosQuery // hir::db::ExprScopesQuery // hir::db::ExternCrateDeclDataQuery @@ -191,11 +190,10 @@ impl RootDatabase { // hir::db::NotableTraitsInDepsQuery // hir::db::ProcMacroDataQuery // hir::db::StaticDataQuery - // hir::db::StructDataWithDiagnosticsQuery // hir::db::TraitAliasDataQuery // hir::db::TraitItemsWithDiagnosticsQuery // hir::db::TypeAliasDataQuery - // hir::db::UnionDataWithDiagnosticsQuery + // hir::db::VariantDataWithDiagnosticsQuery // // InternDatabase // hir::db::InternFunctionQuery From aed21ed588677c4d556650e7ca0fa575956e12f3 Mon Sep 17 00:00:00 2001 From: Vishruth-Thimmaiah Date: Mon, 3 Mar 2025 18:31:13 +0530 Subject: [PATCH 0122/2248] feat: for loop to while let assist --- .../src/handlers/convert_for_to_while_let.rs | 422 ++++++++++++++++++ .../crates/ide-assists/src/lib.rs | 2 + .../crates/ide-assists/src/tests/generated.rs | 24 + .../crates/syntax/src/ast/make.rs | 4 + .../src/ast/syntax_factory/constructors.rs | 17 +- 5 files changed, 467 insertions(+), 2 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs new file mode 100644 index 0000000000000..2d2751de99d87 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs @@ -0,0 +1,422 @@ +use hir::{ + sym::{self}, + Name, +}; +use ide_db::{famous_defs::FamousDefs, syntax_helpers::suggest_name}; +use syntax::{ + ast::{self, edit::IndentLevel, make, syntax_factory::SyntaxFactory, HasLoopBody}, + syntax_editor::Position, + AstNode, +}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: convert_for_loop_to_while_let +// +// Converts a for loop into a while let on the Iterator. +// +// ``` +// fn main() { +// let x = vec![1, 2, 3]; +// for$0 v in x { +// let y = v * 2; +// }; +// } +// ``` +// -> +// ``` +// fn main() { +// let x = vec![1, 2, 3]; +// let mut tmp = x.into_iter(); +// while let Some(v) = tmp.next() { +// let y = v * 2; +// }; +// } +// ``` +pub(crate) fn convert_for_loop_to_while_let( + acc: &mut Assists, + ctx: &AssistContext<'_>, +) -> Option<()> { + let for_loop = ctx.find_node_at_offset::()?; + let iterable = for_loop.iterable()?; + let pat = for_loop.pat()?; + let body = for_loop.loop_body()?; + if body.syntax().text_range().start() < ctx.offset() { + cov_mark::hit!(not_available_in_body); + return None; + } + + acc.add( + AssistId("convert_for_loop_to_while_let", AssistKind::RefactorRewrite), + "Replace this for loop with `while let`", + for_loop.syntax().text_range(), + |builder| { + let make = SyntaxFactory::new(); + let mut editor = builder.make_editor(for_loop.syntax()); + + let (iterable, method) = if impls_core_iter(&ctx.sema, &iterable) { + (iterable, None) + } else if let Some((expr, method)) = is_ref_and_impls_iter_method(&ctx.sema, &iterable) + { + (expr, Some(make.name_ref(method.as_str()))) + } else if let ast::Expr::RefExpr(_) = iterable { + (make::expr_paren(iterable), Some(make.name_ref("into_iter"))) + } else { + (iterable, Some(make.name_ref("into_iter"))) + }; + + let iterable = if let Some(method) = method { + make::expr_method_call(iterable, method, make::arg_list([])) + } else { + iterable + }; + + let mut new_name = suggest_name::NameGenerator::new_from_scope_locals( + ctx.sema.scope(for_loop.syntax()), + ); + let tmp_var = new_name.suggest_name("tmp"); + + let mut_expr = make.let_stmt( + make.ident_pat(false, true, make.name(&tmp_var)).into(), + None, + Some(iterable), + ); + let indent = IndentLevel::from_node(for_loop.syntax()); + editor.insert( + Position::before(for_loop.syntax()), + make::tokens::whitespace(format!("\n{indent}").as_str()), + ); + editor.insert(Position::before(for_loop.syntax()), mut_expr.syntax()); + + let opt_pat = make.tuple_struct_pat(make::ext::ident_path("Some"), [pat]); + let iter_next_expr = make.expr_method_call( + make.expr_path(make::ext::ident_path(&tmp_var)), + make.name_ref("next"), + make.arg_list([]), + ); + let cond = make.expr_let(opt_pat.into(), iter_next_expr.into()); + + let while_loop = make.expr_while_loop(cond.into(), body); + + editor.replace(for_loop.syntax(), while_loop.syntax()); + + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.file_id(), editor); + }, + ) +} + +/// If iterable is a reference where the expression behind the reference implements a method +/// returning an Iterator called iter or iter_mut (depending on the type of reference) then return +/// the expression behind the reference and the method name +fn is_ref_and_impls_iter_method( + sema: &hir::Semantics<'_, ide_db::RootDatabase>, + iterable: &ast::Expr, +) -> Option<(ast::Expr, hir::Name)> { + let ref_expr = match iterable { + ast::Expr::RefExpr(r) => r, + _ => return None, + }; + let wanted_method = Name::new_symbol_root(if ref_expr.mut_token().is_some() { + sym::iter_mut.clone() + } else { + sym::iter.clone() + }); + let expr_behind_ref = ref_expr.expr()?; + let ty = sema.type_of_expr(&expr_behind_ref)?.adjusted(); + let scope = sema.scope(iterable.syntax())?; + let krate = scope.krate(); + let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?; + + let has_wanted_method = ty + .iterate_method_candidates(sema.db, &scope, None, Some(&wanted_method), |func| { + if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) { + return Some(()); + } + None + }) + .is_some(); + if !has_wanted_method { + return None; + } + + Some((expr_behind_ref, wanted_method)) +} + +/// Whether iterable implements core::Iterator +fn impls_core_iter(sema: &hir::Semantics<'_, ide_db::RootDatabase>, iterable: &ast::Expr) -> bool { + (|| { + let it_typ = sema.type_of_expr(iterable)?.adjusted(); + + let module = sema.scope(iterable.syntax())?.module(); + + let krate = module.krate(); + let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?; + cov_mark::hit!(test_already_impls_iterator); + Some(it_typ.impls_trait(sema.db, iter_trait, &[])) + })() + .unwrap_or(false) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn each_to_for_simple_for() { + check_assist( + convert_for_loop_to_while_let, + r" +fn main() { + let mut x = vec![1, 2, 3]; + for $0v in x { + v *= 2; + }; +}", + r" +fn main() { + let mut x = vec![1, 2, 3]; + let mut tmp = x.into_iter(); + while let Some(v) = tmp.next() { + v *= 2; + }; +}", + ) + } + + #[test] + fn each_to_for_for_in_range() { + check_assist( + convert_for_loop_to_while_let, + r#" +//- minicore: range, iterators +impl core::iter::Iterator for core::ops::Range { + type Item = T; + + fn next(&mut self) -> Option { + None + } +} + +fn main() { + for $0x in 0..92 { + print!("{}", x); + } +}"#, + r#" +impl core::iter::Iterator for core::ops::Range { + type Item = T; + + fn next(&mut self) -> Option { + None + } +} + +fn main() { + let mut tmp = 0..92; + while let Some(x) = tmp.next() { + print!("{}", x); + } +}"#, + ) + } + + #[test] + fn each_to_for_not_available_in_body() { + cov_mark::check!(not_available_in_body); + check_assist_not_applicable( + convert_for_loop_to_while_let, + r" +fn main() { + let mut x = vec![1, 2, 3]; + for v in x { + $0v *= 2; + } +}", + ) + } + + #[test] + fn each_to_for_for_borrowed() { + check_assist( + convert_for_loop_to_while_let, + r#" +//- minicore: iterators +use core::iter::{Repeat, repeat}; + +struct S; +impl S { + fn iter(&self) -> Repeat { repeat(92) } + fn iter_mut(&mut self) -> Repeat { repeat(92) } +} + +fn main() { + let x = S; + for $0v in &x { + let a = v * 2; + } +} +"#, + r#" +use core::iter::{Repeat, repeat}; + +struct S; +impl S { + fn iter(&self) -> Repeat { repeat(92) } + fn iter_mut(&mut self) -> Repeat { repeat(92) } +} + +fn main() { + let x = S; + let mut tmp = x.iter(); + while let Some(v) = tmp.next() { + let a = v * 2; + } +} +"#, + ) + } + + #[test] + fn each_to_for_for_borrowed_no_iter_method() { + check_assist( + convert_for_loop_to_while_let, + r" +struct NoIterMethod; +fn main() { + let x = NoIterMethod; + for $0v in &x { + let a = v * 2; + } +} +", + r" +struct NoIterMethod; +fn main() { + let x = NoIterMethod; + let mut tmp = (&x).into_iter(); + while let Some(v) = tmp.next() { + let a = v * 2; + } +} +", + ) + } + + #[test] + fn each_to_for_for_borrowed_no_iter_method_mut() { + check_assist( + convert_for_loop_to_while_let, + r" +struct NoIterMethod; +fn main() { + let x = NoIterMethod; + for $0v in &mut x { + let a = v * 2; + } +} +", + r" +struct NoIterMethod; +fn main() { + let x = NoIterMethod; + let mut tmp = (&mut x).into_iter(); + while let Some(v) = tmp.next() { + let a = v * 2; + } +} +", + ) + } + + #[test] + fn each_to_for_for_borrowed_mut() { + check_assist( + convert_for_loop_to_while_let, + r#" +//- minicore: iterators +use core::iter::{Repeat, repeat}; + +struct S; +impl S { + fn iter(&self) -> Repeat { repeat(92) } + fn iter_mut(&mut self) -> Repeat { repeat(92) } +} + +fn main() { + let x = S; + for $0v in &mut x { + let a = v * 2; + } +} +"#, + r#" +use core::iter::{Repeat, repeat}; + +struct S; +impl S { + fn iter(&self) -> Repeat { repeat(92) } + fn iter_mut(&mut self) -> Repeat { repeat(92) } +} + +fn main() { + let x = S; + let mut tmp = x.iter_mut(); + while let Some(v) = tmp.next() { + let a = v * 2; + } +} +"#, + ) + } + + #[test] + fn each_to_for_for_borrowed_mut_behind_var() { + check_assist( + convert_for_loop_to_while_let, + r" +fn main() { + let mut x = vec![1, 2, 3]; + let y = &mut x; + for $0v in y { + *v *= 2; + } +}", + r" +fn main() { + let mut x = vec![1, 2, 3]; + let y = &mut x; + let mut tmp = y.into_iter(); + while let Some(v) = tmp.next() { + *v *= 2; + } +}", + ) + } + + #[test] + fn each_to_for_already_impls_iterator() { + cov_mark::check!(test_already_impls_iterator); + check_assist( + convert_for_loop_to_while_let, + r#" +//- minicore: iterators +fn main() { + for$0 a in core::iter::repeat(92).take(1) { + println!("{}", a); + } +} +"#, + r#" +fn main() { + let mut tmp = core::iter::repeat(92).take(1); + while let Some(a) = tmp.next() { + println!("{}", a); + } +} +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index e8480b0de1906..7e9d59661481e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -122,6 +122,7 @@ mod handlers { mod convert_closure_to_fn; mod convert_comment_block; mod convert_comment_from_or_to_doc; + mod convert_for_to_while_let; mod convert_from_to_tryfrom; mod convert_integer_literal; mod convert_into_to_from; @@ -252,6 +253,7 @@ mod handlers { convert_closure_to_fn::convert_closure_to_fn, convert_comment_block::convert_comment_block, convert_comment_from_or_to_doc::convert_comment_from_or_to_doc, + convert_for_to_while_let::convert_for_loop_to_while_let, convert_from_to_tryfrom::convert_from_to_tryfrom, convert_integer_literal::convert_integer_literal, convert_into_to_from::convert_into_to_from, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 4234124d670ff..359de438ed6d2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -439,6 +439,30 @@ fn main() { ) } +#[test] +fn doctest_convert_for_loop_to_while_let() { + check_doc_test( + "convert_for_loop_to_while_let", + r#####" +fn main() { + let x = vec![1, 2, 3]; + for$0 v in x { + let y = v * 2; + }; +} +"#####, + r#####" +fn main() { + let x = vec![1, 2, 3]; + let mut tmp = x.into_iter(); + while let Some(v) = tmp.next() { + let y = v * 2; + }; +} +"#####, + ) +} + #[test] fn doctest_convert_for_loop_with_for_each() { check_doc_test( diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index 231c21c38f85f..234e3d1efe1fb 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -623,6 +623,10 @@ pub fn expr_for_loop(pat: ast::Pat, expr: ast::Expr, block: ast::BlockExpr) -> a expr_from_text(&format!("for {pat} in {expr} {block}")) } +pub fn expr_while_loop(condition: ast::Expr, block: ast::BlockExpr) -> ast::WhileExpr { + expr_from_text(&format!("while {condition} {block}")) +} + pub fn expr_loop(block: ast::BlockExpr) -> ast::Expr { expr_from_text(&format!("loop {block}")) } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs index 44f13041c244f..bec5d2a39a330 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs @@ -1,8 +1,8 @@ //! Wrappers over [`make`] constructors use crate::{ ast::{ - self, make, HasArgList, HasGenericArgs, HasGenericParams, HasName, HasTypeBounds, - HasVisibility, + self, make, HasArgList, HasGenericArgs, HasGenericParams, HasLoopBody, HasName, + HasTypeBounds, HasVisibility, }, syntax_editor::SyntaxMappingBuilder, AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken, @@ -543,6 +543,19 @@ impl SyntaxFactory { ast } + pub fn expr_while_loop(&self, condition: ast::Expr, body: ast::BlockExpr) -> ast::WhileExpr { + let ast = make::expr_while_loop(condition.clone(), body.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(condition.syntax().clone(), ast.condition().unwrap().syntax().clone()); + builder.map_node(body.syntax().clone(), ast.loop_body().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + pub fn expr_let(&self, pattern: ast::Pat, expr: ast::Expr) -> ast::LetExpr { let ast = make::expr_let(pattern.clone(), expr.clone()).clone_for_update(); From 2c2bc99a634689840e1c2c465ca7382c2bf0e1b9 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 14 Mar 2025 14:52:03 +0100 Subject: [PATCH 0123/2248] Avoid recursively debug printing crates --- .../rust-analyzer/crates/base-db/src/input.rs | 3 +- .../ide-db/src/test_data/test_doc_alias.txt | 6 ++-- .../test_symbol_index_collection.txt | 30 +++++++++---------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index c4e64b372f36a..913dfe6efb770 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -393,7 +393,8 @@ impl BuiltDependency { pub type CratesIdMap = FxHashMap; -#[salsa::input] +#[salsa::input(no_debug)] +#[derive(Debug)] pub struct Crate { #[return_ref] pub data: BuiltCrateData, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt index 1e2d4f1ab94fc..a527ce19d2051 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt @@ -2,9 +2,9 @@ ( Module { id: ModuleId { - krate: Crate { - [salsa id]: Id(2c00), - }, + krate: Crate( + Id(2c00), + ), block: None, local_id: Idx::(0), }, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt index 1a77052b18d46..82440d7c1ee09 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt @@ -2,9 +2,9 @@ ( Module { id: ModuleId { - krate: Crate { - [salsa id]: Id(2c00), - }, + krate: Crate( + Id(2c00), + ), block: None, local_id: Idx::(0), }, @@ -534,9 +534,9 @@ def: Module( Module { id: ModuleId { - krate: Crate { - [salsa id]: Id(2c00), - }, + krate: Crate( + Id(2c00), + ), block: None, local_id: Idx::(1), }, @@ -569,9 +569,9 @@ def: Module( Module { id: ModuleId { - krate: Crate { - [salsa id]: Id(2c00), - }, + krate: Crate( + Id(2c00), + ), block: None, local_id: Idx::(2), }, @@ -833,9 +833,9 @@ ( Module { id: ModuleId { - krate: Crate { - [salsa id]: Id(2c00), - }, + krate: Crate( + Id(2c00), + ), block: None, local_id: Idx::(1), }, @@ -879,9 +879,9 @@ ( Module { id: ModuleId { - krate: Crate { - [salsa id]: Id(2c00), - }, + krate: Crate( + Id(2c00), + ), block: None, local_id: Idx::(2), }, From 9576c712ccc22ce09be4317b90813600d2af2533 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Thu, 13 Mar 2025 14:36:02 -0700 Subject: [PATCH 0124/2248] Teach rustfmt to handle postfix yield --- clippy_utils/src/ast_utils/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index 707312a97f3bc..deda6030831ec 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -201,7 +201,8 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { (Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lt, rt), (Block(lb, ll), Block(rb, rl)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lb, rb), (TryBlock(l), TryBlock(r)) => eq_block(l, r), - (Yield(l), Yield(r)) | (Ret(l), Ret(r)) => eq_expr_opt(l.as_ref(), r.as_ref()), + (Yield(l, lk), Yield(r, rk)) => eq_expr_opt(l.as_ref(), r.as_ref()) && lk == rk, + (Ret(l), Ret(r)) => eq_expr_opt(l.as_ref(), r.as_ref()), (Break(ll, le), Break(rl, re)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_expr_opt(le.as_ref(), re.as_ref()), (Continue(ll), Continue(rl)) => eq_label(ll.as_ref(), rl.as_ref()), (Assign(l1, l2, _), Assign(r1, r2, _)) | (Index(l1, l2, _), Index(r1, r2, _)) => { @@ -688,7 +689,7 @@ pub fn eq_generics(l: &Generics, r: &Generics) -> bool { pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { use WherePredicateKind::*; - over(&l.attrs, &r.attrs, eq_attr) + over(&l.attrs, &r.attrs, eq_attr) && match (&l.kind, &r.kind) { (BoundPredicate(l), BoundPredicate(r)) => { over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { From ed1778c226591425b31f93ae01a2997fcbbcc738 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Thu, 13 Mar 2025 16:14:31 -0700 Subject: [PATCH 0125/2248] Fix clippy --- clippy_lints/src/suspicious_operation_groupings.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/suspicious_operation_groupings.rs b/clippy_lints/src/suspicious_operation_groupings.rs index 0d809c17989de..206912d8de40d 100644 --- a/clippy_lints/src/suspicious_operation_groupings.rs +++ b/clippy_lints/src/suspicious_operation_groupings.rs @@ -528,7 +528,7 @@ fn ident_difference_expr_with_base_location( &strip_non_ident_wrappers(left).kind, &strip_non_ident_wrappers(right).kind, ) { - (Yield(_), Yield(_)) + (Yield(_, _), Yield(_, _)) | (Try(_), Try(_)) | (Paren(_), Paren(_)) | (Repeat(_, _), Repeat(_, _)) From 7060bfe553f67d5d8370e9f53a7ce2d74a8026f8 Mon Sep 17 00:00:00 2001 From: David Richey Date: Fri, 14 Mar 2025 16:55:24 -0500 Subject: [PATCH 0126/2248] Require Rust 1.85 --- src/tools/rust-analyzer/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 7dd5f2bb1faa9..e9d70bea346dc 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -4,7 +4,7 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"] resolver = "2" [workspace.package] -rust-version = "1.84" +rust-version = "1.85" edition = "2021" license = "MIT OR Apache-2.0" authors = ["rust-analyzer team"] From 246415809cb151cbe6411e075c815940d61f55b4 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 15 Mar 2025 15:53:23 +0100 Subject: [PATCH 0127/2248] fix: Fix missing `with_durability` calls --- src/tools/rust-analyzer/crates/base-db/src/lib.rs | 10 +++++++--- src/tools/rust-analyzer/crates/hir-expand/src/db.rs | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index 0f29abbb54f14..b733c4d24147e 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -86,7 +86,7 @@ impl Files { let files = Arc::clone(&self.files); match files.entry(file_id) { Entry::Occupied(mut occupied) => { - occupied.get_mut().set_text(db).to(Arc::from(text)); + occupied.get_mut().set_text(db).with_durability(durability).to(Arc::from(text)); } Entry::Vacant(vacant) => { let text = @@ -116,7 +116,7 @@ impl Files { let source_roots = Arc::clone(&self.source_roots); match source_roots.entry(source_root_id) { Entry::Occupied(mut occupied) => { - occupied.get_mut().set_source_root(db).to(source_root); + occupied.get_mut().set_source_root(db).with_durability(durability).to(source_root); } Entry::Vacant(vacant) => { let source_root = @@ -145,7 +145,11 @@ impl Files { // let db = self; match file_source_roots.entry(id) { Entry::Occupied(mut occupied) => { - occupied.get_mut().set_source_root_id(db).to(source_root_id); + occupied + .get_mut() + .set_source_root_id(db) + .with_durability(durability) + .to(source_root_id); } Entry::Vacant(vacant) => { let file_source_root = diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 112327f11e1a8..7e7858d15b4cf 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -61,6 +61,7 @@ pub trait ExpandDatabase: RootQueryDb { #[salsa::input] fn proc_macros(&self) -> Arc; + /// Incrementality query to prevent queries from directly depending on `ExpandDatabase::proc_macros`. #[salsa::invoke_actual(crate::proc_macro::proc_macros_for_crate)] fn proc_macros_for_crate(&self, krate: Crate) -> Option>; From 94e0b32258b024192f860709a3b64100eb05ba69 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 15 Mar 2025 16:10:02 +0100 Subject: [PATCH 0128/2248] chore: Drop legacy salsa --- src/tools/rust-analyzer/Cargo.lock | 111 +-- .../rust-analyzer/crates/ra-salsa/Cargo.toml | 35 - .../rust-analyzer/crates/ra-salsa/FAQ.md | 34 - .../crates/ra-salsa/LICENSE-APACHE | 176 ---- .../rust-analyzer/crates/ra-salsa/LICENSE-MIT | 23 - .../rust-analyzer/crates/ra-salsa/README.md | 42 - .../ra-salsa/ra-salsa-macros/Cargo.toml | 23 - .../ra-salsa/ra-salsa-macros/LICENSE-APACHE | 1 - .../ra-salsa/ra-salsa-macros/LICENSE-MIT | 1 - .../crates/ra-salsa/ra-salsa-macros/README.md | 1 - .../ra-salsa-macros/src/database_storage.rs | 243 ----- .../ra-salsa/ra-salsa-macros/src/lib.rs | 125 --- .../ra-salsa-macros/src/parenthesized.rs | 13 - .../ra-salsa-macros/src/query_group.rs | 753 --------------- .../crates/ra-salsa/src/debug.rs | 65 -- .../crates/ra-salsa/src/derived.rs | 163 ---- .../crates/ra-salsa/src/derived/slot.rs | 782 ---------------- .../crates/ra-salsa/src/derived_lru.rs | 233 ----- .../crates/ra-salsa/src/derived_lru/slot.rs | 856 ------------------ .../crates/ra-salsa/src/durability.rs | 49 - .../rust-analyzer/crates/ra-salsa/src/hash.rs | 3 - .../crates/ra-salsa/src/input.rs | 371 -------- .../crates/ra-salsa/src/intern_id.rs | 131 --- .../crates/ra-salsa/src/interned.rs | 510 ----------- .../rust-analyzer/crates/ra-salsa/src/lib.rs | 750 --------------- .../rust-analyzer/crates/ra-salsa/src/lru.rs | 325 ------- .../crates/ra-salsa/src/plumbing.rs | 245 ----- .../crates/ra-salsa/src/revision.rs | 66 -- .../crates/ra-salsa/src/runtime.rs | 668 -------------- .../ra-salsa/src/runtime/dependency_graph.rs | 250 ----- .../ra-salsa/src/runtime/local_state.rs | 204 ----- .../crates/ra-salsa/src/storage.rs | 53 -- .../crates/ra-salsa/tests/cycles.rs | 492 ---------- .../crates/ra-salsa/tests/dyn_trait.rs | 28 - .../ra-salsa/tests/incremental/constants.rs | 145 --- .../ra-salsa/tests/incremental/counter.rs | 14 - .../tests/incremental/implementation.rs | 59 -- .../crates/ra-salsa/tests/incremental/log.rs | 16 - .../crates/ra-salsa/tests/incremental/main.rs | 9 - .../tests/incremental/memoized_dep_inputs.rs | 60 -- .../tests/incremental/memoized_inputs.rs | 76 -- .../tests/incremental/memoized_volatile.rs | 77 -- .../crates/ra-salsa/tests/interned.rs | 90 -- .../crates/ra-salsa/tests/lru.rs | 104 --- .../crates/ra-salsa/tests/macros.rs | 12 - .../crates/ra-salsa/tests/no_send_sync.rs | 31 - .../crates/ra-salsa/tests/on_demand_inputs.rs | 147 --- .../crates/ra-salsa/tests/panic_safely.rs | 93 -- .../ra-salsa/tests/parallel/cancellation.rs | 132 --- .../crates/ra-salsa/tests/parallel/frozen.rs | 57 -- .../ra-salsa/tests/parallel/independent.rs | 29 - .../crates/ra-salsa/tests/parallel/main.rs | 13 - .../parallel/parallel_cycle_all_recover.rs | 109 --- .../parallel/parallel_cycle_mid_recover.rs | 109 --- .../parallel/parallel_cycle_none_recover.rs | 68 -- .../parallel/parallel_cycle_one_recovers.rs | 94 -- .../crates/ra-salsa/tests/parallel/race.rs | 37 - .../crates/ra-salsa/tests/parallel/setup.rs | 197 ---- .../crates/ra-salsa/tests/parallel/signal.rs | 40 - .../crates/ra-salsa/tests/parallel/stress.rs | 168 ---- .../ra-salsa/tests/parallel/true_parallel.rs | 125 --- .../tests/storage_varieties/implementation.rs | 19 - .../ra-salsa/tests/storage_varieties/main.rs | 5 - .../tests/storage_varieties/queries.rs | 22 - .../ra-salsa/tests/storage_varieties/tests.rs | 49 - .../crates/ra-salsa/tests/transparent.rs | 39 - .../crates/ra-salsa/tests/variadic.rs | 51 -- src/tools/rust-analyzer/xtask/src/tidy.rs | 3 +- 68 files changed, 9 insertions(+), 10115 deletions(-) delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/Cargo.toml delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/FAQ.md delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/LICENSE-APACHE delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/LICENSE-MIT delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/README.md delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/Cargo.toml delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/LICENSE-APACHE delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/LICENSE-MIT delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/README.md delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/database_storage.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/lib.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/parenthesized.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/query_group.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/debug.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/derived.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/derived/slot.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru/slot.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/durability.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/hash.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/input.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/intern_id.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/interned.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/lib.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/lru.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/plumbing.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/revision.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/runtime.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/runtime/dependency_graph.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/runtime/local_state.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/src/storage.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/cycles.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/dyn_trait.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/constants.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/counter.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/implementation.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/log.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/main.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_dep_inputs.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_inputs.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_volatile.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/interned.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/lru.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/macros.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/no_send_sync.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/on_demand_inputs.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/panic_safely.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/cancellation.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/frozen.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/independent.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/main.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_all_recover.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_mid_recover.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_none_recover.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_one_recovers.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/race.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/setup.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/signal.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/stress.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/true_parallel.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/implementation.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/main.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/queries.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/tests.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/transparent.rs delete mode 100644 src/tools/rust-analyzer/crates/ra-salsa/tests/variadic.rs diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 00da1c973dc0f..54cc9d1c68025 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -88,7 +88,7 @@ dependencies = [ "lz4_flex", "query-group-macro", "rustc-hash 2.1.1", - "salsa 0.19.0", + "salsa", "semver", "span", "stdx", @@ -656,7 +656,7 @@ dependencies = [ "ra-ap-rustc_parse_format", "rustc-hash 2.1.1", "rustc_apfloat", - "salsa 0.19.0", + "salsa", "smallvec", "span", "stdx", @@ -687,7 +687,7 @@ dependencies = [ "parser", "query-group-macro", "rustc-hash 2.1.1", - "salsa 0.19.0", + "salsa", "smallvec", "span", "stdx", @@ -729,7 +729,7 @@ dependencies = [ "ra-ap-rustc_pattern_analysis", "rustc-hash 2.1.1", "rustc_apfloat", - "salsa 0.19.0", + "salsa", "scoped-tls", "smallvec", "span", @@ -966,7 +966,7 @@ dependencies = [ "query-group-macro", "rayon", "rustc-hash 2.1.1", - "salsa 0.19.0", + "salsa", "span", "stdx", "syntax", @@ -1190,12 +1190,6 @@ dependencies = [ "text-size", ] -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "litemap" version = "0.7.5" @@ -1619,15 +1613,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "proc-macro-api" version = "0.0.0" @@ -1785,7 +1770,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "salsa 0.19.0", + "salsa", "syn", ] @@ -1874,36 +1859,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - [[package]] name = "rayon" version = "1.10.0" @@ -2113,26 +2068,6 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "salsa" -version = "0.0.0" -dependencies = [ - "dissimilar", - "expect-test", - "indexmap", - "itertools", - "linked-hash-map", - "lock_api", - "oorandom", - "parking_lot", - "rand", - "rustc-hash 2.1.1", - "salsa-macros 0.0.0", - "smallvec", - "tracing", - "triomphe", -] - [[package]] name = "salsa" version = "0.19.0" @@ -2150,7 +2085,7 @@ dependencies = [ "rayon", "rustc-hash 2.1.1", "salsa-macro-rules", - "salsa-macros 0.19.0", + "salsa-macros", "smallvec", "tracing", ] @@ -2161,16 +2096,6 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2619b4b451beab0a7e4364ff1e6f31950e7e418888fd9bf2f28889671563166a" -[[package]] -name = "salsa-macros" -version = "0.0.0" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "salsa-macros" version = "0.19.0" @@ -2314,7 +2239,7 @@ dependencies = [ "hashbrown 0.14.5", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 2.1.1", - "salsa 0.19.0", + "salsa", "stdx", "syntax", "text-size", @@ -3267,26 +3192,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zerocopy" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zerofrom" version = "0.1.6" diff --git a/src/tools/rust-analyzer/crates/ra-salsa/Cargo.toml b/src/tools/rust-analyzer/crates/ra-salsa/Cargo.toml deleted file mode 100644 index 57a20be0cadd7..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -[package] -name = "salsa" -version = "0.0.0" -authors = ["Salsa developers"] -edition = "2021" -license = "Apache-2.0 OR MIT" -repository = "https://github.com/salsa-rs/salsa" -description = "A generic framework for on-demand, incrementalized computation (experimental)" - -rust-version.workspace = true - -[lib] -name = "ra_salsa" - -[dependencies] -indexmap = "2.1.0" -lock_api = "0.4" -tracing = "0.1" -parking_lot = "0.12.1" -rustc-hash = "2.0.0" -smallvec = "1.0.0" -oorandom = "11" -triomphe.workspace = true -itertools.workspace = true - -ra-salsa-macros = { version = "0.0.0", path = "ra-salsa-macros", package = "salsa-macros" } - -[dev-dependencies] -linked-hash-map = "0.5.6" -rand = "0.8.5" -expect-test = "1.4.0" -dissimilar = "1.0.7" - -[lints] -workspace = true diff --git a/src/tools/rust-analyzer/crates/ra-salsa/FAQ.md b/src/tools/rust-analyzer/crates/ra-salsa/FAQ.md deleted file mode 100644 index 9c9f6f92da990..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/FAQ.md +++ /dev/null @@ -1,34 +0,0 @@ -# Frequently asked questions - -## Why is it called salsa? - -I like salsa! Don't you?! Well, ok, there's a bit more to it. The -underlying algorithm for figuring out which bits of code need to be -re-executed after any given change is based on the algorithm used in -rustc. Michael Woerister and I first described the rustc algorithm in -terms of two colors, red and green, and hence we called it the -"red-green algorithm". This made me think of the New Mexico State -Question --- ["Red or green?"][nm] --- which refers to chile -(salsa). Although this version no longer uses colors (we borrowed -revision counters from Glimmer, instead), I still like the name. - -[nm]: https://www.sos.state.nm.us/about-new-mexico/state-question/ - -## What is the relationship between salsa and an Entity-Component System (ECS)? - -You may have noticed that Salsa "feels" a lot like an ECS in some -ways. That's true -- Salsa's queries are a bit like *components* (and -the keys to the queries are a bit like *entities*). But there is one -big difference: **ECS is -- at its heart -- a mutable system**. You -can get or set a component of some entity whenever you like. In -contrast, salsa's queries **define "derived values" via pure -computations**. - -Partly as a consequence, ECS doesn't handle incremental updates for -you. When you update some component of some entity, you have to ensure -that other entities' components are updated appropriately. - -Finally, ECS offers interesting metadata and "aspect-like" facilities, -such as iterating over all entities that share certain components. -Salsa has no analogue to that. - diff --git a/src/tools/rust-analyzer/crates/ra-salsa/LICENSE-APACHE b/src/tools/rust-analyzer/crates/ra-salsa/LICENSE-APACHE deleted file mode 100644 index 1b5ec8b78e237..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/LICENSE-APACHE +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS diff --git a/src/tools/rust-analyzer/crates/ra-salsa/LICENSE-MIT b/src/tools/rust-analyzer/crates/ra-salsa/LICENSE-MIT deleted file mode 100644 index 31aa79387f27e..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/src/tools/rust-analyzer/crates/ra-salsa/README.md b/src/tools/rust-analyzer/crates/ra-salsa/README.md deleted file mode 100644 index 4a8d9f8c7317a..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# salsa - -*A generic framework for on-demand, incrementalized computation.* - -## Obligatory warning - -This is a fork of https://github.com/salsa-rs/salsa/ adjusted to rust-analyzer's needs. - -## Credits - -This system is heavily inspired by [adapton](http://adapton.org/), [glimmer](https://github.com/glimmerjs/glimmer-vm), and rustc's query -system. So credit goes to Eduard-Mihai Burtescu, Matthew Hammer, -Yehuda Katz, and Michael Woerister. - -## Key idea - -The key idea of `salsa` is that you define your program as a set of -**queries**. Every query is used like function `K -> V` that maps from -some key of type `K` to a value of type `V`. Queries come in two basic -varieties: - -- **Inputs**: the base inputs to your system. You can change these - whenever you like. -- **Functions**: pure functions (no side effects) that transform your - inputs into other values. The results of queries is memoized to - avoid recomputing them a lot. When you make changes to the inputs, - we'll figure out (fairly intelligently) when we can re-use these - memoized values and when we have to recompute them. - -## Want to learn more? - -To learn more about Salsa, try one of the following: - -- read the [heavily commented `hello_world` example](https://github.com/salsa-rs/salsa/blob/master/examples/hello_world/main.rs); -- check out the [Salsa book](https://salsa-rs.github.io/salsa); -- watch one of our [videos](https://salsa-rs.github.io/salsa/videos.html). - -## Getting in touch - -The bulk of the discussion happens in the [issues](https://github.com/salsa-rs/salsa/issues) -and [pull requests](https://github.com/salsa-rs/salsa/pulls), -but we have a [zulip chat](https://salsa.zulipchat.com/) as well. diff --git a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/Cargo.toml b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/Cargo.toml deleted file mode 100644 index 3c2daacaf9501..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "salsa-macros" -version = "0.0.0" -authors = ["Salsa developers"] -edition = "2021" -license = "Apache-2.0 OR MIT" -repository = "https://github.com/salsa-rs/salsa" -description = "Procedural macros for the salsa crate" - -rust-version.workspace = true - -[lib] -proc-macro = true -name = "ra_salsa_macros" - -[dependencies] -heck = "0.5.0" -proc-macro2 = "1.0" -quote = "1.0" -syn = { version = "2.0", features = ["full", "extra-traits"] } - -[lints] -workspace = true diff --git a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/LICENSE-APACHE b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/LICENSE-APACHE deleted file mode 100644 index 0bf2cad6488f5..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-APACHE diff --git a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/LICENSE-MIT b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/LICENSE-MIT deleted file mode 100644 index d99cce5f72063..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/LICENSE-MIT +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-MIT diff --git a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/README.md b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/README.md deleted file mode 100644 index 94389aee61a0e..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/README.md +++ /dev/null @@ -1 +0,0 @@ -../README.md diff --git a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/database_storage.rs b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/database_storage.rs deleted file mode 100644 index 63ab84a621e7e..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/database_storage.rs +++ /dev/null @@ -1,243 +0,0 @@ -//! Implementation for `[ra_salsa::database]` decorator. - -use heck::ToSnakeCase; -use proc_macro::TokenStream; -use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::{Ident, ItemStruct, Path, Token}; - -type PunctuatedQueryGroups = Punctuated; - -pub(crate) fn database(args: TokenStream, input: TokenStream) -> TokenStream { - let args = syn::parse_macro_input!(args as QueryGroupList); - let input = syn::parse_macro_input!(input as ItemStruct); - - let query_groups = &args.query_groups; - let database_name = &input.ident; - let visibility = &input.vis; - let db_storage_field = quote! { storage }; - - let mut output = proc_macro2::TokenStream::new(); - output.extend(quote! { #input }); - - let query_group_names_snake: Vec<_> = query_groups - .iter() - .map(|query_group| { - let group_name = query_group.name(); - Ident::new(&group_name.to_string().to_snake_case(), group_name.span()) - }) - .collect(); - - let query_group_storage_names: Vec<_> = query_groups - .iter() - .map(|QueryGroup { group_path }| { - quote! { - <#group_path as ra_salsa::plumbing::QueryGroup>::GroupStorage - } - }) - .collect(); - - // For each query group `foo::MyGroup` create a link to its - // `foo::MyGroupGroupStorage` - let mut storage_fields = proc_macro2::TokenStream::new(); - let mut storage_initializers = proc_macro2::TokenStream::new(); - let mut has_group_impls = proc_macro2::TokenStream::new(); - for (((query_group, group_name_snake), group_storage), group_index) in query_groups - .iter() - .zip(&query_group_names_snake) - .zip(&query_group_storage_names) - .zip(0_u16..) - { - let group_path = &query_group.group_path; - - // rewrite the last identifier (`MyGroup`, above) to - // (e.g.) `MyGroupGroupStorage`. - storage_fields.extend(quote! { - #group_name_snake: #group_storage, - }); - - // rewrite the last identifier (`MyGroup`, above) to - // (e.g.) `MyGroupGroupStorage`. - storage_initializers.extend(quote! { - #group_name_snake: #group_storage::new(#group_index), - }); - - // ANCHOR:HasQueryGroup - has_group_impls.extend(quote! { - impl ra_salsa::plumbing::HasQueryGroup<#group_path> for #database_name { - fn group_storage(&self) -> &#group_storage { - &self.#db_storage_field.query_store().#group_name_snake - } - - fn group_storage_mut(&mut self) -> (&#group_storage, &mut ra_salsa::Runtime) { - let (query_store_mut, runtime) = self.#db_storage_field.query_store_mut(); - (&query_store_mut.#group_name_snake, runtime) - } - } - }); - // ANCHOR_END:HasQueryGroup - } - - // create group storage wrapper struct - output.extend(quote! { - #[doc(hidden)] - #visibility struct __SalsaDatabaseStorage { - #storage_fields - } - - impl Default for __SalsaDatabaseStorage { - fn default() -> Self { - Self { - #storage_initializers - } - } - } - }); - - // Create a tuple (D1, D2, ...) where Di is the data for a given query group. - let mut database_data = vec![]; - for QueryGroup { group_path } in query_groups { - database_data.push(quote! { - <#group_path as ra_salsa::plumbing::QueryGroup>::GroupData - }); - } - - // ANCHOR:DatabaseStorageTypes - output.extend(quote! { - impl ra_salsa::plumbing::DatabaseStorageTypes for #database_name { - type DatabaseStorage = __SalsaDatabaseStorage; - } - }); - // ANCHOR_END:DatabaseStorageTypes - - // ANCHOR:DatabaseOps - let mut fmt_ops = proc_macro2::TokenStream::new(); - let mut maybe_changed_ops = proc_macro2::TokenStream::new(); - let mut cycle_recovery_strategy_ops = proc_macro2::TokenStream::new(); - let mut for_each_ops = proc_macro2::TokenStream::new(); - for ((QueryGroup { group_path }, group_storage), group_index) in - query_groups.iter().zip(&query_group_storage_names).zip(0_u16..) - { - fmt_ops.extend(quote! { - #group_index => { - let storage: &#group_storage = - >::group_storage(self); - storage.fmt_index(self, input, fmt) - } - }); - maybe_changed_ops.extend(quote! { - #group_index => { - let storage: &#group_storage = - >::group_storage(self); - storage.maybe_changed_after(self, input, revision) - } - }); - cycle_recovery_strategy_ops.extend(quote! { - #group_index => { - let storage: &#group_storage = - >::group_storage(self); - storage.cycle_recovery_strategy(self, input) - } - }); - for_each_ops.extend(quote! { - let storage: &#group_storage = - >::group_storage(self); - storage.for_each_query(runtime, &mut op); - }); - } - output.extend(quote! { - impl ra_salsa::plumbing::DatabaseOps for #database_name { - fn ops_database(&self) -> &dyn ra_salsa::Database { - self - } - - fn ops_salsa_runtime(&self) -> &ra_salsa::Runtime { - self.#db_storage_field.salsa_runtime() - } - - fn synthetic_write(&mut self, durability: ra_salsa::Durability) { - self.#db_storage_field.salsa_runtime_mut().synthetic_write(durability) - } - - fn fmt_index( - &self, - input: ra_salsa::DatabaseKeyIndex, - fmt: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - match input.group_index() { - #fmt_ops - i => panic!("ra_salsa: invalid group index {}", i) - } - } - - fn maybe_changed_after( - &self, - input: ra_salsa::DatabaseKeyIndex, - revision: ra_salsa::Revision - ) -> bool { - match input.group_index() { - #maybe_changed_ops - i => panic!("ra_salsa: invalid group index {}", i) - } - } - - fn cycle_recovery_strategy( - &self, - input: ra_salsa::DatabaseKeyIndex, - ) -> ra_salsa::plumbing::CycleRecoveryStrategy { - match input.group_index() { - #cycle_recovery_strategy_ops - i => panic!("ra_salsa: invalid group index {}", i) - } - } - - fn for_each_query( - &self, - mut op: &mut dyn FnMut(&dyn ra_salsa::plumbing::QueryStorageMassOps), - ) { - let runtime = ra_salsa::Database::salsa_runtime(self); - #for_each_ops - } - } - }); - // ANCHOR_END:DatabaseOps - - output.extend(has_group_impls); - - output.into() -} - -#[derive(Clone, Debug)] -struct QueryGroupList { - query_groups: PunctuatedQueryGroups, -} - -impl Parse for QueryGroupList { - fn parse(input: ParseStream<'_>) -> syn::Result { - let query_groups: PunctuatedQueryGroups = - input.parse_terminated(QueryGroup::parse, Token![,])?; - Ok(QueryGroupList { query_groups }) - } -} - -#[derive(Clone, Debug)] -struct QueryGroup { - group_path: Path, -} - -impl QueryGroup { - /// The name of the query group trait. - fn name(&self) -> Ident { - self.group_path.segments.last().unwrap().ident.clone() - } -} - -impl Parse for QueryGroup { - /// ```ignore - /// impl HelloWorldDatabase; - /// ``` - fn parse(input: ParseStream<'_>) -> syn::Result { - let group_path: Path = input.parse()?; - Ok(QueryGroup { group_path }) - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/lib.rs b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/lib.rs deleted file mode 100644 index d3e17c5ebf1d4..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/lib.rs +++ /dev/null @@ -1,125 +0,0 @@ -//! This crate provides salsa's macros and attributes. - -#![recursion_limit = "256"] - -#[macro_use] -extern crate quote; - -use proc_macro::TokenStream; - -mod database_storage; -mod parenthesized; -mod query_group; - -/// The decorator that defines a salsa "query group" trait. This is a -/// trait that defines everything that a block of queries need to -/// execute, as well as defining the queries themselves that are -/// exported for others to use. -/// -/// This macro declares the "prototype" for a group of queries. It will -/// expand into a trait and a set of structs, one per query. -/// -/// For each query, you give the name of the accessor method to invoke -/// the query (e.g., `my_query`, below), as well as its parameter -/// types and the output type. You also give the name for a query type -/// (e.g., `MyQuery`, below) that represents the query, and optionally -/// other details, such as its storage. -/// -/// # Examples -/// -/// The simplest example is something like this: -/// -/// ```ignore -/// #[salsa::query_group] -/// trait TypeckDatabase { -/// #[salsa::input] // see below for other legal attributes -/// fn my_query(&self, input: u32) -> u64; -/// -/// /// Queries can have any number of inputs (including zero); if there -/// /// is not exactly one input, then the key type will be -/// /// a tuple of the input types, so in this case `(u32, f32)`. -/// fn other_query(&self, input1: u32, input2: f32) -> u64; -/// } -/// ``` -/// -/// Here is a list of legal `salsa::XXX` attributes: -/// -/// - Storage attributes: control how the query data is stored and set. These -/// are described in detail in the section below. -/// - `#[salsa::input]` -/// - `#[salsa::memoized]` -/// - `#[salsa::dependencies]` -/// - Query execution: -/// - `#[salsa::invoke(path::to::my_fn)]` -- for a non-input, this -/// indicates the function to call when a query must be -/// recomputed. The default is to call a function in the same -/// module with the same name as the query. -/// - `#[query_type(MyQueryTypeName)]` specifies the name of the -/// dummy struct created for the query. Default is the name of the -/// query, in camel case, plus the word "Query" (e.g., -/// `MyQueryQuery` and `OtherQueryQuery` in the examples above). -/// -/// # Storage attributes -/// -/// Here are the possible storage values for each query. The default -/// is `storage memoized`. -/// -/// ## Input queries -/// -/// Specifying `storage input` will give you an **input -/// query**. Unlike derived queries, whose value is given by a -/// function, input queries are explicitly set by doing -/// `db.query(QueryType).set(key, value)` (where `QueryType` is the -/// `type` specified for the query). Accessing a value that has not -/// yet been set will panic. Each time you invoke `set`, we assume the -/// value has changed, and so we will potentially re-execute derived -/// queries that read (transitively) from this input. -/// -/// ## Derived queries -/// -/// Derived queries are specified by a function. -/// -/// - `#[salsa::memoized]` (the default) -- The result is memoized -/// between calls. If the inputs have changed, we will recompute -/// the value, but then compare against the old memoized value, -/// which can significantly reduce the amount of recomputation -/// required in new revisions. This does require that the value -/// implements `Eq`. -/// - `#[salsa::dependencies]` -- does not cache the value, so it will -/// be recomputed every time it is needed. We do track the inputs, however, -/// so if they have not changed, then things that rely on this query -/// may be known not to have changed. -/// -/// ## Attribute combinations -/// -/// Some attributes are mutually exclusive. For example, it is an error to add -/// multiple storage specifiers or to annotate a function to `invoke` on an -/// `input` query. -#[proc_macro_attribute] -pub fn query_group(args: TokenStream, input: TokenStream) -> TokenStream { - query_group::query_group(args, input) -} - -/// This attribute is placed on your database struct. It takes a list of the -/// query groups that your database supports. The format looks like so: -/// -/// ```rust,ignore -/// #[salsa::database(MyQueryGroup1, MyQueryGroup2)] -/// struct MyDatabase { -/// runtime: salsa::Runtime, // <-- your database will need this field, too -/// } -/// ``` -/// -/// Here, the struct `MyDatabase` would support the two query groups -/// `MyQueryGroup1` and `MyQueryGroup2`. In addition to the `database` -/// attribute, the struct needs to have a `runtime` field (of type -/// [`salsa::Runtime`]) and to implement the `salsa::Database` trait. -/// -/// See [the `hello_world` example][hw] for more details. -/// -/// [`salsa::Runtime`]: struct.Runtime.html -/// [hw]: https://github.com/salsa-rs/salsa/tree/master/examples/hello_world -#[proc_macro_attribute] -pub fn database(args: TokenStream, input: TokenStream) -> TokenStream { - database_storage::database(args, input) -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/parenthesized.rs b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/parenthesized.rs deleted file mode 100644 index 5ecd1b8a05838..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/parenthesized.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! Parenthesis helper -pub(crate) struct Parenthesized(pub(crate) T); - -impl syn::parse::Parse for Parenthesized -where - T: syn::parse::Parse, -{ - fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { - let content; - syn::parenthesized!(content in input); - content.parse::().map(Parenthesized) - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/query_group.rs b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/query_group.rs deleted file mode 100644 index d761a5e798e89..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/query_group.rs +++ /dev/null @@ -1,753 +0,0 @@ -//! Implementation for `[ra_salsa::query_group]` decorator. - -use crate::parenthesized::Parenthesized; -use heck::ToUpperCamelCase; -use proc_macro::TokenStream; -use proc_macro2::Span; -use quote::ToTokens; -use syn::{ - parse_macro_input, parse_quote, spanned::Spanned, Attribute, Error, FnArg, Ident, ItemTrait, - ReturnType, TraitItem, Type, -}; - -/// Implementation for `[ra_salsa::query_group]` decorator. -pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream { - let group_struct = parse_macro_input!(args as Ident); - let input: ItemTrait = parse_macro_input!(input as ItemTrait); - // println!("args: {:#?}", args); - // println!("input: {:#?}", input); - - let input_span = input.span(); - let (trait_attrs, salsa_attrs) = filter_attrs(input.attrs); - if !salsa_attrs.is_empty() { - return Error::new(input_span, format!("unsupported attributes: {salsa_attrs:?}")) - .to_compile_error() - .into(); - } - - let trait_vis = input.vis; - let trait_name = input.ident; - let _generics = input.generics.clone(); - let dyn_db = quote! { dyn #trait_name }; - - // Decompose the trait into the corresponding queries. - let mut queries = vec![]; - for item in input.items { - if let TraitItem::Fn(method) = item { - let query_name = method.sig.ident.to_string(); - - let mut storage = QueryStorage::Memoized; - let mut cycle = None; - let mut invoke = None; - - let mut query_type = - format_ident!("{}Query", query_name.to_string().to_upper_camel_case()); - let mut num_storages = 0; - - // Extract attributes. - let (attrs, salsa_attrs) = filter_attrs(method.attrs); - for SalsaAttr { name, tts, span } in salsa_attrs { - match name.as_str() { - "memoized" => { - storage = QueryStorage::Memoized; - num_storages += 1; - } - "dependencies" => { - storage = QueryStorage::LruDependencies; - num_storages += 1; - } - "lru" => { - storage = QueryStorage::LruMemoized; - num_storages += 1; - } - "input" => { - storage = QueryStorage::Input; - num_storages += 1; - } - "interned" => { - storage = QueryStorage::Interned; - num_storages += 1; - } - "cycle" => { - cycle = Some(parse_macro_input!(tts as Parenthesized).0); - } - "invoke" => { - invoke = Some(parse_macro_input!(tts as Parenthesized).0); - } - "query_type" => { - query_type = parse_macro_input!(tts as Parenthesized).0; - } - "transparent" => { - storage = QueryStorage::Transparent; - num_storages += 1; - } - _ => { - return Error::new(span, format!("unknown ra_salsa attribute `{name}`")) - .to_compile_error() - .into(); - } - } - } - - let sig_span = method.sig.span(); - // Check attribute combinations. - if num_storages > 1 { - return Error::new(sig_span, "multiple storage attributes specified") - .to_compile_error() - .into(); - } - match &invoke { - Some(invoke) if storage == QueryStorage::Input => { - return Error::new( - invoke.span(), - "#[ra_salsa::invoke] cannot be set on #[ra_salsa::input] queries", - ) - .to_compile_error() - .into(); - } - _ => {} - } - - // Extract keys. - let mut iter = method.sig.inputs.iter(); - let self_receiver = match iter.next() { - Some(FnArg::Receiver(sr)) if sr.mutability.is_none() => sr, - _ => { - return Error::new( - sig_span, - format!("first argument of query `{query_name}` must be `&self`"), - ) - .to_compile_error() - .into(); - } - }; - let mut keys: Vec<(Ident, Type)> = vec![]; - for (idx, arg) in iter.enumerate() { - match arg { - FnArg::Typed(syn::PatType { pat, ty, .. }) => keys.push(( - match pat.as_ref() { - syn::Pat::Ident(ident_pat) => ident_pat.ident.clone(), - _ => format_ident!("key{}", idx), - }, - Type::clone(ty), - )), - arg => { - return Error::new( - arg.span(), - format!("unsupported argument `{arg:?}` of `{query_name}`",), - ) - .to_compile_error() - .into(); - } - } - } - - // Extract value. - let value = match method.sig.output { - ReturnType::Type(_, ref ty) => ty.as_ref().clone(), - ref ret => { - return Error::new( - ret.span(), - format!("unsupported return type `{ret:?}` of `{query_name}`"), - ) - .to_compile_error() - .into(); - } - }; - - // For `#[ra_salsa::interned]` keys, we create a "lookup key" automatically. - // - // For a query like: - // - // fn foo(&self, x: Key1, y: Key2) -> u32 - // - // we would create - // - // fn lookup_foo(&self, x: u32) -> (Key1, Key2) - let lookup_query = if let QueryStorage::Interned = storage { - let lookup_query_type = - format_ident!("{}LookupQuery", query_name.to_string().to_upper_camel_case()); - let lookup_fn_name = format_ident!("lookup_{}", query_name); - let keys = keys.iter().map(|(_, ty)| ty); - let lookup_value: Type = parse_quote!((#(#keys),*)); - let lookup_keys = vec![(parse_quote! { key }, value.clone())]; - Some(Query { - query_type: lookup_query_type, - query_name: format!("{lookup_fn_name}"), - fn_name: lookup_fn_name, - receiver: self_receiver.clone(), - attrs: vec![], // FIXME -- some automatically generated docs on this method? - storage: QueryStorage::InternedLookup { intern_query_type: query_type.clone() }, - keys: lookup_keys, - value: lookup_value, - invoke: None, - cycle: cycle.clone(), - }) - } else { - None - }; - - queries.push(Query { - query_type, - query_name, - fn_name: method.sig.ident, - receiver: self_receiver.clone(), - attrs, - storage, - keys, - value, - invoke, - cycle, - }); - - queries.extend(lookup_query); - } - } - - let group_storage = format_ident!("{}GroupStorage__", trait_name, span = Span::call_site()); - - let mut query_fn_declarations = proc_macro2::TokenStream::new(); - let mut query_fn_definitions = proc_macro2::TokenStream::new(); - let mut storage_fields = proc_macro2::TokenStream::new(); - let mut queries_with_storage = vec![]; - for query in &queries { - #[allow(clippy::map_identity)] - // clippy is incorrect here, this is not the identity function due to match ergonomics - let (key_names, keys): (Vec<_>, Vec<_>) = query.keys.iter().map(|(a, b)| (a, b)).unzip(); - let value = &query.value; - let fn_name = &query.fn_name; - let qt = &query.query_type; - let attrs = &query.attrs; - let self_receiver = &query.receiver; - - query_fn_declarations.extend(quote! { - #(#attrs)* - fn #fn_name(#self_receiver, #(#key_names: #keys),*) -> #value; - }); - - // Special case: transparent queries don't create actual storage, - // just inline the definition - if let QueryStorage::Transparent = query.storage { - let invoke = query.invoke_tt(); - query_fn_definitions.extend(quote! { - fn #fn_name(&self, #(#key_names: #keys),*) -> #value { - #invoke(self, #(#key_names),*) - } - }); - continue; - } - - queries_with_storage.push(fn_name); - - let tracing = if let QueryStorage::Memoized | QueryStorage::LruMemoized = query.storage { - let s = format!("{trait_name}::{fn_name}"); - Some(quote! { - let _p = tracing::trace_span!(#s, #(#key_names = tracing::field::debug(&#key_names)),*).entered(); - }) - } else { - None - } - .into_iter(); - - query_fn_definitions.extend(quote! { - fn #fn_name(&self, #(#key_names: #keys),*) -> #value { - #(#tracing),* - // Create a shim to force the code to be monomorphized in the - // query crate. Our experiments revealed that this makes a big - // difference in total compilation time in rust-analyzer, though - // it's not totally obvious why that should be. - fn __shim(db: &(dyn #trait_name + '_), #(#key_names: #keys),*) -> #value { - ra_salsa::plumbing::get_query_table::<#qt>(db).get((#(#key_names),*)) - } - __shim(self, #(#key_names),*) - - } - }); - - // For input queries, we need `set_foo` etc - if let QueryStorage::Input = query.storage { - let set_fn_name = format_ident!("set_{}", fn_name); - let set_with_durability_fn_name = format_ident!("set_{}_with_durability", fn_name); - - let set_fn_docs = format!( - " - Set the value of the `{fn_name}` input. - - See `{fn_name}` for details. - - *Note:* Setting values will trigger cancellation - of any ongoing queries; this method blocks until - those queries have been cancelled. - " - ); - - let set_constant_fn_docs = format!( - " - Set the value of the `{fn_name}` input with a - specific durability instead of the default of - `Durability::LOW`. You can use `Durability::MAX` - to promise that its value will never change again. - - See `{fn_name}` for details. - - *Note:* Setting values will trigger cancellation - of any ongoing queries; this method blocks until - those queries have been cancelled. - " - ); - - query_fn_declarations.extend(quote! { - # [doc = #set_fn_docs] - fn #set_fn_name(&mut self, #(#key_names: #keys,)* value__: #value); - - - # [doc = #set_constant_fn_docs] - fn #set_with_durability_fn_name(&mut self, #(#key_names: #keys,)* value__: #value, durability__: ra_salsa::Durability); - }); - - query_fn_definitions.extend(quote! { - fn #set_fn_name(&mut self, #(#key_names: #keys,)* value__: #value) { - fn __shim(db: &mut dyn #trait_name, #(#key_names: #keys,)* value__: #value) { - ra_salsa::plumbing::get_query_table_mut::<#qt>(db).set((#(#key_names),*), value__) - } - __shim(self, #(#key_names,)* value__) - } - - fn #set_with_durability_fn_name(&mut self, #(#key_names: #keys,)* value__: #value, durability__: ra_salsa::Durability) { - fn __shim(db: &mut dyn #trait_name, #(#key_names: #keys,)* value__: #value, durability__: ra_salsa::Durability) { - ra_salsa::plumbing::get_query_table_mut::<#qt>(db).set_with_durability((#(#key_names),*), value__, durability__) - } - __shim(self, #(#key_names,)* value__ ,durability__) - } - }); - } - - // A field for the storage struct - storage_fields.extend(quote! { - #fn_name: std::sync::Arc<<#qt as ra_salsa::Query>::Storage>, - }); - } - - // Emit the trait itself. - let mut output = { - let bounds = &input.supertraits; - quote! { - #(#trait_attrs)* - #trait_vis trait #trait_name : - ra_salsa::Database + - ra_salsa::plumbing::HasQueryGroup<#group_struct> + - #bounds - { - #query_fn_declarations - } - } - }; - - // Emit the query group struct and impl of `QueryGroup`. - output.extend(quote! { - /// Representative struct for the query group. - #trait_vis struct #group_struct { } - - impl ra_salsa::plumbing::QueryGroup for #group_struct - { - type DynDb = #dyn_db; - type GroupStorage = #group_storage; - } - }); - - // Emit an impl of the trait - output.extend({ - let bounds = input.supertraits; - quote! { - impl #trait_name for DB - where - DB: #bounds, - DB: ra_salsa::Database, - DB: ra_salsa::plumbing::HasQueryGroup<#group_struct>, - { - #query_fn_definitions - } - } - }); - - let non_transparent_queries = - || queries.iter().filter(|q| !matches!(q.storage, QueryStorage::Transparent)); - - // Emit the query types. - for (query, query_index) in non_transparent_queries().zip(0_u16..) { - let fn_name = &query.fn_name; - let qt = &query.query_type; - - let storage = match &query.storage { - QueryStorage::Memoized => quote!(ra_salsa::plumbing::MemoizedStorage), - QueryStorage::LruMemoized => quote!(ra_salsa::plumbing::LruMemoizedStorage), - QueryStorage::LruDependencies => { - quote!(ra_salsa::plumbing::LruDependencyStorage) - } - QueryStorage::Input if query.keys.is_empty() => { - quote!(ra_salsa::plumbing::UnitInputStorage) - } - QueryStorage::Input => quote!(ra_salsa::plumbing::InputStorage), - QueryStorage::Interned => quote!(ra_salsa::plumbing::InternedStorage), - QueryStorage::InternedLookup { intern_query_type } => { - quote!(ra_salsa::plumbing::LookupInternedStorage) - } - QueryStorage::Transparent => panic!("should have been filtered"), - }; - let keys = query.keys.iter().map(|(_, ty)| ty); - let value = &query.value; - let query_name = &query.query_name; - - // Emit the query struct and implement the Query trait on it. - output.extend(quote! { - #[derive(Default, Debug)] - #trait_vis struct #qt; - }); - - output.extend(quote! { - impl #qt { - /// Get access to extra methods pertaining to this query. - /// You can also use it to invoke this query. - #trait_vis fn in_db(self, db: &#dyn_db) -> ra_salsa::QueryTable<'_, Self> - { - ra_salsa::plumbing::get_query_table::<#qt>(db) - } - } - }); - - output.extend(quote! { - impl #qt { - /// Like `in_db`, but gives access to methods for setting the - /// value of an input. Not applicable to derived queries. - /// - /// # Threads, cancellation, and blocking - /// - /// Mutating the value of a query cannot be done while there are - /// still other queries executing. If you are using your database - /// within a single thread, this is not a problem: you only have - /// `&self` access to the database, but this method requires `&mut - /// self`. - /// - /// However, if you have used `snapshot` to create other threads, - /// then attempts to `set` will **block the current thread** until - /// those snapshots are dropped (usually when those threads - /// complete). This also implies that if you create a snapshot but - /// do not send it to another thread, then invoking `set` will - /// deadlock. - /// - /// Before blocking, the thread that is attempting to `set` will - /// also set a cancellation flag. This will cause any query - /// invocations in other threads to unwind with a `Cancelled` - /// sentinel value and eventually let the `set` succeed once all - /// threads have unwound past the ra_salsa invocation. - /// - /// If your query implementations are performing expensive - /// operations without invoking another query, you can also use - /// the `Runtime::unwind_if_cancelled` method to check for an - /// ongoing cancellation and bring those operations to a close, - /// thus allowing the `set` to succeed. Otherwise, long-running - /// computations may lead to "starvation", meaning that the - /// thread attempting to `set` has to wait a long, long time. =) - #trait_vis fn in_db_mut(self, db: &mut #dyn_db) -> ra_salsa::QueryTableMut<'_, Self> - { - ra_salsa::plumbing::get_query_table_mut::<#qt>(db) - } - } - - impl<'d> ra_salsa::QueryDb<'d> for #qt - { - type DynDb = #dyn_db + 'd; - type Group = #group_struct; - type GroupStorage = #group_storage; - } - - // ANCHOR:Query_impl - impl ra_salsa::Query for #qt - { - type Key = (#(#keys),*); - type Value = #value; - type Storage = #storage; - - const QUERY_INDEX: u16 = #query_index; - - const QUERY_NAME: &'static str = #query_name; - - fn query_storage<'a>( - group_storage: &'a >::GroupStorage, - ) -> &'a std::sync::Arc { - &group_storage.#fn_name - } - - fn query_storage_mut<'a>( - group_storage: &'a >::GroupStorage, - ) -> &'a std::sync::Arc { - &group_storage.#fn_name - } - } - // ANCHOR_END:Query_impl - }); - - // Implement the QueryFunction trait for queries which need it. - if query.storage.needs_query_function() { - let span = query.fn_name.span(); - - let key_names: Vec<_> = query.keys.iter().map(|(pat, _)| pat).collect(); - let key_pattern = if query.keys.len() == 1 { - quote! { #(#key_names),* } - } else { - quote! { (#(#key_names),*) } - }; - let invoke = query.invoke_tt(); - - let recover = if let Some(cycle_recovery_fn) = &query.cycle { - quote! { - const CYCLE_STRATEGY: ra_salsa::plumbing::CycleRecoveryStrategy = - ra_salsa::plumbing::CycleRecoveryStrategy::Fallback; - fn cycle_fallback(db: &>::DynDb, cycle: &ra_salsa::Cycle, #key_pattern: &::Key) - -> ::Value { - #cycle_recovery_fn( - db, - cycle, - #(#key_names),* - ) - } - } - } else { - quote! { - const CYCLE_STRATEGY: ra_salsa::plumbing::CycleRecoveryStrategy = - ra_salsa::plumbing::CycleRecoveryStrategy::Panic; - } - }; - - output.extend(quote_spanned! {span=> - // ANCHOR:QueryFunction_impl - impl ra_salsa::plumbing::QueryFunction for #qt - { - fn execute(db: &>::DynDb, #key_pattern: ::Key) - -> ::Value { - #invoke(db, #(#key_names),*) - } - - #recover - } - // ANCHOR_END:QueryFunction_impl - }); - } - } - - let mut fmt_ops = proc_macro2::TokenStream::new(); - for (Query { fn_name, .. }, query_index) in non_transparent_queries().zip(0_u16..) { - fmt_ops.extend(quote! { - #query_index => { - ra_salsa::plumbing::QueryStorageOps::fmt_index( - &*self.#fn_name, db, input.key_index(), fmt, - ) - } - }); - } - - let mut maybe_changed_ops = proc_macro2::TokenStream::new(); - for (Query { fn_name, .. }, query_index) in non_transparent_queries().zip(0_u16..) { - maybe_changed_ops.extend(quote! { - #query_index => { - ra_salsa::plumbing::QueryStorageOps::maybe_changed_after( - &*self.#fn_name, db, input.key_index(), revision - ) - } - }); - } - - let mut cycle_recovery_strategy_ops = proc_macro2::TokenStream::new(); - for (Query { fn_name, .. }, query_index) in non_transparent_queries().zip(0_u16..) { - cycle_recovery_strategy_ops.extend(quote! { - #query_index => { - ra_salsa::plumbing::QueryStorageOps::cycle_recovery_strategy( - &*self.#fn_name - ) - } - }); - } - - let mut for_each_ops = proc_macro2::TokenStream::new(); - for Query { fn_name, .. } in non_transparent_queries() { - for_each_ops.extend(quote! { - op(&*self.#fn_name); - }); - } - - // Emit query group storage struct - output.extend(quote! { - #trait_vis struct #group_storage { - #storage_fields - } - - // ANCHOR:group_storage_new - impl #group_storage { - #trait_vis fn new(group_index: u16) -> Self { - #group_storage { - #( - #queries_with_storage: - std::sync::Arc::new(ra_salsa::plumbing::QueryStorageOps::new(group_index)), - )* - } - } - } - // ANCHOR_END:group_storage_new - - // ANCHOR:group_storage_methods - impl #group_storage { - #trait_vis fn fmt_index( - &self, - db: &(#dyn_db + '_), - input: ra_salsa::DatabaseKeyIndex, - fmt: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - match input.query_index() { - #fmt_ops - i => panic!("ra_salsa: impossible query index {}", i), - } - } - - #trait_vis fn maybe_changed_after( - &self, - db: &(#dyn_db + '_), - input: ra_salsa::DatabaseKeyIndex, - revision: ra_salsa::Revision, - ) -> bool { - match input.query_index() { - #maybe_changed_ops - i => panic!("ra_salsa: impossible query index {}", i), - } - } - - #trait_vis fn cycle_recovery_strategy( - &self, - db: &(#dyn_db + '_), - input: ra_salsa::DatabaseKeyIndex, - ) -> ra_salsa::plumbing::CycleRecoveryStrategy { - match input.query_index() { - #cycle_recovery_strategy_ops - i => panic!("ra_salsa: impossible query index {}", i), - } - } - - #trait_vis fn for_each_query( - &self, - _runtime: &ra_salsa::Runtime, - mut op: &mut dyn FnMut(&dyn ra_salsa::plumbing::QueryStorageMassOps), - ) { - #for_each_ops - } - } - // ANCHOR_END:group_storage_methods - }); - output.into() -} - -struct SalsaAttr { - name: String, - tts: TokenStream, - span: Span, -} - -impl std::fmt::Debug for SalsaAttr { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(fmt, "{:?}", self.name) - } -} - -impl TryFrom for SalsaAttr { - type Error = syn::Attribute; - - fn try_from(attr: syn::Attribute) -> Result { - if is_not_salsa_attr_path(attr.path()) { - return Err(attr); - } - - let span = attr.span(); - let name = attr.path().segments[1].ident.to_string(); - let tts = match attr.meta { - syn::Meta::Path(path) => path.into_token_stream(), - syn::Meta::List(ref list) => { - let tts = list - .into_token_stream() - .into_iter() - .skip(attr.path().to_token_stream().into_iter().count()); - proc_macro2::TokenStream::from_iter(tts) - } - syn::Meta::NameValue(nv) => nv.into_token_stream(), - } - .into(); - - Ok(SalsaAttr { name, tts, span }) - } -} - -fn is_not_salsa_attr_path(path: &syn::Path) -> bool { - path.segments.first().map(|s| s.ident != "ra_salsa").unwrap_or(true) || path.segments.len() != 2 -} - -fn filter_attrs(attrs: Vec) -> (Vec, Vec) { - let mut other = vec![]; - let mut ra_salsa = vec![]; - // Leave non-ra_salsa attributes untouched. These are - // attributes that don't start with `ra_salsa::` or don't have - // exactly two segments in their path. - // Keep the ra_salsa attributes around. - for attr in attrs { - match SalsaAttr::try_from(attr) { - Ok(it) => ra_salsa.push(it), - Err(it) => other.push(it), - } - } - (other, ra_salsa) -} - -#[derive(Debug)] -struct Query { - fn_name: Ident, - receiver: syn::Receiver, - query_name: String, - attrs: Vec, - query_type: Ident, - storage: QueryStorage, - keys: Vec<(Ident, syn::Type)>, - value: syn::Type, - invoke: Option, - cycle: Option, -} - -impl Query { - fn invoke_tt(&self) -> proc_macro2::TokenStream { - match &self.invoke { - Some(i) => i.into_token_stream(), - None => self.fn_name.clone().into_token_stream(), - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -enum QueryStorage { - Memoized, - LruDependencies, - LruMemoized, - Input, - Interned, - InternedLookup { intern_query_type: Ident }, - Transparent, -} - -impl QueryStorage { - /// Do we need a `QueryFunction` impl for this type of query? - fn needs_query_function(&self) -> bool { - match self { - QueryStorage::Input - | QueryStorage::Interned - | QueryStorage::InternedLookup { .. } - | QueryStorage::Transparent => false, - QueryStorage::Memoized | QueryStorage::LruMemoized | QueryStorage::LruDependencies => { - true - } - } - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/debug.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/debug.rs deleted file mode 100644 index 5f113541f04cf..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/debug.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Debugging APIs: these are meant for use when unit-testing or -//! debugging your application but aren't ordinarily needed. - -use crate::durability::Durability; -use crate::plumbing::QueryStorageOps; -use crate::Query; -use crate::QueryTable; - -/// Additional methods on queries that can be used to "peek into" -/// their current state. These methods are meant for debugging and -/// observing the effects of garbage collection etc. -pub trait DebugQueryTable { - /// Key of this query. - type Key; - - /// Value of this query. - type Value; - - /// Returns a lower bound on the durability for the given key. - /// This is typically the minimum durability of all values that - /// the query accessed, but we may return a lower durability in - /// some cases. - fn durability(&self, key: Self::Key) -> Durability; - - /// Get the (current) set of the entries in the query table. - fn entries(&self) -> C - where - C: FromIterator>; -} - -/// An entry from a query table, for debugging and inspecting the table state. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -#[non_exhaustive] -pub struct TableEntry { - /// key of the query - pub key: K, - /// value of the query, if it is stored - pub value: Option, -} - -impl TableEntry { - pub(crate) fn new(key: K, value: Option) -> TableEntry { - TableEntry { key, value } - } -} - -impl DebugQueryTable for QueryTable<'_, Q> -where - Q: Query, - Q::Storage: QueryStorageOps, -{ - type Key = Q::Key; - type Value = Q::Value; - - fn durability(&self, key: Q::Key) -> Durability { - self.storage.durability(self.db, &key) - } - - fn entries(&self) -> C - where - C: FromIterator>, - { - self.storage.entries(self.db) - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/derived.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/derived.rs deleted file mode 100644 index 8b2fdd6b19cc8..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/derived.rs +++ /dev/null @@ -1,163 +0,0 @@ -use crate::debug::TableEntry; -use crate::durability::Durability; -use crate::hash::FxIndexMap; -use crate::plumbing::DerivedQueryStorageOps; -use crate::plumbing::QueryFunction; -use crate::plumbing::QueryStorageMassOps; -use crate::plumbing::QueryStorageOps; -use crate::runtime::StampedValue; -use crate::Runtime; -use crate::{Database, DatabaseKeyIndex, QueryDb, Revision}; -use parking_lot::RwLock; -use std::borrow::Borrow; -use std::hash::Hash; -use triomphe::Arc; - -mod slot; -use slot::Slot; - -/// Memoized queries store the result plus a list of the other queries -/// that they invoked. This means we can avoid recomputing them when -/// none of those inputs have changed. -pub type MemoizedStorage = DerivedStorage; - -/// Handles storage where the value is 'derived' by executing a -/// function (in contrast to "inputs"). -pub struct DerivedStorage -where - Q: QueryFunction, -{ - group_index: u16, - slot_map: RwLock>>>, -} - -impl std::panic::RefUnwindSafe for DerivedStorage -where - Q: QueryFunction, - - Q::Key: std::panic::RefUnwindSafe, - Q::Value: std::panic::RefUnwindSafe, -{ -} - -impl DerivedStorage -where - Q: QueryFunction, - Q::Value: Eq, -{ - fn slot(&self, key: &Q::Key) -> Arc> { - if let Some(v) = self.slot_map.read().get(key) { - return v.clone(); - } - - let mut write = self.slot_map.write(); - let entry = write.entry(key.clone()); - let key_index = entry.index() as u32; - let database_key_index = DatabaseKeyIndex { - group_index: self.group_index, - query_index: Q::QUERY_INDEX, - key_index, - }; - entry.or_insert_with(|| Arc::new(Slot::new(database_key_index))).clone() - } -} - -impl QueryStorageOps for DerivedStorage -where - Q: QueryFunction, - Q::Value: Eq, -{ - const CYCLE_STRATEGY: crate::plumbing::CycleRecoveryStrategy = Q::CYCLE_STRATEGY; - - fn new(group_index: u16) -> Self { - DerivedStorage { group_index, slot_map: RwLock::new(FxIndexMap::default()) } - } - - fn fmt_index( - &self, - _db: &>::DynDb, - index: u32, - fmt: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - let slot_map = self.slot_map.read(); - let key = slot_map.get_index(index as usize).unwrap().0; - write!(fmt, "{}::{}({:?})", std::any::type_name::(), Q::QUERY_NAME, key) - } - - fn maybe_changed_after( - &self, - db: &>::DynDb, - index: u32, - revision: Revision, - ) -> bool { - debug_assert!(revision < db.salsa_runtime().current_revision()); - let (key, slot) = { - let read = self.slot_map.read(); - let Some((key, slot)) = read.get_index(index as usize) else { - return false; - }; - (key.clone(), slot.clone()) - }; - slot.maybe_changed_after(db, revision, &key) - } - - fn fetch(&self, db: &>::DynDb, key: &Q::Key) -> Q::Value { - db.unwind_if_cancelled(); - - let slot = self.slot(key); - let StampedValue { value, durability, changed_at } = slot.read(db, key); - - db.salsa_runtime().report_query_read_and_unwind_if_cycle_resulted( - slot.database_key_index(), - durability, - changed_at, - ); - - value - } - - fn durability(&self, db: &>::DynDb, key: &Q::Key) -> Durability { - self.slot_map.read().get(key).map_or(Durability::LOW, |slot| slot.durability(db)) - } - - fn entries(&self, _db: &>::DynDb) -> C - where - C: std::iter::FromIterator>, - { - let slot_map = self.slot_map.read(); - slot_map.iter().filter_map(|(key, slot)| slot.as_table_entry(key)).collect() - } -} - -impl QueryStorageMassOps for DerivedStorage -where - Q: QueryFunction, -{ - fn purge(&self) { - *self.slot_map.write() = Default::default(); - } -} - -impl DerivedQueryStorageOps for DerivedStorage -where - Q: QueryFunction, - Q::Value: Eq, -{ - fn invalidate(&self, runtime: &mut Runtime, key: &S) - where - S: Eq + Hash, - Q::Key: Borrow, - { - runtime.with_incremented_revision(|new_revision| { - let map_read = self.slot_map.read(); - - if let Some(slot) = map_read.get(key) { - if let Some(durability) = slot.invalidate(new_revision) { - return Some(durability); - } - } - - None - }) - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/derived/slot.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/derived/slot.rs deleted file mode 100644 index cfe2c48f411f1..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/derived/slot.rs +++ /dev/null @@ -1,782 +0,0 @@ -use crate::debug::TableEntry; -use crate::durability::Durability; -use crate::plumbing::{DatabaseOps, QueryFunction}; -use crate::revision::Revision; -use crate::runtime::local_state::ActiveQueryGuard; -use crate::runtime::local_state::QueryRevisions; -use crate::runtime::Runtime; -use crate::runtime::RuntimeId; -use crate::runtime::StampedValue; -use crate::runtime::WaitResult; -use crate::Cycle; -use crate::{Database, DatabaseKeyIndex, Event, EventKind, QueryDb}; -use parking_lot::{RawRwLock, RwLock}; -use std::ops::Deref; -use std::sync::atomic::{AtomicBool, Ordering}; -use tracing::trace; - -pub(super) struct Slot -where - Q: QueryFunction, -{ - key_index: u32, - // FIXME: Yeet this - group_index: u16, - state: RwLock>, -} - -/// Defines the "current state" of query's memoized results. -enum QueryState -where - Q: QueryFunction, -{ - NotComputed, - - /// The runtime with the given id is currently computing the - /// result of this query. - InProgress { - id: RuntimeId, - - /// Set to true if any other queries are blocked, - /// waiting for this query to complete. - anyone_waiting: AtomicBool, - }, - - /// We have computed the query already, and here is the result. - Memoized(Memo), -} - -struct Memo { - /// The result of the query, if we decide to memoize it. - value: V, - - /// Last revision when this memo was verified; this begins - /// as the current revision. - pub(crate) verified_at: Revision, - - /// Revision information - revisions: QueryRevisions, -} - -/// Return value of `probe` helper. -enum ProbeState { - /// Another thread was active but has completed. - /// Try again! - Retry, - - /// No entry for this key at all. - NotComputed(G), - - /// There is an entry, but its contents have not been - /// verified in this revision. - Stale(G), - - /// There is an entry which has been verified, - /// and it has the following value-- or, we blocked - /// on another thread, and that resulted in a cycle. - UpToDate(V), -} - -/// Return value of `maybe_changed_after_probe` helper. -enum MaybeChangedSinceProbeState { - /// Another thread was active but has completed. - /// Try again! - Retry, - - /// Value may have changed in the given revision. - ChangedAt(Revision), - - /// There is a stale cache entry that has not been - /// verified in this revision, so we can't say. - Stale(G), -} - -impl Slot -where - Q: QueryFunction, - Q::Value: Eq, -{ - pub(super) fn new(database_key_index: DatabaseKeyIndex) -> Self { - Self { - key_index: database_key_index.key_index, - group_index: database_key_index.group_index, - state: RwLock::new(QueryState::NotComputed), - } - } - - pub(super) fn database_key_index(&self) -> DatabaseKeyIndex { - DatabaseKeyIndex { - group_index: self.group_index, - query_index: Q::QUERY_INDEX, - key_index: self.key_index, - } - } - - pub(super) fn read( - &self, - db: &>::DynDb, - key: &Q::Key, - ) -> StampedValue { - let runtime = db.salsa_runtime(); - - // NB: We don't need to worry about people modifying the - // revision out from under our feet. Either `db` is a frozen - // database, in which case there is a lock, or the mutator - // thread is the current thread, and it will be prevented from - // doing any `set` invocations while the query function runs. - let revision_now = runtime.current_revision(); - - trace!("{:?}: invoked at {:?}", self, revision_now,); - - // First, do a check with a read-lock. - loop { - match self.probe(db, self.state.read(), runtime, revision_now) { - ProbeState::UpToDate(v) => return v, - ProbeState::Stale(..) | ProbeState::NotComputed(..) => break, - ProbeState::Retry => continue, - } - } - - self.read_upgrade(db, key, revision_now) - } - - /// Second phase of a read operation: acquires an upgradable-read - /// and -- if needed -- validates whether inputs have changed, - /// recomputes value, etc. This is invoked after our initial probe - /// shows a potentially out of date value. - fn read_upgrade( - &self, - db: &>::DynDb, - key: &Q::Key, - revision_now: Revision, - ) -> StampedValue { - let runtime = db.salsa_runtime(); - - trace!("{:?}: read_upgrade(revision_now={:?})", self, revision_now,); - - // Check with an upgradable read to see if there is a value - // already. (This permits other readers but prevents anyone - // else from running `read_upgrade` at the same time.) - let mut old_memo = loop { - match self.probe(db, self.state.upgradable_read(), runtime, revision_now) { - ProbeState::UpToDate(v) => return v, - ProbeState::Stale(state) | ProbeState::NotComputed(state) => { - type RwLockUpgradableReadGuard<'a, T> = - lock_api::RwLockUpgradableReadGuard<'a, RawRwLock, T>; - - let mut state = RwLockUpgradableReadGuard::upgrade(state); - match std::mem::replace(&mut *state, QueryState::in_progress(runtime.id())) { - QueryState::Memoized(old_memo) => break Some(old_memo), - QueryState::InProgress { .. } => unreachable!(), - QueryState::NotComputed => break None, - } - } - ProbeState::Retry => continue, - } - }; - - let panic_guard = PanicGuard::new(self, runtime); - let active_query = runtime.push_query(self.database_key_index()); - - // If we have an old-value, it *may* now be stale, since there - // has been a new revision since the last time we checked. So, - // first things first, let's walk over each of our previous - // inputs and check whether they are out of date. - if let Some(memo) = &mut old_memo { - if let Some(value) = memo.verify_value(db.ops_database(), revision_now, &active_query) { - trace!("{:?}: validated old memoized value", self,); - - db.salsa_event(Event { - runtime_id: runtime.id(), - kind: EventKind::DidValidateMemoizedValue { - database_key: self.database_key_index(), - }, - }); - - panic_guard.proceed(old_memo); - - return value; - } - } - - self.execute(db, runtime, revision_now, active_query, panic_guard, old_memo, key) - } - - fn execute( - &self, - db: &>::DynDb, - runtime: &Runtime, - revision_now: Revision, - active_query: ActiveQueryGuard<'_>, - panic_guard: PanicGuard<'_, Q>, - old_memo: Option>, - key: &Q::Key, - ) -> StampedValue { - tracing::trace!("{:?}: executing query", self.database_key_index().debug(db)); - - db.salsa_event(Event { - runtime_id: db.salsa_runtime().id(), - kind: EventKind::WillExecute { database_key: self.database_key_index() }, - }); - - // Query was not previously executed, or value is potentially - // stale, or value is absent. Let's execute! - let value = match Cycle::catch(|| Q::execute(db, key.clone())) { - Ok(v) => v, - Err(cycle) => { - tracing::trace!( - "{:?}: caught cycle {:?}, have strategy {:?}", - self.database_key_index().debug(db), - cycle, - Q::CYCLE_STRATEGY, - ); - match Q::CYCLE_STRATEGY { - crate::plumbing::CycleRecoveryStrategy::Panic => { - panic_guard.proceed(None); - cycle.throw() - } - crate::plumbing::CycleRecoveryStrategy::Fallback => { - if let Some(c) = active_query.take_cycle() { - assert!(c.is(&cycle)); - Q::cycle_fallback(db, &cycle, key) - } else { - // we are not a participant in this cycle - debug_assert!(!cycle - .participant_keys() - .any(|k| k == self.database_key_index())); - cycle.throw() - } - } - } - } - }; - - let mut revisions = active_query.pop(); - - // We assume that query is side-effect free -- that is, does - // not mutate the "inputs" to the query system. Sanity check - // that assumption here, at least to the best of our ability. - assert_eq!( - runtime.current_revision(), - revision_now, - "revision altered during query execution", - ); - - // If the new value is equal to the old one, then it didn't - // really change, even if some of its inputs have. So we can - // "backdate" its `changed_at` revision to be the same as the - // old value. - if let Some(old_memo) = &old_memo { - // Careful: if the value became less durable than it - // used to be, that is a "breaking change" that our - // consumers must be aware of. Becoming *more* durable - // is not. See the test `constant_to_non_constant`. - if revisions.durability >= old_memo.revisions.durability && old_memo.value == value { - trace!( - "read_upgrade({:?}): value is equal, back-dating to {:?}", - self, - old_memo.revisions.changed_at, - ); - - assert!(old_memo.revisions.changed_at <= revisions.changed_at); - revisions.changed_at = old_memo.revisions.changed_at; - } - } - - let new_value = StampedValue { - value, - durability: revisions.durability, - changed_at: revisions.changed_at, - }; - - let memo_value = new_value.value.clone(); - - trace!("read_upgrade({:?}): result.revisions = {:#?}", self, revisions,); - - panic_guard.proceed(Some(Memo { value: memo_value, verified_at: revision_now, revisions })); - - new_value - } - - /// Helper for `read` that does a shallow check (not recursive) if we have an up-to-date value. - /// - /// Invoked with the guard `state` corresponding to the `QueryState` of some `Slot` (the guard - /// can be either read or write). Returns a suitable `ProbeState`: - /// - /// - `ProbeState::UpToDate(r)` if the table has an up-to-date value (or we blocked on another - /// thread that produced such a value). - /// - `ProbeState::StaleOrAbsent(g)` if either (a) there is no memo for this key, (b) the memo - /// has no value; or (c) the memo has not been verified at the current revision. - /// - /// Note that in case `ProbeState::UpToDate`, the lock will have been released. - fn probe( - &self, - db: &>::DynDb, - state: StateGuard, - runtime: &Runtime, - revision_now: Revision, - ) -> ProbeState, StateGuard> - where - StateGuard: Deref>, - { - match &*state { - QueryState::NotComputed => ProbeState::NotComputed(state), - - QueryState::InProgress { id, anyone_waiting } => { - let other_id = *id; - - // NB: `Ordering::Relaxed` is sufficient here, - // as there are no loads that are "gated" on this - // value. Everything that is written is also protected - // by a lock that must be acquired. The role of this - // boolean is to decide *whether* to acquire the lock, - // not to gate future atomic reads. - anyone_waiting.store(true, Ordering::Relaxed); - - self.block_on_or_unwind(db, runtime, other_id, state); - - // Other thread completely normally, so our value may be available now. - ProbeState::Retry - } - - QueryState::Memoized(memo) => { - trace!( - "{:?}: found memoized value, verified_at={:?}, changed_at={:?}", - self, - memo.verified_at, - memo.revisions.changed_at, - ); - - if memo.verified_at < revision_now { - return ProbeState::Stale(state); - } - - let value = &memo.value; - let value = StampedValue { - durability: memo.revisions.durability, - changed_at: memo.revisions.changed_at, - value: value.clone(), - }; - - trace!("{:?}: returning memoized value changed at {:?}", self, value.changed_at); - - ProbeState::UpToDate(value) - } - } - } - - pub(super) fn durability(&self, db: &>::DynDb) -> Durability { - match &*self.state.read() { - QueryState::NotComputed => Durability::LOW, - QueryState::InProgress { .. } => panic!("query in progress"), - QueryState::Memoized(memo) => { - if memo.check_durability(db.salsa_runtime()) { - memo.revisions.durability - } else { - Durability::LOW - } - } - } - } - - pub(super) fn as_table_entry(&self, key: &Q::Key) -> Option> { - match &*self.state.read() { - QueryState::NotComputed => None, - QueryState::InProgress { .. } => Some(TableEntry::new(key.clone(), None)), - QueryState::Memoized(memo) => { - Some(TableEntry::new(key.clone(), Some(memo.value.clone()))) - } - } - } - - pub(super) fn invalidate(&self, new_revision: Revision) -> Option { - tracing::trace!("Slot::invalidate(new_revision = {:?})", new_revision); - match &mut *self.state.write() { - QueryState::Memoized(memo) => { - memo.revisions.untracked = true; - memo.revisions.inputs = None; - memo.revisions.changed_at = new_revision; - Some(memo.revisions.durability) - } - QueryState::NotComputed => None, - QueryState::InProgress { .. } => unreachable!(), - } - } - - pub(super) fn maybe_changed_after( - &self, - db: &>::DynDb, - revision: Revision, - key: &Q::Key, - ) -> bool { - let runtime = db.salsa_runtime(); - let revision_now = runtime.current_revision(); - - db.unwind_if_cancelled(); - - trace!( - "maybe_changed_after({:?}) called with revision={:?}, revision_now={:?}", - self, - revision, - revision_now, - ); - - // Do an initial probe with just the read-lock. - // - // If we find that a cache entry for the value is present - // but hasn't been verified in this revision, we'll have to - // do more. - loop { - match self.maybe_changed_after_probe(db, self.state.read(), runtime, revision_now) { - MaybeChangedSinceProbeState::Retry => continue, - MaybeChangedSinceProbeState::ChangedAt(changed_at) => return changed_at > revision, - MaybeChangedSinceProbeState::Stale(state) => { - drop(state); - return self.maybe_changed_after_upgrade(db, revision, key); - } - } - } - } - - fn maybe_changed_after_probe( - &self, - db: &>::DynDb, - state: StateGuard, - runtime: &Runtime, - revision_now: Revision, - ) -> MaybeChangedSinceProbeState - where - StateGuard: Deref>, - { - match self.probe(db, state, runtime, revision_now) { - ProbeState::Retry => MaybeChangedSinceProbeState::Retry, - - ProbeState::Stale(state) => MaybeChangedSinceProbeState::Stale(state), - - // If we know when value last changed, we can return right away. - // Note that we don't need the actual value to be available. - ProbeState::UpToDate(StampedValue { value: _, durability: _, changed_at }) => { - MaybeChangedSinceProbeState::ChangedAt(changed_at) - } - - // If we have nothing cached, then value may have changed. - ProbeState::NotComputed(_) => MaybeChangedSinceProbeState::ChangedAt(revision_now), - } - } - - fn maybe_changed_after_upgrade( - &self, - db: &>::DynDb, - revision: Revision, - key: &Q::Key, - ) -> bool { - let runtime = db.salsa_runtime(); - let revision_now = runtime.current_revision(); - - // Get an upgradable read lock, which permits other reads but no writers. - // Probe again. If the value is stale (needs to be verified), then upgrade - // to a write lock and swap it with InProgress while we work. - let mut old_memo = match self.maybe_changed_after_probe( - db, - self.state.upgradable_read(), - runtime, - revision_now, - ) { - MaybeChangedSinceProbeState::ChangedAt(changed_at) => return changed_at > revision, - - // If another thread was active, then the cache line is going to be - // either verified or cleared out. Just recurse to figure out which. - // Note that we don't need an upgradable read. - MaybeChangedSinceProbeState::Retry => { - return self.maybe_changed_after(db, revision, key) - } - - MaybeChangedSinceProbeState::Stale(state) => { - type RwLockUpgradableReadGuard<'a, T> = - lock_api::RwLockUpgradableReadGuard<'a, RawRwLock, T>; - - let mut state = RwLockUpgradableReadGuard::upgrade(state); - match std::mem::replace(&mut *state, QueryState::in_progress(runtime.id())) { - QueryState::Memoized(old_memo) => old_memo, - QueryState::NotComputed | QueryState::InProgress { .. } => unreachable!(), - } - } - }; - - let panic_guard = PanicGuard::new(self, runtime); - let active_query = runtime.push_query(self.database_key_index()); - - if old_memo.verify_revisions(db.ops_database(), revision_now, &active_query) { - let maybe_changed = old_memo.revisions.changed_at > revision; - panic_guard.proceed(Some(old_memo)); - maybe_changed - } else { - // We found that this memoized value may have changed - // but we have an old value. We can re-run the code and - // actually *check* if it has changed. - let StampedValue { changed_at, .. } = self.execute( - db, - runtime, - revision_now, - active_query, - panic_guard, - Some(old_memo), - key, - ); - changed_at > revision - } - } - - /// Helper: see [`Runtime::try_block_on_or_unwind`]. - fn block_on_or_unwind( - &self, - db: &>::DynDb, - runtime: &Runtime, - other_id: RuntimeId, - mutex_guard: MutexGuard, - ) { - runtime.block_on_or_unwind( - db.ops_database(), - self.database_key_index(), - other_id, - mutex_guard, - ) - } -} - -impl QueryState -where - Q: QueryFunction, -{ - fn in_progress(id: RuntimeId) -> Self { - QueryState::InProgress { id, anyone_waiting: Default::default() } - } -} - -struct PanicGuard<'me, Q> -where - Q: QueryFunction, - Q::Value: Eq, -{ - slot: &'me Slot, - runtime: &'me Runtime, -} - -impl<'me, Q> PanicGuard<'me, Q> -where - Q: QueryFunction, - Q::Value: Eq, -{ - fn new(slot: &'me Slot, runtime: &'me Runtime) -> Self { - Self { slot, runtime } - } - - /// Indicates that we have concluded normally (without panicking). - /// If `opt_memo` is some, then this memo is installed as the new - /// memoized value. If `opt_memo` is `None`, then the slot is cleared - /// and has no value. - fn proceed(mut self, opt_memo: Option>) { - self.overwrite_placeholder(WaitResult::Completed, opt_memo); - std::mem::forget(self) - } - - /// Overwrites the `InProgress` placeholder for `key` that we - /// inserted; if others were blocked, waiting for us to finish, - /// then notify them. - fn overwrite_placeholder(&mut self, wait_result: WaitResult, opt_memo: Option>) { - let old_value = { - let mut write = self.slot.state.write(); - match opt_memo { - // Replace the `InProgress` marker that we installed with the new - // memo, thus releasing our unique access to this key. - Some(memo) => std::mem::replace(&mut *write, QueryState::Memoized(memo)), - - // We had installed an `InProgress` marker, but we panicked before - // it could be removed. At this point, we therefore "own" unique - // access to our slot, so we can just remove the key. - None => std::mem::replace(&mut *write, QueryState::NotComputed), - } - }; - - match old_value { - QueryState::InProgress { id, anyone_waiting } => { - assert_eq!(id, self.runtime.id()); - - // NB: As noted on the `store`, `Ordering::Relaxed` is - // sufficient here. This boolean signals us on whether to - // acquire a mutex; the mutex will guarantee that all writes - // we are interested in are visible. - if anyone_waiting.load(Ordering::Relaxed) { - self.runtime - .unblock_queries_blocked_on(self.slot.database_key_index(), wait_result); - } - } - _ => panic!( - "\ -Unexpected panic during query evaluation, aborting the process. - -Please report this bug to https://github.com/salsa-rs/salsa/issues." - ), - } - } -} - -impl Drop for PanicGuard<'_, Q> -where - Q: QueryFunction, - Q::Value: Eq, -{ - fn drop(&mut self) { - if std::thread::panicking() { - // We panicked before we could proceed and need to remove `key`. - self.overwrite_placeholder(WaitResult::Panicked, None) - } else { - // If no panic occurred, then panic guard ought to be - // "forgotten" and so this Drop code should never run. - panic!(".forget() was not called") - } - } -} - -impl Memo -where - V: Clone, -{ - /// Determines whether the value stored in this memo (if any) is still - /// valid in the current revision. If so, returns a stamped value. - /// - /// If needed, this will walk each dependency and - /// recursively invoke `maybe_changed_after`, which may in turn - /// re-execute the dependency. This can cause cycles to occur, - /// so the current query must be pushed onto the - /// stack to permit cycle detection and recovery: therefore, - /// takes the `active_query` argument as evidence. - fn verify_value( - &mut self, - db: &dyn Database, - revision_now: Revision, - active_query: &ActiveQueryGuard<'_>, - ) -> Option> { - if self.verify_revisions(db, revision_now, active_query) { - Some(StampedValue { - durability: self.revisions.durability, - changed_at: self.revisions.changed_at, - value: self.value.clone(), - }) - } else { - None - } - } - - /// Determines whether the value represented by this memo is still - /// valid in the current revision; note that the value itself is - /// not needed for this check. If needed, this will walk each - /// dependency and recursively invoke `maybe_changed_after`, which - /// may in turn re-execute the dependency. This can cause cycles to occur, - /// so the current query must be pushed onto the - /// stack to permit cycle detection and recovery: therefore, - /// takes the `active_query` argument as evidence. - fn verify_revisions( - &mut self, - db: &dyn Database, - revision_now: Revision, - _active_query: &ActiveQueryGuard<'_>, - ) -> bool { - assert!(self.verified_at != revision_now); - let verified_at = self.verified_at; - - trace!( - "verify_revisions: verified_at={:?}, revision_now={:?}, inputs={:#?}", - verified_at, - revision_now, - self.revisions.inputs - ); - - if self.check_durability(db.salsa_runtime()) { - return self.mark_value_as_verified(revision_now); - } - - match &self.revisions.inputs { - // We can't validate values that had untracked inputs; just have to - // re-execute. - None if self.revisions.untracked => return false, - None => {} - - // Check whether any of our inputs changed since the - // **last point where we were verified** (not since we - // last changed). This is important: if we have - // memoized values, then an input may have changed in - // revision R2, but we found that *our* value was the - // same regardless, so our change date is still - // R1. But our *verification* date will be R2, and we - // are only interested in finding out whether the - // input changed *again*. - Some(inputs) => { - let changed_input = - inputs.slice.iter().find(|&&input| db.maybe_changed_after(input, verified_at)); - if let Some(input) = changed_input { - trace!("validate_memoized_value: `{:?}` may have changed", input); - - return false; - } - } - }; - - self.mark_value_as_verified(revision_now) - } - - /// True if this memo is known not to have changed based on its durability. - fn check_durability(&self, runtime: &Runtime) -> bool { - let last_changed = runtime.last_changed_revision(self.revisions.durability); - trace!( - "check_durability(last_changed={:?} <= verified_at={:?}) = {:?}", - last_changed, - self.verified_at, - last_changed <= self.verified_at, - ); - last_changed <= self.verified_at - } - - fn mark_value_as_verified(&mut self, revision_now: Revision) -> bool { - self.verified_at = revision_now; - true - } -} - -impl std::fmt::Debug for Slot -where - Q: QueryFunction, -{ - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(fmt, "{:?}", Q::default()) - } -} - -/// Check that `Slot: Send + Sync` as long as -/// `DB::DatabaseData: Send + Sync`, which in turn implies that -/// `Q::Key: Send + Sync`, `Q::Value: Send + Sync`. -#[allow(dead_code)] -fn check_send_sync() -where - Q: QueryFunction, - - Q::Key: Send + Sync, - Q::Value: Send + Sync, -{ - fn is_send_sync() {} - is_send_sync::>(); -} - -/// Check that `Slot: 'static` as long as -/// `DB::DatabaseData: 'static`, which in turn implies that -/// `Q::Key: 'static`, `Q::Value: 'static`. -#[allow(dead_code)] -fn check_static() -where - Q: QueryFunction + 'static, - Q::Key: 'static, - Q::Value: 'static, -{ - fn is_static() {} - is_static::>(); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru.rs deleted file mode 100644 index bdb448e2412ee..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru.rs +++ /dev/null @@ -1,233 +0,0 @@ -use crate::debug::TableEntry; -use crate::durability::Durability; -use crate::hash::FxIndexMap; -use crate::lru::Lru; -use crate::plumbing::DerivedQueryStorageOps; -use crate::plumbing::LruQueryStorageOps; -use crate::plumbing::QueryFunction; -use crate::plumbing::QueryStorageMassOps; -use crate::plumbing::QueryStorageOps; -use crate::runtime::StampedValue; -use crate::Runtime; -use crate::{Database, DatabaseKeyIndex, QueryDb, Revision}; -use parking_lot::RwLock; -use std::borrow::Borrow; -use std::hash::Hash; -use std::marker::PhantomData; -use triomphe::Arc; - -mod slot; -use slot::Slot; - -/// Memoized queries store the result plus a list of the other queries -/// that they invoked. This means we can avoid recomputing them when -/// none of those inputs have changed. -pub type MemoizedStorage = DerivedStorage; - -/// "Dependency" queries just track their dependencies and not the -/// actual value (which they produce on demand). This lessens the -/// storage requirements. -pub type DependencyStorage = DerivedStorage; - -/// Handles storage where the value is 'derived' by executing a -/// function (in contrast to "inputs"). -pub struct DerivedStorage -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - group_index: u16, - lru_list: Lru>, - slot_map: RwLock>>>, - policy: PhantomData, -} - -impl std::panic::RefUnwindSafe for DerivedStorage -where - Q: QueryFunction, - MP: MemoizationPolicy, - Q::Key: std::panic::RefUnwindSafe, - Q::Value: std::panic::RefUnwindSafe, -{ -} - -pub trait MemoizationPolicy: Send + Sync -where - Q: QueryFunction, -{ - fn should_memoize_value(key: &Q::Key) -> bool; - - fn memoized_value_eq(old_value: &Q::Value, new_value: &Q::Value) -> bool; -} - -pub enum AlwaysMemoizeValue {} -impl MemoizationPolicy for AlwaysMemoizeValue -where - Q: QueryFunction, - Q::Value: Eq, -{ - fn should_memoize_value(_key: &Q::Key) -> bool { - true - } - - fn memoized_value_eq(old_value: &Q::Value, new_value: &Q::Value) -> bool { - old_value == new_value - } -} - -pub enum NeverMemoizeValue {} -impl MemoizationPolicy for NeverMemoizeValue -where - Q: QueryFunction, -{ - fn should_memoize_value(_key: &Q::Key) -> bool { - false - } - - fn memoized_value_eq(_old_value: &Q::Value, _new_value: &Q::Value) -> bool { - panic!("cannot reach since we never memoize") - } -} - -impl DerivedStorage -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - fn slot(&self, key: &Q::Key) -> Arc> { - if let Some(v) = self.slot_map.read().get(key) { - return v.clone(); - } - - let mut write = self.slot_map.write(); - let entry = write.entry(key.clone()); - let key_index = entry.index() as u32; - let database_key_index = DatabaseKeyIndex { - group_index: self.group_index, - query_index: Q::QUERY_INDEX, - key_index, - }; - entry.or_insert_with(|| Arc::new(Slot::new(database_key_index))).clone() - } -} - -impl QueryStorageOps for DerivedStorage -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - const CYCLE_STRATEGY: crate::plumbing::CycleRecoveryStrategy = Q::CYCLE_STRATEGY; - - fn new(group_index: u16) -> Self { - DerivedStorage { - group_index, - slot_map: RwLock::new(FxIndexMap::default()), - lru_list: Default::default(), - policy: PhantomData, - } - } - - fn fmt_index( - &self, - _db: &>::DynDb, - index: u32, - fmt: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - let slot_map = self.slot_map.read(); - let key = slot_map.get_index(index as usize).unwrap().0; - write!(fmt, "{}::{}({:?})", std::any::type_name::(), Q::QUERY_NAME, key) - } - - fn maybe_changed_after( - &self, - db: &>::DynDb, - index: u32, - revision: Revision, - ) -> bool { - debug_assert!(revision < db.salsa_runtime().current_revision()); - let (key, slot) = { - let read = self.slot_map.read(); - let Some((key, slot)) = read.get_index(index as usize) else { - return false; - }; - (key.clone(), slot.clone()) - }; - slot.maybe_changed_after(db, revision, &key) - } - - fn fetch(&self, db: &>::DynDb, key: &Q::Key) -> Q::Value { - db.unwind_if_cancelled(); - - let slot = self.slot(key); - let StampedValue { value, durability, changed_at } = slot.read(db, key); - - if let Some(evicted) = self.lru_list.record_use(&slot) { - evicted.evict(); - } - - db.salsa_runtime().report_query_read_and_unwind_if_cycle_resulted( - slot.database_key_index(), - durability, - changed_at, - ); - - value - } - - fn durability(&self, db: &>::DynDb, key: &Q::Key) -> Durability { - self.slot(key).durability(db) - } - - fn entries(&self, _db: &>::DynDb) -> C - where - C: std::iter::FromIterator>, - { - let slot_map = self.slot_map.read(); - slot_map.iter().filter_map(|(key, slot)| slot.as_table_entry(key)).collect() - } -} - -impl QueryStorageMassOps for DerivedStorage -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - fn purge(&self) { - self.lru_list.purge(); - *self.slot_map.write() = Default::default(); - } -} - -impl LruQueryStorageOps for DerivedStorage -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - fn set_lru_capacity(&self, new_capacity: u16) { - self.lru_list.set_lru_capacity(new_capacity); - } -} - -impl DerivedQueryStorageOps for DerivedStorage -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - fn invalidate(&self, runtime: &mut Runtime, key: &S) - where - S: Eq + Hash, - Q::Key: Borrow, - { - runtime.with_incremented_revision(|new_revision| { - let map_read = self.slot_map.read(); - - if let Some(slot) = map_read.get(key) { - if let Some(durability) = slot.invalidate(new_revision) { - return Some(durability); - } - } - - None - }) - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru/slot.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru/slot.rs deleted file mode 100644 index 73a5e07aa05ab..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru/slot.rs +++ /dev/null @@ -1,856 +0,0 @@ -use crate::debug::TableEntry; -use crate::derived_lru::MemoizationPolicy; -use crate::durability::Durability; -use crate::lru::LruIndex; -use crate::lru::LruNode; -use crate::plumbing::{DatabaseOps, QueryFunction}; -use crate::revision::Revision; -use crate::runtime::local_state::ActiveQueryGuard; -use crate::runtime::local_state::QueryRevisions; -use crate::runtime::Runtime; -use crate::runtime::RuntimeId; -use crate::runtime::StampedValue; -use crate::runtime::WaitResult; -use crate::Cycle; -use crate::{Database, DatabaseKeyIndex, Event, EventKind, QueryDb}; -use parking_lot::{RawRwLock, RwLock}; -use std::marker::PhantomData; -use std::ops::Deref; -use std::sync::atomic::{AtomicBool, Ordering}; -use tracing::trace; - -pub(super) struct Slot -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - key_index: u32, - group_index: u16, - state: RwLock>, - lru_index: LruIndex, - policy: PhantomData, -} - -/// Defines the "current state" of query's memoized results. -enum QueryState -where - Q: QueryFunction, -{ - NotComputed, - - /// The runtime with the given id is currently computing the - /// result of this query. - InProgress { - id: RuntimeId, - - /// Set to true if any other queries are blocked, - /// waiting for this query to complete. - anyone_waiting: AtomicBool, - }, - - /// We have computed the query already, and here is the result. - Memoized(Memo), -} - -struct Memo { - /// The result of the query, if we decide to memoize it. - value: Option, - - /// Last revision when this memo was verified; this begins - /// as the current revision. - pub(crate) verified_at: Revision, - - /// Revision information - revisions: QueryRevisions, -} - -/// Return value of `probe` helper. -enum ProbeState { - /// Another thread was active but has completed. - /// Try again! - Retry, - - /// No entry for this key at all. - NotComputed(G), - - /// There is an entry, but its contents have not been - /// verified in this revision. - Stale(G), - - /// There is an entry, and it has been verified - /// in this revision, but it has no cached - /// value. The `Revision` is the revision where the - /// value last changed (if we were to recompute it). - NoValue(G, Revision), - - /// There is an entry which has been verified, - /// and it has the following value-- or, we blocked - /// on another thread, and that resulted in a cycle. - UpToDate(V), -} - -/// Return value of `maybe_changed_after_probe` helper. -enum MaybeChangedSinceProbeState { - /// Another thread was active but has completed. - /// Try again! - Retry, - - /// Value may have changed in the given revision. - ChangedAt(Revision), - - /// There is a stale cache entry that has not been - /// verified in this revision, so we can't say. - Stale(G), -} - -impl Slot -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - pub(super) fn new(database_key_index: DatabaseKeyIndex) -> Self { - Self { - key_index: database_key_index.key_index, - group_index: database_key_index.group_index, - state: RwLock::new(QueryState::NotComputed), - lru_index: LruIndex::default(), - policy: PhantomData, - } - } - - pub(super) fn database_key_index(&self) -> DatabaseKeyIndex { - DatabaseKeyIndex { - group_index: self.group_index, - query_index: Q::QUERY_INDEX, - key_index: self.key_index, - } - } - - pub(super) fn read( - &self, - db: &>::DynDb, - key: &Q::Key, - ) -> StampedValue { - let runtime = db.salsa_runtime(); - - // NB: We don't need to worry about people modifying the - // revision out from under our feet. Either `db` is a frozen - // database, in which case there is a lock, or the mutator - // thread is the current thread, and it will be prevented from - // doing any `set` invocations while the query function runs. - let revision_now = runtime.current_revision(); - - trace!("{:?}: invoked at {:?}", self, revision_now,); - - // First, do a check with a read-lock. - loop { - match self.probe(db, self.state.read(), runtime, revision_now) { - ProbeState::UpToDate(v) => return v, - ProbeState::Stale(..) | ProbeState::NoValue(..) | ProbeState::NotComputed(..) => { - break - } - ProbeState::Retry => continue, - } - } - - self.read_upgrade(db, key, revision_now) - } - - /// Second phase of a read operation: acquires an upgradable-read - /// and -- if needed -- validates whether inputs have changed, - /// recomputes value, etc. This is invoked after our initial probe - /// shows a potentially out of date value. - fn read_upgrade( - &self, - db: &>::DynDb, - key: &Q::Key, - revision_now: Revision, - ) -> StampedValue { - let runtime = db.salsa_runtime(); - - trace!("{:?}: read_upgrade(revision_now={:?})", self, revision_now,); - - // Check with an upgradable read to see if there is a value - // already. (This permits other readers but prevents anyone - // else from running `read_upgrade` at the same time.) - let mut old_memo = loop { - match self.probe(db, self.state.upgradable_read(), runtime, revision_now) { - ProbeState::UpToDate(v) => return v, - ProbeState::Stale(state) - | ProbeState::NotComputed(state) - | ProbeState::NoValue(state, _) => { - type RwLockUpgradableReadGuard<'a, T> = - lock_api::RwLockUpgradableReadGuard<'a, RawRwLock, T>; - - let mut state = RwLockUpgradableReadGuard::upgrade(state); - match std::mem::replace(&mut *state, QueryState::in_progress(runtime.id())) { - QueryState::Memoized(old_memo) => break Some(old_memo), - QueryState::InProgress { .. } => unreachable!(), - QueryState::NotComputed => break None, - } - } - ProbeState::Retry => continue, - } - }; - - let panic_guard = PanicGuard::new(self, runtime); - let active_query = runtime.push_query(self.database_key_index()); - - // If we have an old-value, it *may* now be stale, since there - // has been a new revision since the last time we checked. So, - // first things first, let's walk over each of our previous - // inputs and check whether they are out of date. - if let Some(memo) = &mut old_memo { - if let Some(value) = memo.verify_value(db.ops_database(), revision_now, &active_query) { - trace!("{:?}: validated old memoized value", self,); - - db.salsa_event(Event { - runtime_id: runtime.id(), - kind: EventKind::DidValidateMemoizedValue { - database_key: self.database_key_index(), - }, - }); - - panic_guard.proceed(old_memo); - - return value; - } - } - - self.execute(db, runtime, revision_now, active_query, panic_guard, old_memo, key) - } - - fn execute( - &self, - db: &>::DynDb, - runtime: &Runtime, - revision_now: Revision, - active_query: ActiveQueryGuard<'_>, - panic_guard: PanicGuard<'_, Q, MP>, - old_memo: Option>, - key: &Q::Key, - ) -> StampedValue { - tracing::trace!("{:?}: executing query", self.database_key_index().debug(db)); - - db.salsa_event(Event { - runtime_id: db.salsa_runtime().id(), - kind: EventKind::WillExecute { database_key: self.database_key_index() }, - }); - - // Query was not previously executed, or value is potentially - // stale, or value is absent. Let's execute! - let value = match Cycle::catch(|| Q::execute(db, key.clone())) { - Ok(v) => v, - Err(cycle) => { - tracing::trace!( - "{:?}: caught cycle {:?}, have strategy {:?}", - self.database_key_index().debug(db), - cycle, - Q::CYCLE_STRATEGY, - ); - match Q::CYCLE_STRATEGY { - crate::plumbing::CycleRecoveryStrategy::Panic => { - panic_guard.proceed(None); - cycle.throw() - } - crate::plumbing::CycleRecoveryStrategy::Fallback => { - if let Some(c) = active_query.take_cycle() { - assert!(c.is(&cycle)); - Q::cycle_fallback(db, &cycle, key) - } else { - // we are not a participant in this cycle - debug_assert!(!cycle - .participant_keys() - .any(|k| k == self.database_key_index())); - cycle.throw() - } - } - } - } - }; - - let mut revisions = active_query.pop(); - - // We assume that query is side-effect free -- that is, does - // not mutate the "inputs" to the query system. Sanity check - // that assumption here, at least to the best of our ability. - assert_eq!( - runtime.current_revision(), - revision_now, - "revision altered during query execution", - ); - - // If the new value is equal to the old one, then it didn't - // really change, even if some of its inputs have. So we can - // "backdate" its `changed_at` revision to be the same as the - // old value. - if let Some(old_memo) = &old_memo { - if let Some(old_value) = &old_memo.value { - // Careful: if the value became less durable than it - // used to be, that is a "breaking change" that our - // consumers must be aware of. Becoming *more* durable - // is not. See the test `constant_to_non_constant`. - if revisions.durability >= old_memo.revisions.durability - && MP::memoized_value_eq(old_value, &value) - { - trace!( - "read_upgrade({:?}): value is equal, back-dating to {:?}", - self, - old_memo.revisions.changed_at, - ); - - assert!(old_memo.revisions.changed_at <= revisions.changed_at); - revisions.changed_at = old_memo.revisions.changed_at; - } - } - } - - let new_value = StampedValue { - value, - durability: revisions.durability, - changed_at: revisions.changed_at, - }; - - let memo_value = - if self.should_memoize_value(key) { Some(new_value.value.clone()) } else { None }; - - trace!("read_upgrade({:?}): result.revisions = {:#?}", self, revisions,); - - panic_guard.proceed(Some(Memo { value: memo_value, verified_at: revision_now, revisions })); - - new_value - } - - /// Helper for `read` that does a shallow check (not recursive) if we have an up-to-date value. - /// - /// Invoked with the guard `state` corresponding to the `QueryState` of some `Slot` (the guard - /// can be either read or write). Returns a suitable `ProbeState`: - /// - /// - `ProbeState::UpToDate(r)` if the table has an up-to-date value (or we blocked on another - /// thread that produced such a value). - /// - `ProbeState::StaleOrAbsent(g)` if either (a) there is no memo for this key, (b) the memo - /// has no value; or (c) the memo has not been verified at the current revision. - /// - /// Note that in case `ProbeState::UpToDate`, the lock will have been released. - fn probe( - &self, - db: &>::DynDb, - state: StateGuard, - runtime: &Runtime, - revision_now: Revision, - ) -> ProbeState, StateGuard> - where - StateGuard: Deref>, - { - match &*state { - QueryState::NotComputed => ProbeState::NotComputed(state), - - QueryState::InProgress { id, anyone_waiting } => { - let other_id = *id; - - // NB: `Ordering::Relaxed` is sufficient here, - // as there are no loads that are "gated" on this - // value. Everything that is written is also protected - // by a lock that must be acquired. The role of this - // boolean is to decide *whether* to acquire the lock, - // not to gate future atomic reads. - anyone_waiting.store(true, Ordering::Relaxed); - - self.block_on_or_unwind(db, runtime, other_id, state); - - // Other thread completely normally, so our value may be available now. - ProbeState::Retry - } - - QueryState::Memoized(memo) => { - trace!( - "{:?}: found memoized value, verified_at={:?}, changed_at={:?}", - self, - memo.verified_at, - memo.revisions.changed_at, - ); - - if memo.verified_at < revision_now { - return ProbeState::Stale(state); - } - - if let Some(value) = &memo.value { - let value = StampedValue { - durability: memo.revisions.durability, - changed_at: memo.revisions.changed_at, - value: value.clone(), - }; - - trace!( - "{:?}: returning memoized value changed at {:?}", - self, - value.changed_at - ); - - ProbeState::UpToDate(value) - } else { - let changed_at = memo.revisions.changed_at; - ProbeState::NoValue(state, changed_at) - } - } - } - } - - pub(super) fn durability(&self, db: &>::DynDb) -> Durability { - match &*self.state.read() { - QueryState::NotComputed => Durability::LOW, - QueryState::InProgress { .. } => panic!("query in progress"), - QueryState::Memoized(memo) => { - if memo.check_durability(db.salsa_runtime()) { - memo.revisions.durability - } else { - Durability::LOW - } - } - } - } - - pub(super) fn as_table_entry(&self, key: &Q::Key) -> Option> { - match &*self.state.read() { - QueryState::NotComputed => None, - QueryState::InProgress { .. } => Some(TableEntry::new(key.clone(), None)), - QueryState::Memoized(memo) => Some(TableEntry::new(key.clone(), memo.value.clone())), - } - } - - pub(super) fn evict(&self) { - let mut state = self.state.write(); - if let QueryState::Memoized(memo) = &mut *state { - // Evicting a value with an untracked input could - // lead to inconsistencies. Note that we can't check - // `has_untracked_input` when we add the value to the cache, - // because inputs can become untracked in the next revision. - if memo.has_untracked_input() { - return; - } - memo.value = None; - } - } - - pub(super) fn invalidate(&self, new_revision: Revision) -> Option { - tracing::trace!("Slot::invalidate(new_revision = {:?})", new_revision); - match &mut *self.state.write() { - QueryState::Memoized(memo) => { - memo.revisions.untracked = true; - memo.revisions.inputs = None; - memo.revisions.changed_at = new_revision; - Some(memo.revisions.durability) - } - QueryState::NotComputed => None, - QueryState::InProgress { .. } => unreachable!(), - } - } - - pub(super) fn maybe_changed_after( - &self, - db: &>::DynDb, - revision: Revision, - key: &Q::Key, - ) -> bool { - let runtime = db.salsa_runtime(); - let revision_now = runtime.current_revision(); - - db.unwind_if_cancelled(); - - trace!( - "maybe_changed_after({:?}) called with revision={:?}, revision_now={:?}", - self, - revision, - revision_now, - ); - - // Do an initial probe with just the read-lock. - // - // If we find that a cache entry for the value is present - // but hasn't been verified in this revision, we'll have to - // do more. - loop { - match self.maybe_changed_after_probe(db, self.state.read(), runtime, revision_now) { - MaybeChangedSinceProbeState::Retry => continue, - MaybeChangedSinceProbeState::ChangedAt(changed_at) => return changed_at > revision, - MaybeChangedSinceProbeState::Stale(state) => { - drop(state); - return self.maybe_changed_after_upgrade(db, revision, key); - } - } - } - } - - fn maybe_changed_after_probe( - &self, - db: &>::DynDb, - state: StateGuard, - runtime: &Runtime, - revision_now: Revision, - ) -> MaybeChangedSinceProbeState - where - StateGuard: Deref>, - { - match self.probe(db, state, runtime, revision_now) { - ProbeState::Retry => MaybeChangedSinceProbeState::Retry, - - ProbeState::Stale(state) => MaybeChangedSinceProbeState::Stale(state), - - // If we know when value last changed, we can return right away. - // Note that we don't need the actual value to be available. - ProbeState::NoValue(_, changed_at) - | ProbeState::UpToDate(StampedValue { value: _, durability: _, changed_at }) => { - MaybeChangedSinceProbeState::ChangedAt(changed_at) - } - - // If we have nothing cached, then value may have changed. - ProbeState::NotComputed(_) => MaybeChangedSinceProbeState::ChangedAt(revision_now), - } - } - - fn maybe_changed_after_upgrade( - &self, - db: &>::DynDb, - revision: Revision, - key: &Q::Key, - ) -> bool { - let runtime = db.salsa_runtime(); - let revision_now = runtime.current_revision(); - - // Get an upgradable read lock, which permits other reads but no writers. - // Probe again. If the value is stale (needs to be verified), then upgrade - // to a write lock and swap it with InProgress while we work. - let mut old_memo = match self.maybe_changed_after_probe( - db, - self.state.upgradable_read(), - runtime, - revision_now, - ) { - MaybeChangedSinceProbeState::ChangedAt(changed_at) => return changed_at > revision, - - // If another thread was active, then the cache line is going to be - // either verified or cleared out. Just recurse to figure out which. - // Note that we don't need an upgradable read. - MaybeChangedSinceProbeState::Retry => { - return self.maybe_changed_after(db, revision, key) - } - - MaybeChangedSinceProbeState::Stale(state) => { - type RwLockUpgradableReadGuard<'a, T> = - lock_api::RwLockUpgradableReadGuard<'a, RawRwLock, T>; - - let mut state = RwLockUpgradableReadGuard::upgrade(state); - match std::mem::replace(&mut *state, QueryState::in_progress(runtime.id())) { - QueryState::Memoized(old_memo) => old_memo, - QueryState::NotComputed | QueryState::InProgress { .. } => unreachable!(), - } - } - }; - - let panic_guard = PanicGuard::new(self, runtime); - let active_query = runtime.push_query(self.database_key_index()); - - if old_memo.verify_revisions(db.ops_database(), revision_now, &active_query) { - let maybe_changed = old_memo.revisions.changed_at > revision; - panic_guard.proceed(Some(old_memo)); - maybe_changed - } else if old_memo.value.is_some() { - // We found that this memoized value may have changed - // but we have an old value. We can re-run the code and - // actually *check* if it has changed. - let StampedValue { changed_at, .. } = self.execute( - db, - runtime, - revision_now, - active_query, - panic_guard, - Some(old_memo), - key, - ); - changed_at > revision - } else { - // We found that inputs to this memoized value may have chanced - // but we don't have an old value to compare against or re-use. - // No choice but to drop the memo and say that its value may have changed. - panic_guard.proceed(None); - true - } - } - - /// Helper: see [`Runtime::try_block_on_or_unwind`]. - fn block_on_or_unwind( - &self, - db: &>::DynDb, - runtime: &Runtime, - other_id: RuntimeId, - mutex_guard: MutexGuard, - ) { - runtime.block_on_or_unwind( - db.ops_database(), - self.database_key_index(), - other_id, - mutex_guard, - ) - } - - fn should_memoize_value(&self, key: &Q::Key) -> bool { - MP::should_memoize_value(key) - } -} - -impl QueryState -where - Q: QueryFunction, -{ - fn in_progress(id: RuntimeId) -> Self { - QueryState::InProgress { id, anyone_waiting: Default::default() } - } -} - -struct PanicGuard<'me, Q, MP> -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - slot: &'me Slot, - runtime: &'me Runtime, -} - -impl<'me, Q, MP> PanicGuard<'me, Q, MP> -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - fn new(slot: &'me Slot, runtime: &'me Runtime) -> Self { - Self { slot, runtime } - } - - /// Indicates that we have concluded normally (without panicking). - /// If `opt_memo` is some, then this memo is installed as the new - /// memoized value. If `opt_memo` is `None`, then the slot is cleared - /// and has no value. - fn proceed(mut self, opt_memo: Option>) { - self.overwrite_placeholder(WaitResult::Completed, opt_memo); - std::mem::forget(self) - } - - /// Overwrites the `InProgress` placeholder for `key` that we - /// inserted; if others were blocked, waiting for us to finish, - /// then notify them. - fn overwrite_placeholder(&mut self, wait_result: WaitResult, opt_memo: Option>) { - let old_value = { - let mut write = self.slot.state.write(); - match opt_memo { - // Replace the `InProgress` marker that we installed with the new - // memo, thus releasing our unique access to this key. - Some(memo) => std::mem::replace(&mut *write, QueryState::Memoized(memo)), - - // We had installed an `InProgress` marker, but we panicked before - // it could be removed. At this point, we therefore "own" unique - // access to our slot, so we can just remove the key. - None => std::mem::replace(&mut *write, QueryState::NotComputed), - } - }; - - match old_value { - QueryState::InProgress { id, anyone_waiting } => { - assert_eq!(id, self.runtime.id()); - - // NB: As noted on the `store`, `Ordering::Relaxed` is - // sufficient here. This boolean signals us on whether to - // acquire a mutex; the mutex will guarantee that all writes - // we are interested in are visible. - if anyone_waiting.load(Ordering::Relaxed) { - self.runtime - .unblock_queries_blocked_on(self.slot.database_key_index(), wait_result); - } - } - _ => panic!( - "\ -Unexpected panic during query evaluation, aborting the process. - -Please report this bug to https://github.com/salsa-rs/salsa/issues." - ), - } - } -} - -impl Drop for PanicGuard<'_, Q, MP> -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - fn drop(&mut self) { - if std::thread::panicking() { - // We panicked before we could proceed and need to remove `key`. - self.overwrite_placeholder(WaitResult::Panicked, None) - } else { - // If no panic occurred, then panic guard ought to be - // "forgotten" and so this Drop code should never run. - panic!(".forget() was not called") - } - } -} - -impl Memo -where - V: Clone, -{ - /// Determines whether the value stored in this memo (if any) is still - /// valid in the current revision. If so, returns a stamped value. - /// - /// If needed, this will walk each dependency and - /// recursively invoke `maybe_changed_after`, which may in turn - /// re-execute the dependency. This can cause cycles to occur, - /// so the current query must be pushed onto the - /// stack to permit cycle detection and recovery: therefore, - /// takes the `active_query` argument as evidence. - fn verify_value( - &mut self, - db: &dyn Database, - revision_now: Revision, - active_query: &ActiveQueryGuard<'_>, - ) -> Option> { - // If we don't have a memoized value, nothing to validate. - if self.value.is_none() { - return None; - } - if self.verify_revisions(db, revision_now, active_query) { - self.value.clone().map(|value| StampedValue { - durability: self.revisions.durability, - changed_at: self.revisions.changed_at, - value, - }) - } else { - None - } - } - - /// Determines whether the value represented by this memo is still - /// valid in the current revision; note that the value itself is - /// not needed for this check. If needed, this will walk each - /// dependency and recursively invoke `maybe_changed_after`, which - /// may in turn re-execute the dependency. This can cause cycles to occur, - /// so the current query must be pushed onto the - /// stack to permit cycle detection and recovery: therefore, - /// takes the `active_query` argument as evidence. - fn verify_revisions( - &mut self, - db: &dyn Database, - revision_now: Revision, - _active_query: &ActiveQueryGuard<'_>, - ) -> bool { - assert!(self.verified_at != revision_now); - let verified_at = self.verified_at; - - trace!( - "verify_revisions: verified_at={:?}, revision_now={:?}, inputs={:#?}", - verified_at, - revision_now, - self.revisions.inputs - ); - - if self.check_durability(db.salsa_runtime()) { - return self.mark_value_as_verified(revision_now); - } - - match &self.revisions.inputs { - // We can't validate values that had untracked inputs; just have to - // re-execute. - None if self.revisions.untracked => return false, - None => {} - - // Check whether any of our inputs changed since the - // **last point where we were verified** (not since we - // last changed). This is important: if we have - // memoized values, then an input may have changed in - // revision R2, but we found that *our* value was the - // same regardless, so our change date is still - // R1. But our *verification* date will be R2, and we - // are only interested in finding out whether the - // input changed *again*. - Some(inputs) => { - let changed_input = - inputs.slice.iter().find(|&&input| db.maybe_changed_after(input, verified_at)); - if let Some(input) = changed_input { - trace!("validate_memoized_value: `{:?}` may have changed", input); - - return false; - } - } - }; - - self.mark_value_as_verified(revision_now) - } - - /// True if this memo is known not to have changed based on its durability. - fn check_durability(&self, runtime: &Runtime) -> bool { - let last_changed = runtime.last_changed_revision(self.revisions.durability); - trace!( - "check_durability(last_changed={:?} <= verified_at={:?}) = {:?}", - last_changed, - self.verified_at, - last_changed <= self.verified_at, - ); - last_changed <= self.verified_at - } - - fn mark_value_as_verified(&mut self, revision_now: Revision) -> bool { - self.verified_at = revision_now; - true - } - - fn has_untracked_input(&self) -> bool { - self.revisions.untracked - } -} - -impl std::fmt::Debug for Slot -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(fmt, "{:?}", Q::default()) - } -} - -impl LruNode for Slot -where - Q: QueryFunction, - MP: MemoizationPolicy, -{ - fn lru_index(&self) -> &LruIndex { - &self.lru_index - } -} - -/// Check that `Slot: Send + Sync` as long as -/// `DB::DatabaseData: Send + Sync`, which in turn implies that -/// `Q::Key: Send + Sync`, `Q::Value: Send + Sync`. -#[allow(dead_code)] -fn check_send_sync() -where - Q: QueryFunction, - MP: MemoizationPolicy, - Q::Key: Send + Sync, - Q::Value: Send + Sync, -{ - fn is_send_sync() {} - is_send_sync::>(); -} - -/// Check that `Slot: 'static` as long as -/// `DB::DatabaseData: 'static`, which in turn implies that -/// `Q::Key: 'static`, `Q::Value: 'static`. -#[allow(dead_code)] -fn check_static() -where - Q: QueryFunction + 'static, - MP: MemoizationPolicy + 'static, - Q::Key: 'static, - Q::Value: 'static, -{ - fn is_static() {} - is_static::>(); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/durability.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/durability.rs deleted file mode 100644 index 9116f1606faf1..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/durability.rs +++ /dev/null @@ -1,49 +0,0 @@ -/// Describes how likely a value is to change -- how "durable" it is. -/// By default, inputs have `Durability::LOW` and interned values have -/// `Durability::HIGH`. But inputs can be explicitly set with other -/// durabilities. -/// -/// We use durabilities to optimize the work of "revalidating" a query -/// after some input has changed. Ordinarily, in a new revision, -/// queries have to trace all their inputs back to the base inputs to -/// determine if any of those inputs have changed. But if we know that -/// the only changes were to inputs of low durability (the common -/// case), and we know that the query only used inputs of medium -/// durability or higher, then we can skip that enumeration. -/// -/// Typically, one assigns low durabilities to inputs that the user is -/// frequently editing. Medium or high durabilities are used for -/// configuration, the source from library crates, or other things -/// that are unlikely to be edited. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Durability(u8); - -impl Durability { - /// Low durability: things that change frequently. - /// - /// Example: part of the crate being edited - pub const LOW: Durability = Durability(0); - - /// Medium durability: things that change sometimes, but rarely. - /// - /// Example: a Cargo.toml file - pub const MEDIUM: Durability = Durability(1); - - /// High durability: things that are not expected to change under - /// common usage. - /// - /// Example: the standard library or something from crates.io - pub const HIGH: Durability = Durability(2); - - /// The maximum possible durability; equivalent to HIGH but - /// "conceptually" distinct (i.e., if we add more durability - /// levels, this could change). - pub(crate) const MAX: Durability = Self::HIGH; - - /// Number of durability levels. - pub(crate) const LEN: usize = Self::MAX.index() + 1; - - pub(crate) const fn index(self) -> usize { - self.0 as usize - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/hash.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/hash.rs deleted file mode 100644 index 3b2d7df3fbeaa..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/hash.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub(crate) type FxHasher = std::hash::BuildHasherDefault; -pub(crate) type FxIndexSet = indexmap::IndexSet; -pub(crate) type FxIndexMap = indexmap::IndexMap; diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/input.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/input.rs deleted file mode 100644 index 4992a0c7271cc..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/input.rs +++ /dev/null @@ -1,371 +0,0 @@ -use crate::debug::TableEntry; -use crate::durability::Durability; -use crate::hash::FxIndexMap; -use crate::plumbing::CycleRecoveryStrategy; -use crate::plumbing::InputQueryStorageOps; -use crate::plumbing::QueryStorageMassOps; -use crate::plumbing::QueryStorageOps; -use crate::revision::Revision; -use crate::runtime::StampedValue; -use crate::Database; -use crate::Query; -use crate::Runtime; -use crate::{DatabaseKeyIndex, QueryDb}; -use indexmap::map::Entry; -use parking_lot::RwLock; -use std::iter; -use tracing::trace; - -/// Input queries store the result plus a list of the other queries -/// that they invoked. This means we can avoid recomputing them when -/// none of those inputs have changed. -pub struct InputStorage -where - Q: Query, -{ - group_index: u16, - slots: RwLock>>, -} - -struct Slot { - key_index: u32, - stamped_value: RwLock>, -} - -impl std::panic::RefUnwindSafe for InputStorage -where - Q: Query, - Q::Key: std::panic::RefUnwindSafe, - Q::Value: std::panic::RefUnwindSafe, -{ -} - -impl QueryStorageOps for InputStorage -where - Q: Query, -{ - const CYCLE_STRATEGY: crate::plumbing::CycleRecoveryStrategy = CycleRecoveryStrategy::Panic; - - fn new(group_index: u16) -> Self { - InputStorage { group_index, slots: Default::default() } - } - - fn fmt_index( - &self, - _db: &>::DynDb, - index: u32, - fmt: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - let slot_map = self.slots.read(); - let key = slot_map.get_index(index as usize).unwrap().0; - write!(fmt, "{}({:?})", Q::QUERY_NAME, key) - } - - fn maybe_changed_after( - &self, - db: &>::DynDb, - index: u32, - revision: Revision, - ) -> bool { - debug_assert!(revision < db.salsa_runtime().current_revision()); - let slots = &self.slots.read(); - let Some((_, slot)) = slots.get_index(index as usize) else { - return true; - }; - - trace!("maybe_changed_after(slot={:?}, revision={:?})", Q::default(), revision,); - - let changed_at = slot.stamped_value.read().changed_at; - - trace!("maybe_changed_after: changed_at = {:?}", changed_at); - - changed_at > revision - } - - fn fetch(&self, db: &>::DynDb, key: &Q::Key) -> Q::Value { - db.unwind_if_cancelled(); - - let slots = &self.slots.read(); - let slot = slots - .get(key) - .unwrap_or_else(|| panic!("no value set for {:?}({:?})", Q::default(), key)); - - let StampedValue { value, durability, changed_at } = slot.stamped_value.read().clone(); - - db.salsa_runtime().report_query_read_and_unwind_if_cycle_resulted( - DatabaseKeyIndex { - group_index: self.group_index, - query_index: Q::QUERY_INDEX, - key_index: slot.key_index, - }, - durability, - changed_at, - ); - - value - } - - fn durability(&self, _db: &>::DynDb, key: &Q::Key) -> Durability { - match self.slots.read().get(key) { - Some(slot) => slot.stamped_value.read().durability, - None => panic!("no value set for {:?}({:?})", Q::default(), key), - } - } - - fn entries(&self, _db: &>::DynDb) -> C - where - C: std::iter::FromIterator>, - { - let slots = self.slots.read(); - slots - .iter() - .map(|(key, slot)| { - TableEntry::new(key.clone(), Some(slot.stamped_value.read().value.clone())) - }) - .collect() - } -} - -impl QueryStorageMassOps for InputStorage -where - Q: Query, -{ - fn purge(&self) { - *self.slots.write() = Default::default(); - } -} - -impl InputQueryStorageOps for InputStorage -where - Q: Query, -{ - fn set(&self, runtime: &mut Runtime, key: &Q::Key, value: Q::Value, durability: Durability) { - tracing::trace!("{:?}({:?}) = {:?} ({:?})", Q::default(), key, value, durability); - - // The value is changing, so we need a new revision (*). We also - // need to update the 'last changed' revision by invoking - // `guard.mark_durability_as_changed`. - // - // CAREFUL: This will block until the global revision lock can - // be acquired. If there are still queries executing, they may - // need to read from this input. Therefore, we wait to acquire - // the lock on `map` until we also hold the global query write - // lock. - // - // (*) Technically, since you can't presently access an input - // for a non-existent key, and you can't enumerate the set of - // keys, we only need a new revision if the key used to - // exist. But we may add such methods in the future and this - // case doesn't generally seem worth optimizing for. - runtime.with_incremented_revision(|next_revision| { - let mut slots = self.slots.write(); - - // Do this *after* we acquire the lock, so that we are not - // racing with somebody else to modify this same cell. - // (Otherwise, someone else might write a *newer* revision - // into the same cell while we block on the lock.) - let stamped_value = StampedValue { value, durability, changed_at: next_revision }; - - match slots.entry(key.clone()) { - Entry::Occupied(entry) => { - let mut slot_stamped_value = entry.get().stamped_value.write(); - let old_durability = slot_stamped_value.durability; - *slot_stamped_value = stamped_value; - Some(old_durability) - } - - Entry::Vacant(entry) => { - let key_index = entry.index() as u32; - entry.insert(Slot { key_index, stamped_value: RwLock::new(stamped_value) }); - None - } - } - }); - } -} - -/// Same as `InputStorage`, but optimized for queries that take no inputs. -pub struct UnitInputStorage -where - Q: Query, -{ - slot: UnitSlot, -} - -struct UnitSlot { - database_key_index: DatabaseKeyIndex, - stamped_value: RwLock>>, -} - -impl std::panic::RefUnwindSafe for UnitInputStorage -where - Q: Query, - Q::Key: std::panic::RefUnwindSafe, - Q::Value: std::panic::RefUnwindSafe, -{ -} - -impl QueryStorageOps for UnitInputStorage -where - Q: Query, -{ - const CYCLE_STRATEGY: crate::plumbing::CycleRecoveryStrategy = CycleRecoveryStrategy::Panic; - - fn new(group_index: u16) -> Self { - let database_key_index = - DatabaseKeyIndex { group_index, query_index: Q::QUERY_INDEX, key_index: 0 }; - UnitInputStorage { slot: UnitSlot { database_key_index, stamped_value: RwLock::new(None) } } - } - - fn fmt_index( - &self, - _db: &>::DynDb, - _index: u32, - fmt: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - write!(fmt, "{}", Q::QUERY_NAME) - } - - fn maybe_changed_after( - &self, - db: &>::DynDb, - _index: u32, - revision: Revision, - ) -> bool { - debug_assert!(revision < db.salsa_runtime().current_revision()); - - trace!("maybe_changed_after(slot={:?}, revision={:?})", Q::default(), revision,); - - let Some(value) = &*self.slot.stamped_value.read() else { - return true; - }; - let changed_at = value.changed_at; - - trace!("maybe_changed_after: changed_at = {:?}", changed_at); - - changed_at > revision - } - - fn fetch(&self, db: &>::DynDb, &(): &Q::Key) -> Q::Value { - db.unwind_if_cancelled(); - - let StampedValue { value, durability, changed_at } = self - .slot - .stamped_value - .read() - .clone() - .unwrap_or_else(|| panic!("no value set for {:?}", Q::default())); - - db.salsa_runtime().report_query_read_and_unwind_if_cycle_resulted( - self.slot.database_key_index, - durability, - changed_at, - ); - - value - } - - fn durability(&self, _db: &>::DynDb, &(): &Q::Key) -> Durability { - match &*self.slot.stamped_value.read() { - Some(stamped_value) => stamped_value.durability, - None => panic!("no value set for {:?}", Q::default(),), - } - } - - fn entries(&self, _db: &>::DynDb) -> C - where - C: std::iter::FromIterator>, - { - iter::once(TableEntry::new( - (), - self.slot.stamped_value.read().as_ref().map(|it| it.value.clone()), - )) - .collect() - } -} - -impl QueryStorageMassOps for UnitInputStorage -where - Q: Query, -{ - fn purge(&self) { - *self.slot.stamped_value.write() = Default::default(); - } -} - -impl InputQueryStorageOps for UnitInputStorage -where - Q: Query, -{ - fn set(&self, runtime: &mut Runtime, (): &Q::Key, value: Q::Value, durability: Durability) { - tracing::trace!("{:?} = {:?} ({:?})", Q::default(), value, durability); - - // The value is changing, so we need a new revision (*). We also - // need to update the 'last changed' revision by invoking - // `guard.mark_durability_as_changed`. - // - // CAREFUL: This will block until the global revision lock can - // be acquired. If there are still queries executing, they may - // need to read from this input. Therefore, we wait to acquire - // the lock on `map` until we also hold the global query write - // lock. - // - // (*) Technically, since you can't presently access an input - // for a non-existent key, and you can't enumerate the set of - // keys, we only need a new revision if the key used to - // exist. But we may add such methods in the future and this - // case doesn't generally seem worth optimizing for. - runtime.with_incremented_revision(|next_revision| { - let mut stamped_value_slot = self.slot.stamped_value.write(); - - // Do this *after* we acquire the lock, so that we are not - // racing with somebody else to modify this same cell. - // (Otherwise, someone else might write a *newer* revision - // into the same cell while we block on the lock.) - let stamped_value = StampedValue { value, durability, changed_at: next_revision }; - - match &mut *stamped_value_slot { - Some(slot_stamped_value) => { - let old_durability = slot_stamped_value.durability; - *slot_stamped_value = stamped_value; - Some(old_durability) - } - - stamped_value_slot @ None => { - *stamped_value_slot = Some(stamped_value); - None - } - } - }); - } -} - -/// Check that `Slot: Send + Sync` as long as -/// `DB::DatabaseData: Send + Sync`, which in turn implies that -/// `Q::Key: Send + Sync`, `Q::Value: Send + Sync`. -#[allow(dead_code)] -fn check_send_sync() -where - Q: Query, - Q::Key: Send + Sync, - Q::Value: Send + Sync, -{ - fn is_send_sync() {} - is_send_sync::>(); - is_send_sync::>(); -} - -/// Check that `Slot: 'static` as long as -/// `DB::DatabaseData: 'static`, which in turn implies that -/// `Q::Key: 'static`, `Q::Value: 'static`. -#[allow(dead_code)] -fn check_static() -where - Q: Query + 'static, - Q::Key: 'static, - Q::Value: 'static, -{ - fn is_static() {} - is_static::>(); - is_static::>(); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/intern_id.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/intern_id.rs deleted file mode 100644 index 35b495998e16a..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/intern_id.rs +++ /dev/null @@ -1,131 +0,0 @@ -use std::fmt; -use std::num::NonZeroU32; - -/// The "raw-id" is used for interned keys in salsa -- it is basically -/// a newtype'd u32. Typically, it is wrapped in a type of your own -/// devising. For more information about interned keys, see [the -/// interned key RFC][rfc]. -/// -/// # Creating a `InternId` -// -/// InternId values can be constructed using the `From` impls, -/// which are implemented for `u32` and `usize`: -/// -/// ``` -/// # use ra_salsa::InternId; -/// let intern_id1 = InternId::from(22_u32); -/// let intern_id2 = InternId::from(22_usize); -/// assert_eq!(intern_id1, intern_id2); -/// ``` -/// -/// # Converting to a u32 or usize -/// -/// Normally, there should be no need to access the underlying integer -/// in a `InternId`. But if you do need to do so, you can convert to a -/// `usize` using the `as_u32` or `as_usize` methods or the `From` impls. -/// -/// ``` -/// # use ra_salsa::InternId;; -/// let intern_id = InternId::from(22_u32); -/// let value = u32::from(intern_id); -/// assert_eq!(value, 22); -/// ``` -/// -/// ## Illegal values -/// -/// Be warned, however, that `InternId` values cannot be created from -/// *arbitrary* values -- in particular large values greater than -/// `InternId::MAX` will panic. Those large values are reserved so that -/// the Rust compiler can use them as sentinel values, which means -/// that (for example) `Option` is represented in a single -/// word. -/// -/// ```should_panic -/// # use ra_salsa::InternId;; -/// InternId::from(InternId::MAX); -/// ``` -/// -/// [rfc]: https://github.com/salsa-rs/salsa-rfcs/pull/2 -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct InternId { - value: NonZeroU32, -} - -impl InternId { - /// The maximum allowed `InternId`. This value can grow between - /// releases without affecting semver. - pub const MAX: u32 = 0xFFFF_FF00; - - /// Creates a new InternId. - /// - /// # Safety - /// - /// `value` must be less than `MAX` - pub const unsafe fn new_unchecked(value: u32) -> Self { - debug_assert!(value < InternId::MAX); - let value = unsafe { NonZeroU32::new_unchecked(value + 1) }; - InternId { value } - } - - /// Convert this raw-id into a u32 value. - /// - /// ``` - /// # use ra_salsa::InternId; - /// let intern_id = InternId::from(22_u32); - /// let value = intern_id.as_usize(); - /// assert_eq!(value, 22); - /// ``` - pub fn as_u32(self) -> u32 { - self.value.get() - 1 - } - - /// Convert this raw-id into a usize value. - /// - /// ``` - /// # use ra_salsa::InternId; - /// let intern_id = InternId::from(22_u32); - /// let value = intern_id.as_usize(); - /// assert_eq!(value, 22); - /// ``` - pub fn as_usize(self) -> usize { - self.as_u32() as usize - } -} - -impl From for u32 { - fn from(raw: InternId) -> u32 { - raw.as_u32() - } -} - -impl From for usize { - fn from(raw: InternId) -> usize { - raw.as_usize() - } -} - -impl From for InternId { - fn from(id: u32) -> InternId { - assert!(id < InternId::MAX); - unsafe { InternId::new_unchecked(id) } - } -} - -impl From for InternId { - fn from(id: usize) -> InternId { - assert!(id < (InternId::MAX as usize)); - unsafe { InternId::new_unchecked(id as u32) } - } -} - -impl fmt::Debug for InternId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.as_usize().fmt(f) - } -} - -impl fmt::Display for InternId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.as_usize().fmt(f) - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/interned.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/interned.rs deleted file mode 100644 index 42c398d697de6..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/interned.rs +++ /dev/null @@ -1,510 +0,0 @@ -use crate::debug::TableEntry; -use crate::durability::Durability; -use crate::intern_id::InternId; -use crate::plumbing::CycleRecoveryStrategy; -use crate::plumbing::HasQueryGroup; -use crate::plumbing::QueryStorageMassOps; -use crate::plumbing::QueryStorageOps; -use crate::revision::Revision; -use crate::Query; -use crate::QueryTable; -use crate::{Database, DatabaseKeyIndex, QueryDb}; -use parking_lot::RwLock; -use rustc_hash::FxHashMap; -use std::collections::hash_map::Entry; -use std::fmt::Debug; -use std::hash::Hash; -use triomphe::Arc; - -const INTERN_DURABILITY: Durability = Durability::HIGH; - -/// Handles storage where the value is 'derived' by executing a -/// function (in contrast to "inputs"). -pub struct InternedStorage -where - Q: Query, - Q::Key: InternValue, - Q::Value: InternKey, -{ - group_index: u16, - tables: RwLock, Q::Key>>, -} - -/// Storage for the looking up interned things. -pub struct LookupInternedStorage -where - Q: Query, - Q::Key: InternKey, - Q::Value: InternValue, -{ - phantom: std::marker::PhantomData<(Q::Key, IQ)>, -} - -struct InternTables { - /// Map from the key to the corresponding intern-index. - map: FxHashMap, - - /// For each valid intern-index, stores the interned value. - values: Vec>>, -} - -/// Trait implemented for the "key" that results from a -/// `#[salsa::intern]` query. This is basically meant to be a -/// "newtype"'d `u32`. -pub trait InternKey { - /// Create an instance of the intern-key from a `u32` value. - fn from_intern_id(v: InternId) -> Self; - - /// Extract the `u32` with which the intern-key was created. - fn as_intern_id(&self) -> InternId; -} - -impl InternKey for InternId { - fn from_intern_id(v: InternId) -> InternId { - v - } - - fn as_intern_id(&self) -> InternId { - *self - } -} - -/// Trait implemented for the "value" that is being interned. -pub trait InternValue { - /// They key used to intern this value by. - type Key: Eq + Hash + Debug + Clone; - /// Maps the value to a key that will be used to intern it. - fn into_key(&self) -> Self::Key; - /// Calls the given function with the key that was used to intern this value. - /// - /// This is mainly used to prevent frequent cloning of the key when doing a lookup. - #[inline] - fn with_key T, T>(&self, f: F) -> T { - f(&self.into_key()) - } -} - -impl - InternValue for (A, B) -{ - type Key = Self; - #[inline] - fn into_key(&self) -> Self::Key { - self.clone() - } - #[inline] - fn with_key T, T>(&self, f: F) -> T { - f(self) - } -} - -pub trait InternValueTrivial -where - Self: Eq + Hash + Debug + Clone, -{ -} - -/// Implement [`InternValue`] trivially, that is without actually mapping at all. -impl InternValue for V { - type Key = Self; - #[inline] - fn into_key(&self) -> Self::Key { - self.clone() - } - #[inline] - fn with_key T, T>(&self, f: F) -> T { - f(self) - } -} - -impl InternValueTrivial for String {} - -#[derive(Debug)] -struct Slot { - /// key index for this slot. - key_index: u32, - - /// Value that was interned. - value: V, - - /// When was this intern'd? - /// - /// (This informs the "changed-at" result) - interned_at: Revision, -} - -impl std::panic::RefUnwindSafe for InternedStorage -where - Q: Query, - Q::Key: InternValue, - Q::Key: std::panic::RefUnwindSafe, - Q::Value: InternKey, - Q::Value: std::panic::RefUnwindSafe, -{ -} - -impl InternTables { - /// Returns the slot for the given key. - fn slot_for_key(&self, key: &K) -> Option<(Arc>, InternId)> { - let &index = self.map.get(key)?; - Some((self.slot_for_index(index), index)) - } - - /// Returns the slot at the given index. - fn slot_for_index(&self, index: InternId) -> Arc> { - let slot = &self.values[index.as_usize()]; - slot.clone() - } -} - -impl Default for InternTables -where - K: Eq + Hash, -{ - fn default() -> Self { - Self { map: Default::default(), values: Default::default() } - } -} - -type MappedKey = <::Key as InternValue>::Key; - -impl InternedStorage -where - Q: Query, - Q::Key: InternValue, - Q::Value: InternKey, -{ - /// Creates a new slot. - fn intern_index( - &self, - db: &>::DynDb, - mapped_key: MappedKey, - insert: impl FnOnce(Q::Value) -> Q::Key, - ) -> (Arc>, InternId) { - let revision_now = db.salsa_runtime().current_revision(); - - let mut tables = self.tables.write(); - let tables = &mut *tables; - let entry = match tables.map.entry(mapped_key) { - Entry::Vacant(entry) => entry, - Entry::Occupied(entry) => { - // Somebody inserted this key while we were waiting - // for the write lock. In this case, we don't need to - // update the `accessed_at` field because they should - // have already done so! - let index = *entry.get(); - let slot = &tables.values[index.as_usize()]; - return (slot.clone(), index); - } - }; - - let create_slot = |index: InternId| { - Arc::new(Slot { - key_index: index.as_u32(), - value: insert(Q::Value::from_intern_id(index)), - interned_at: revision_now, - }) - }; - - let index = InternId::from(tables.values.len()); - let slot = create_slot(index); - tables.values.push(slot.clone()); - entry.insert(index); - - (slot, index) - } - - fn intern_check(&self, key: &MappedKey) -> Option<(Arc>, InternId)> { - self.tables.read().slot_for_key(key) - } - - /// Given an index, lookup and clone its value, updating the - /// `accessed_at` time if necessary. - fn lookup_value(&self, index: InternId) -> Arc> { - self.tables.read().slot_for_index(index) - } - - fn fetch_or_insert( - &self, - db: &>::DynDb, - key: MappedKey, - insert: impl FnOnce(Q::Value) -> Q::Key, - ) -> Q::Value { - db.unwind_if_cancelled(); - let (slot, index) = match self.intern_check(&key) { - Some(i) => i, - None => self.intern_index(db, key, insert), - }; - let changed_at = slot.interned_at; - db.salsa_runtime().report_query_read_and_unwind_if_cycle_resulted( - DatabaseKeyIndex { - group_index: self.group_index, - query_index: Q::QUERY_INDEX, - key_index: slot.key_index, - }, - INTERN_DURABILITY, - changed_at, - ); - ::from_intern_id(index) - } -} - -impl QueryStorageOps for InternedStorage -where - Q: Query, - Q::Key: InternValue, - Q::Value: InternKey, -{ - const CYCLE_STRATEGY: crate::plumbing::CycleRecoveryStrategy = CycleRecoveryStrategy::Panic; - - fn new(group_index: u16) -> Self { - InternedStorage { group_index, tables: RwLock::new(InternTables::default()) } - } - - fn fmt_index( - &self, - _db: &>::DynDb, - index: u32, - fmt: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - let intern_id = InternId::from(index); - let slot = self.lookup_value(intern_id); - write!(fmt, "{}({:?})", Q::QUERY_NAME, slot.value) - } - - fn maybe_changed_after( - &self, - db: &>::DynDb, - input: u32, - revision: Revision, - ) -> bool { - debug_assert!(revision < db.salsa_runtime().current_revision()); - let intern_id = InternId::from(input); - let slot = self.lookup_value(intern_id); - slot.maybe_changed_after(revision) - } - - fn fetch(&self, db: &>::DynDb, key: &Q::Key) -> Q::Value { - db.unwind_if_cancelled(); - - let (slot, index) = match key.with_key(|key| self.intern_check(key)) { - Some(i) => i, - None => self.intern_index(db, key.into_key(), |_| key.clone()), - }; - let changed_at = slot.interned_at; - db.salsa_runtime().report_query_read_and_unwind_if_cycle_resulted( - DatabaseKeyIndex { - group_index: self.group_index, - query_index: Q::QUERY_INDEX, - key_index: slot.key_index, - }, - INTERN_DURABILITY, - changed_at, - ); - ::from_intern_id(index) - } - - fn durability(&self, _db: &>::DynDb, _key: &Q::Key) -> Durability { - INTERN_DURABILITY - } - - fn entries(&self, _db: &>::DynDb) -> C - where - C: std::iter::FromIterator>, - { - let tables = self.tables.read(); - tables - .map - .values() - .map(|index| { - TableEntry::new( - tables.values[index.as_usize()].value.clone(), - Some(::from_intern_id(*index)), - ) - }) - .collect() - } -} - -impl QueryStorageMassOps for InternedStorage -where - Q: Query, - Q::Key: InternValue, - Q::Value: InternKey, -{ - fn purge(&self) { - *self.tables.write() = Default::default(); - } -} - -// Workaround for -// ``` -// IQ: for<'d> QueryDb< -// 'd, -// DynDb = >::DynDb, -// Group = >::Group, -// GroupStorage = >::GroupStorage, -// >, -// ``` -// not working to make rustc know DynDb, Group and GroupStorage being the same in `Q` and `IQ` -#[doc(hidden)] -pub trait EqualDynDb<'d, IQ>: QueryDb<'d> -where - IQ: QueryDb<'d>, -{ - fn convert_db(d: &Self::DynDb) -> &IQ::DynDb; - fn convert_group_storage(d: &Self::GroupStorage) -> &IQ::GroupStorage; -} - -impl<'d, IQ, Q> EqualDynDb<'d, IQ> for Q -where - Q: QueryDb<'d, DynDb = IQ::DynDb, Group = IQ::Group, GroupStorage = IQ::GroupStorage>, - Q::DynDb: HasQueryGroup, - IQ: QueryDb<'d>, -{ - fn convert_db(d: &Self::DynDb) -> &IQ::DynDb { - d - } - fn convert_group_storage(d: &Self::GroupStorage) -> &IQ::GroupStorage { - d - } -} - -impl QueryStorageOps for LookupInternedStorage -where - Q: Query, - Q::Key: InternKey, - Q::Value: InternValue, - IQ: Query>, - for<'d> Q: EqualDynDb<'d, IQ>, -{ - const CYCLE_STRATEGY: CycleRecoveryStrategy = CycleRecoveryStrategy::Panic; - - fn new(_group_index: u16) -> Self { - LookupInternedStorage { phantom: std::marker::PhantomData } - } - - fn fmt_index( - &self, - db: &>::DynDb, - index: u32, - fmt: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - let group_storage = - <>::DynDb as HasQueryGroup>::group_storage(db); - let interned_storage = IQ::query_storage(Q::convert_group_storage(group_storage)); - interned_storage.fmt_index(Q::convert_db(db), index, fmt) - } - - fn maybe_changed_after( - &self, - db: &>::DynDb, - input: u32, - revision: Revision, - ) -> bool { - let group_storage = - <>::DynDb as HasQueryGroup>::group_storage(db); - let interned_storage = IQ::query_storage(Q::convert_group_storage(group_storage)); - interned_storage.maybe_changed_after(Q::convert_db(db), input, revision) - } - - fn fetch(&self, db: &>::DynDb, key: &Q::Key) -> Q::Value { - let index = key.as_intern_id(); - let group_storage = - <>::DynDb as HasQueryGroup>::group_storage(db); - let interned_storage = IQ::query_storage(Q::convert_group_storage(group_storage)); - let slot = interned_storage.lookup_value(index); - let value = slot.value.clone(); - let interned_at = slot.interned_at; - db.salsa_runtime().report_query_read_and_unwind_if_cycle_resulted( - DatabaseKeyIndex { - group_index: interned_storage.group_index, - query_index: Q::QUERY_INDEX, - key_index: slot.key_index, - }, - INTERN_DURABILITY, - interned_at, - ); - value - } - - fn durability(&self, _db: &>::DynDb, _key: &Q::Key) -> Durability { - INTERN_DURABILITY - } - - fn entries(&self, db: &>::DynDb) -> C - where - C: std::iter::FromIterator>, - { - let group_storage = - <>::DynDb as HasQueryGroup>::group_storage(db); - let interned_storage = IQ::query_storage(Q::convert_group_storage(group_storage)); - let tables = interned_storage.tables.read(); - tables - .map - .values() - .map(|index| { - TableEntry::new( - ::from_intern_id(*index), - Some(tables.values[index.as_usize()].value.clone()), - ) - }) - .collect() - } -} - -impl QueryStorageMassOps for LookupInternedStorage -where - Q: Query, - Q::Key: InternKey, - Q::Value: InternValue, - IQ: Query, -{ - fn purge(&self) {} -} - -impl Slot { - fn maybe_changed_after(&self, revision: Revision) -> bool { - self.interned_at > revision - } -} - -/// Check that `Slot: Send + Sync` as long as -/// `DB::DatabaseData: Send + Sync`, which in turn implies that -/// `Q::Key: Send + Sync`, `Q::Value: Send + Sync`. -#[allow(dead_code)] -fn check_send_sync() -where - K: Send + Sync, -{ - fn is_send_sync() {} - is_send_sync::>(); -} - -/// Check that `Slot: 'static` as long as -/// `DB::DatabaseData: 'static`, which in turn implies that -/// `Q::Key: 'static`, `Q::Value: 'static`. -#[allow(dead_code)] -fn check_static() -where - K: 'static, -{ - fn is_static() {} - is_static::>(); -} - -impl QueryTable<'_, Q> -where - Q: Query>, - Q::Key: InternValue, - Q::Value: InternKey, -{ - /// Fetches the intern id for the given key or inserts it if it does not exist. - pub fn get_or_insert( - &self, - key: MappedKey, - insert: impl FnOnce(Q::Value) -> Q::Key, - ) -> Q::Value { - self.storage.fetch_or_insert(self.db, key, insert) - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/lib.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/lib.rs deleted file mode 100644 index 843b6d31f0c33..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/lib.rs +++ /dev/null @@ -1,750 +0,0 @@ -#![allow(clippy::type_complexity)] -#![allow(clippy::question_mark)] -#![allow(missing_docs)] -#![warn(rust_2018_idioms)] - -//! The salsa crate is a crate for incremental recomputation. It -//! permits you to define a "database" of queries with both inputs and -//! values derived from those inputs; as you set the inputs, you can -//! re-execute the derived queries and it will try to re-use results -//! from previous invocations as appropriate. - -mod derived; -mod derived_lru; -mod durability; -mod hash; -mod input; -mod intern_id; -mod interned; -mod lru; -mod revision; -mod runtime; -mod storage; - -pub mod debug; -/// Items in this module are public for implementation reasons, -/// and are exempt from the SemVer guarantees. -#[doc(hidden)] -pub mod plumbing; - -use crate::plumbing::CycleRecoveryStrategy; -use crate::plumbing::DerivedQueryStorageOps; -use crate::plumbing::InputQueryStorageOps; -use crate::plumbing::LruQueryStorageOps; -use crate::plumbing::QueryStorageMassOps; -use crate::plumbing::QueryStorageOps; -pub use crate::revision::Revision; -use std::fmt::{self, Debug}; -use std::hash::Hash; -use std::panic::AssertUnwindSafe; -use std::panic::{self, UnwindSafe}; - -pub use crate::durability::Durability; -pub use crate::intern_id::InternId; -pub use crate::interned::{InternKey, InternValue, InternValueTrivial}; -pub use crate::runtime::Runtime; -pub use crate::runtime::RuntimeId; -pub use crate::storage::Storage; - -/// The base trait which your "query context" must implement. Gives -/// access to the salsa runtime, which you must embed into your query -/// context (along with whatever other state you may require). -pub trait Database: plumbing::DatabaseOps { - /// This function is invoked at key points in the salsa - /// runtime. It permits the database to be customized and to - /// inject logging or other custom behavior. - fn salsa_event(&self, event_fn: Event) { - _ = event_fn; - } - - /// Starts unwinding the stack if the current revision is cancelled. - /// - /// This method can be called by query implementations that perform - /// potentially expensive computations, in order to speed up propagation of - /// cancellation. - /// - /// Cancellation will automatically be triggered by salsa on any query - /// invocation. - /// - /// This method should not be overridden by `Database` implementors. A - /// `salsa_event` is emitted when this method is called, so that should be - /// used instead. - #[inline] - fn unwind_if_cancelled(&self) { - let runtime = self.salsa_runtime(); - self.salsa_event(Event { - runtime_id: runtime.id(), - kind: EventKind::WillCheckCancellation, - }); - - let current_revision = runtime.current_revision(); - let pending_revision = runtime.pending_revision(); - tracing::trace!( - "unwind_if_cancelled: current_revision={:?}, pending_revision={:?}", - current_revision, - pending_revision - ); - if pending_revision > current_revision { - runtime.unwind_cancelled(); - } - } - - /// Gives access to the underlying salsa runtime. - /// - /// This method should not be overridden by `Database` implementors. - fn salsa_runtime(&self) -> &Runtime { - self.ops_salsa_runtime() - } - - /// A "synthetic write" causes the system to act *as though* some - /// input of durability `durability` has changed. This is mostly - /// useful for profiling scenarios. - /// - /// **WARNING:** Just like an ordinary write, this method triggers - /// cancellation. If you invoke it while a snapshot exists, it - /// will block until that snapshot is dropped -- if that snapshot - /// is owned by the current thread, this could trigger deadlock. - fn synthetic_write(&mut self, durability: Durability) { - plumbing::DatabaseOps::synthetic_write(self, durability) - } -} - -/// The `Event` struct identifies various notable things that can -/// occur during salsa execution. Instances of this struct are given -/// to `salsa_event`. -pub struct Event { - /// The id of the snapshot that triggered the event. Usually - /// 1-to-1 with a thread, as well. - pub runtime_id: RuntimeId, - - /// What sort of event was it. - pub kind: EventKind, -} - -impl Event { - /// Returns a type that gives a user-readable debug output. - /// Use like `println!("{:?}", index.debug(db))`. - pub fn debug<'me, D>(&'me self, db: &'me D) -> impl std::fmt::Debug + 'me - where - D: ?Sized + plumbing::DatabaseOps, - { - EventDebug { event: self, db } - } -} - -impl fmt::Debug for Event { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("Event") - .field("runtime_id", &self.runtime_id) - .field("kind", &self.kind) - .finish() - } -} - -struct EventDebug<'me, D: ?Sized> -where - D: plumbing::DatabaseOps, -{ - event: &'me Event, - db: &'me D, -} - -impl fmt::Debug for EventDebug<'_, D> -where - D: plumbing::DatabaseOps, -{ - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("Event") - .field("runtime_id", &self.event.runtime_id) - .field("kind", &self.event.kind.debug(self.db)) - .finish() - } -} - -/// An enum identifying the various kinds of events that can occur. -pub enum EventKind { - /// Occurs when we found that all inputs to a memoized value are - /// up-to-date and hence the value can be re-used without - /// executing the closure. - /// - /// Executes before the "re-used" value is returned. - DidValidateMemoizedValue { - /// The database-key for the affected value. Implements `Debug`. - database_key: DatabaseKeyIndex, - }, - - /// Indicates that another thread (with id `other_runtime_id`) is processing the - /// given query (`database_key`), so we will block until they - /// finish. - /// - /// Executes after we have registered with the other thread but - /// before they have answered us. - /// - /// (NB: you can find the `id` of the current thread via the - /// `salsa_runtime`) - WillBlockOn { - /// The id of the runtime we will block on. - other_runtime_id: RuntimeId, - - /// The database-key for the affected value. Implements `Debug`. - database_key: DatabaseKeyIndex, - }, - - /// Indicates that the function for this query will be executed. - /// This is either because it has never executed before or because - /// its inputs may be out of date. - WillExecute { - /// The database-key for the affected value. Implements `Debug`. - database_key: DatabaseKeyIndex, - }, - - /// Indicates that `unwind_if_cancelled` was called and salsa will check if - /// the current revision has been cancelled. - WillCheckCancellation, -} - -impl EventKind { - /// Returns a type that gives a user-readable debug output. - /// Use like `println!("{:?}", index.debug(db))`. - pub fn debug<'me, D>(&'me self, db: &'me D) -> impl std::fmt::Debug + 'me - where - D: ?Sized + plumbing::DatabaseOps, - { - EventKindDebug { kind: self, db } - } -} - -impl fmt::Debug for EventKind { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - EventKind::DidValidateMemoizedValue { database_key } => fmt - .debug_struct("DidValidateMemoizedValue") - .field("database_key", database_key) - .finish(), - EventKind::WillBlockOn { other_runtime_id, database_key } => fmt - .debug_struct("WillBlockOn") - .field("other_runtime_id", other_runtime_id) - .field("database_key", database_key) - .finish(), - EventKind::WillExecute { database_key } => { - fmt.debug_struct("WillExecute").field("database_key", database_key).finish() - } - EventKind::WillCheckCancellation => fmt.debug_struct("WillCheckCancellation").finish(), - } - } -} - -struct EventKindDebug<'me, D: ?Sized> -where - D: plumbing::DatabaseOps, -{ - kind: &'me EventKind, - db: &'me D, -} - -impl fmt::Debug for EventKindDebug<'_, D> -where - D: plumbing::DatabaseOps, -{ - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - EventKind::DidValidateMemoizedValue { database_key } => fmt - .debug_struct("DidValidateMemoizedValue") - .field("database_key", &database_key.debug(self.db)) - .finish(), - EventKind::WillBlockOn { other_runtime_id, database_key } => fmt - .debug_struct("WillBlockOn") - .field("other_runtime_id", &other_runtime_id) - .field("database_key", &database_key.debug(self.db)) - .finish(), - EventKind::WillExecute { database_key } => fmt - .debug_struct("WillExecute") - .field("database_key", &database_key.debug(self.db)) - .finish(), - EventKind::WillCheckCancellation => fmt.debug_struct("WillCheckCancellation").finish(), - } - } -} - -/// Indicates a database that also supports parallel query -/// evaluation. All of Salsa's base query support is capable of -/// parallel execution, but for it to work, your query key/value types -/// must also be `Send`, as must any additional data in your database. -pub trait ParallelDatabase: Database + Send { - /// Creates a second handle to the database that holds the - /// database fixed at a particular revision. So long as this - /// "frozen" handle exists, any attempt to [`set`] an input will - /// block. - /// - /// [`set`]: struct.QueryTable.html#method.set - /// - /// This is the method you are meant to use most of the time in a - /// parallel setting where modifications may arise asynchronously - /// (e.g., a language server). In this context, it is common to - /// wish to "fork off" a snapshot of the database performing some - /// series of queries in parallel and arranging the results. Using - /// this method for that purpose ensures that those queries will - /// see a consistent view of the database (it is also advisable - /// for those queries to use the [`Database::unwind_if_cancelled`] - /// method to check for cancellation). - /// - /// # Panics - /// - /// It is not permitted to create a snapshot from inside of a - /// query. Attempting to do so will panic. - /// - /// # Deadlock warning - /// - /// The intended pattern for snapshots is that, once created, they - /// are sent to another thread and used from there. As such, the - /// `snapshot` acquires a "read lock" on the database -- - /// therefore, so long as the `snapshot` is not dropped, any - /// attempt to `set` a value in the database will block. If the - /// `snapshot` is owned by the same thread that is attempting to - /// `set`, this will cause a problem. - /// - /// # How to implement this - /// - /// Typically, this method will create a second copy of your - /// database type (`MyDatabaseType`, in the example below), - /// cloning over each of the fields from `self` into this new - /// copy. For the field that stores the salsa runtime, you should - /// use [the `Runtime::snapshot` method][rfm] to create a snapshot of the - /// runtime. Finally, package up the result using `Snapshot::new`, - /// which is a simple wrapper type that only gives `&self` access - /// to the database within (thus preventing the use of methods - /// that may mutate the inputs): - /// - /// [rfm]: struct.Runtime.html#method.snapshot - /// - /// ```rust,ignore - /// impl ParallelDatabase for MyDatabaseType { - /// fn snapshot(&self) -> Snapshot { - /// Snapshot::new( - /// MyDatabaseType { - /// runtime: self.runtime.snapshot(self), - /// other_field: self.other_field.clone(), - /// } - /// ) - /// } - /// } - /// ``` - fn snapshot(&self) -> Snapshot; -} - -/// Simple wrapper struct that takes ownership of a database `DB` and -/// only gives `&self` access to it. See [the `snapshot` method][fm] -/// for more details. -/// -/// [fm]: trait.ParallelDatabase.html#method.snapshot -#[derive(Debug)] -pub struct Snapshot -where - DB: ParallelDatabase, -{ - db: DB, -} - -impl Snapshot -where - DB: ParallelDatabase, -{ - /// Creates a `Snapshot` that wraps the given database handle - /// `db`. From this point forward, only shared references to `db` - /// will be possible. - pub fn new(db: DB) -> Self { - Snapshot { db } - } -} - -impl std::ops::Deref for Snapshot -where - DB: ParallelDatabase, -{ - type Target = DB; - - fn deref(&self) -> &DB { - &self.db - } -} - -/// An integer that uniquely identifies a particular query instance within the -/// database. Used to track dependencies between queries. Fully ordered and -/// equatable but those orderings are arbitrary, and meant to be used only for -/// inserting into maps and the like. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub struct DatabaseKeyIndex { - group_index: u16, - query_index: u16, - key_index: u32, -} - -impl DatabaseKeyIndex { - /// Returns the index of the query group containing this key. - #[inline] - pub fn group_index(self) -> u16 { - self.group_index - } - - /// Returns the index of the query within its query group. - #[inline] - pub fn query_index(self) -> u16 { - self.query_index - } - - /// Returns the index of this particular query key within the query. - #[inline] - pub fn key_index(self) -> u32 { - self.key_index - } - - /// Returns a type that gives a user-readable debug output. - /// Use like `println!("{:?}", index.debug(db))`. - pub fn debug(self, db: &D) -> impl std::fmt::Debug + '_ - where - D: ?Sized + plumbing::DatabaseOps, - { - DatabaseKeyIndexDebug { index: self, db } - } -} - -/// Helper type for `DatabaseKeyIndex::debug` -struct DatabaseKeyIndexDebug<'me, D: ?Sized> -where - D: plumbing::DatabaseOps, -{ - index: DatabaseKeyIndex, - db: &'me D, -} - -impl std::fmt::Debug for DatabaseKeyIndexDebug<'_, D> -where - D: plumbing::DatabaseOps, -{ - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.db.fmt_index(self.index, fmt) - } -} - -/// Trait implements by all of the "special types" associated with -/// each of your queries. -/// -/// Base trait of `Query` that has a lifetime parameter to allow the `DynDb` to be non-'static. -pub trait QueryDb<'d>: Sized { - /// Dyn version of the associated trait for this query group. - type DynDb: ?Sized + Database + HasQueryGroup + 'd; - - /// Associate query group struct. - type Group: plumbing::QueryGroup; - - /// Generated struct that contains storage for all queries in a group. - type GroupStorage; -} - -/// Trait implements by all of the "special types" associated with -/// each of your queries. -pub trait Query: Debug + Default + Sized + for<'d> QueryDb<'d> { - /// Type that you give as a parameter -- for queries with zero - /// or more than one input, this will be a tuple. - type Key: Clone + Debug + Hash + Eq; - - /// What value does the query return? - type Value: Clone + Debug; - - /// Internal struct storing the values for the query. - // type Storage: plumbing::QueryStorageOps; - type Storage; - - /// A unique index identifying this query within the group. - const QUERY_INDEX: u16; - - /// Name of the query method (e.g., `foo`) - const QUERY_NAME: &'static str; - - /// Extract storage for this query from the storage for its group. - fn query_storage<'a>( - group_storage: &'a >::GroupStorage, - ) -> &'a std::sync::Arc; - - /// Extract storage for this query from the storage for its group. - fn query_storage_mut<'a>( - group_storage: &'a >::GroupStorage, - ) -> &'a std::sync::Arc; -} - -/// Return value from [the `query` method] on `Database`. -/// Gives access to various less common operations on queries. -/// -/// [the `query` method]: trait.Database.html#method.query -pub struct QueryTable<'me, Q> -where - Q: Query, -{ - db: &'me >::DynDb, - storage: &'me Q::Storage, -} - -impl<'me, Q> QueryTable<'me, Q> -where - Q: Query, - Q::Storage: QueryStorageOps, -{ - /// Constructs a new `QueryTable`. - pub fn new(db: &'me >::DynDb, storage: &'me Q::Storage) -> Self { - Self { db, storage } - } - - /// Execute the query on a given input. Usually it's easier to - /// invoke the trait method directly. Note that for variadic - /// queries (those with no inputs, or those with more than one - /// input) the key will be a tuple. - pub fn get(&self, key: Q::Key) -> Q::Value { - self.storage.fetch(self.db, &key) - } - - /// Completely clears the storage for this query. - /// - /// This method breaks internal invariants of salsa, so any further queries - /// might return nonsense results. It is useful only in very specific - /// circumstances -- for example, when one wants to observe which values - /// dropped together with the table - pub fn purge(&self) - where - Q::Storage: plumbing::QueryStorageMassOps, - { - self.storage.purge(); - } - - pub fn storage(&self) -> &::Storage { - self.storage - } -} - -/// Return value from [the `query_mut` method] on `Database`. -/// Gives access to the `set` method, notably, that is used to -/// set the value of an input query. -/// -/// [the `query_mut` method]: trait.Database.html#method.query_mut -pub struct QueryTableMut<'me, Q> -where - Q: Query + 'me, -{ - runtime: &'me mut Runtime, - storage: &'me Q::Storage, -} - -impl<'me, Q> QueryTableMut<'me, Q> -where - Q: Query, -{ - /// Constructs a new `QueryTableMut`. - pub fn new(runtime: &'me mut Runtime, storage: &'me Q::Storage) -> Self { - Self { runtime, storage } - } - - /// Assign a value to an "input query". Must be used outside of - /// an active query computation. - /// - /// If you are using `snapshot`, see the notes on blocking - /// and cancellation on [the `query_mut` method]. - /// - /// [the `query_mut` method]: trait.Database.html#method.query_mut - pub fn set(&mut self, key: Q::Key, value: Q::Value) - where - Q::Storage: plumbing::InputQueryStorageOps, - { - self.set_with_durability(key, value, Durability::LOW); - } - - /// Assign a value to an "input query", with the additional - /// promise that this value will **never change**. Must be used - /// outside of an active query computation. - /// - /// If you are using `snapshot`, see the notes on blocking - /// and cancellation on [the `query_mut` method]. - /// - /// [the `query_mut` method]: trait.Database.html#method.query_mut - pub fn set_with_durability(&mut self, key: Q::Key, value: Q::Value, durability: Durability) - where - Q::Storage: plumbing::InputQueryStorageOps, - { - self.storage.set(self.runtime, &key, value, durability); - } - - /// Sets the size of LRU cache of values for this query table. - /// - /// That is, at most `cap` values will be preset in the table at the same - /// time. This helps with keeping maximum memory usage under control, at the - /// cost of potential extra recalculations of evicted values. - /// - /// If `cap` is zero, all values are preserved, this is the default. - pub fn set_lru_capacity(&self, cap: u16) - where - Q::Storage: plumbing::LruQueryStorageOps, - { - self.storage.set_lru_capacity(cap); - } - - /// Marks the computed value as outdated. - /// - /// This causes salsa to re-execute the query function on the next access to - /// the query, even if all dependencies are up to date. - /// - /// This is most commonly used as part of the [on-demand input - /// pattern](https://salsa-rs.github.io/salsa/common_patterns/on_demand_inputs.html). - pub fn invalidate(&mut self, key: &Q::Key) - where - Q::Storage: plumbing::DerivedQueryStorageOps, - { - self.storage.invalidate(self.runtime, key) - } -} - -/// A panic payload indicating that execution of a salsa query was cancelled. -/// -/// This can occur for a few reasons: -/// * -/// * -/// * -#[derive(Debug)] -#[non_exhaustive] -pub enum Cancelled { - /// The query was operating on revision R, but there is a pending write to move to revision R+1. - #[non_exhaustive] - PendingWrite, - - /// The query was blocked on another thread, and that thread panicked. - #[non_exhaustive] - PropagatedPanic, -} - -impl Cancelled { - fn throw(self) -> ! { - // We use resume and not panic here to avoid running the panic - // hook (that is, to avoid collecting and printing backtrace). - std::panic::resume_unwind(Box::new(self)); - } - - /// Runs `f`, and catches any salsa cancellation. - pub fn catch(f: F) -> Result - where - F: FnOnce() -> T + UnwindSafe, - { - match panic::catch_unwind(f) { - Ok(t) => Ok(t), - Err(payload) => match payload.downcast() { - Ok(cancelled) => Err(*cancelled), - Err(payload) => panic::resume_unwind(payload), - }, - } - } -} - -impl std::fmt::Display for Cancelled { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let why = match self { - Cancelled::PendingWrite => "pending write", - Cancelled::PropagatedPanic => "propagated panic", - }; - f.write_str("cancelled because of ")?; - f.write_str(why) - } -} - -impl std::error::Error for Cancelled {} - -/// Captures the participants of a cycle that occurred when executing a query. -/// -/// This type is meant to be used to help give meaningful error messages to the -/// user or to help salsa developers figure out why their program is resulting -/// in a computation cycle. -/// -/// It is used in a few ways: -/// -/// * During [cycle recovery](https://https://salsa-rs.github.io/salsa/cycles/fallback.html), -/// where it is given to the fallback function. -/// * As the panic value when an unexpected cycle (i.e., a cycle where one or more participants -/// lacks cycle recovery information) occurs. -/// -/// You can read more about cycle handling in -/// the [salsa book](https://https://salsa-rs.github.io/salsa/cycles.html). -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Cycle { - participants: plumbing::CycleParticipants, -} - -impl Cycle { - pub(crate) fn new(participants: plumbing::CycleParticipants) -> Self { - Self { participants } - } - - /// True if two `Cycle` values represent the same cycle. - pub(crate) fn is(&self, cycle: &Cycle) -> bool { - triomphe::Arc::ptr_eq(&self.participants, &cycle.participants) - } - - pub(crate) fn throw(self) -> ! { - tracing::trace!("throwing cycle {:?}", self); - std::panic::resume_unwind(Box::new(self)) - } - - pub(crate) fn catch(execute: impl FnOnce() -> T) -> Result { - match std::panic::catch_unwind(AssertUnwindSafe(execute)) { - Ok(v) => Ok(v), - Err(err) => match err.downcast::() { - Ok(cycle) => Err(*cycle), - Err(other) => std::panic::resume_unwind(other), - }, - } - } - - /// Iterate over the [`DatabaseKeyIndex`] for each query participating - /// in the cycle. The start point of this iteration within the cycle - /// is arbitrary but deterministic, but the ordering is otherwise determined - /// by the execution. - pub fn participant_keys(&self) -> impl Iterator + '_ { - self.participants.iter().copied() - } - - /// Returns a vector with the debug information for - /// all the participants in the cycle. - pub fn all_participants(&self, db: &DB) -> Vec { - self.participant_keys().map(|d| format!("{:?}", d.debug(db))).collect() - } - - /// Returns a vector with the debug information for - /// those participants in the cycle that lacked recovery - /// information. - pub fn unexpected_participants(&self, db: &DB) -> Vec { - self.participant_keys() - .filter(|&d| db.cycle_recovery_strategy(d) == CycleRecoveryStrategy::Panic) - .map(|d| format!("{:?}", d.debug(db))) - .collect() - } - - /// Returns a "debug" view onto this strict that can be used to print out information. - pub fn debug<'me, DB: ?Sized + Database>(&'me self, db: &'me DB) -> impl std::fmt::Debug + 'me { - struct UnexpectedCycleDebug<'me> { - c: &'me Cycle, - db: &'me dyn Database, - } - - impl std::fmt::Debug for UnexpectedCycleDebug<'_> { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - fmt.debug_struct("UnexpectedCycle") - .field("all_participants", &self.c.all_participants(self.db)) - .field("unexpected_participants", &self.c.unexpected_participants(self.db)) - .finish() - } - } - - UnexpectedCycleDebug { c: self, db: db.ops_database() } - } -} - -// Re-export the procedural macros. -#[allow(unused_imports)] -#[macro_use] -extern crate ra_salsa_macros; -use plumbing::HasQueryGroup; -pub use ra_salsa_macros::*; diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/lru.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/lru.rs deleted file mode 100644 index 7fbd42f92627a..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/lru.rs +++ /dev/null @@ -1,325 +0,0 @@ -use oorandom::Rand64; -use parking_lot::Mutex; -use std::fmt::Debug; -use std::sync::atomic::AtomicU16; -use std::sync::atomic::Ordering; -use triomphe::Arc; - -/// A simple and approximate concurrent lru list. -/// -/// We assume but do not verify that each node is only used with one -/// list. If this is not the case, it is not *unsafe*, but panics and -/// weird results will ensue. -/// -/// Each "node" in the list is of type `Node` and must implement -/// `LruNode`, which is a trait that gives access to a field that -/// stores the index in the list. This index gives us a rough idea of -/// how recently the node has been used. -#[derive(Debug)] -pub(crate) struct Lru -where - Node: LruNode, -{ - green_zone: AtomicU16, - data: Mutex>, -} - -#[derive(Debug)] -struct LruData { - end_red_zone: u16, - end_yellow_zone: u16, - end_green_zone: u16, - rng: Rand64, - entries: Vec>, -} - -pub(crate) trait LruNode: Sized + Debug { - fn lru_index(&self) -> &LruIndex; -} - -#[derive(Debug)] -pub(crate) struct LruIndex { - /// Index in the appropriate LRU list, or std::u16::MAX if not a - /// member. - index: AtomicU16, -} - -impl Default for Lru -where - Node: LruNode, -{ - fn default() -> Self { - Lru::new() - } -} - -// We always use a fixed seed for our randomness so that we have -// predictable results. -const LRU_SEED: &str = "Hello, Rustaceans"; - -impl Lru -where - Node: LruNode, -{ - /// Creates a new LRU list where LRU caching is disabled. - pub(crate) fn new() -> Self { - Self::with_seed(LRU_SEED) - } - - #[cfg_attr(not(test), allow(dead_code))] - fn with_seed(seed: &str) -> Self { - Lru { green_zone: AtomicU16::new(0), data: Mutex::new(LruData::with_seed(seed)) } - } - - /// Adjust the total number of nodes permitted to have a value at - /// once. If `len` is zero, this disables LRU caching completely. - pub(crate) fn set_lru_capacity(&self, len: u16) { - let mut data = self.data.lock(); - - // We require each zone to have at least 1 slot. Therefore, - // the length cannot be just 1 or 2. - if len == 0 { - self.green_zone.store(0, Ordering::Release); - data.resize(0, 0, 0); - } else { - let len = std::cmp::max(len, 3); - - // Top 10% is the green zone. This must be at least length 1. - let green_zone = std::cmp::max(len / 10, 1); - - // Next 20% is the yellow zone. - let yellow_zone = std::cmp::max(len / 5, 1); - - // Remaining 70% is the red zone. - let red_zone = len - yellow_zone - green_zone; - - // We need quick access to the green zone. - self.green_zone.store(green_zone, Ordering::Release); - - // Resize existing array. - data.resize(green_zone, yellow_zone, red_zone); - } - } - - /// Records that `node` was used. This may displace an old node (if the LRU limits are - pub(crate) fn record_use(&self, node: &Arc) -> Option> { - tracing::trace!("record_use(node={:?})", node); - - // Load green zone length and check if the LRU cache is even enabled. - let green_zone = self.green_zone.load(Ordering::Acquire); - tracing::trace!("record_use: green_zone={}", green_zone); - if green_zone == 0 { - return None; - } - - // Find current index of list (if any) and the current length - // of our green zone. - let index = node.lru_index().load(); - tracing::trace!("record_use: index={}", index); - - // Already a member of the list, and in the green zone -- nothing to do! - if index < green_zone { - return None; - } - - self.data.lock().record_use(node) - } - - pub(crate) fn purge(&self) { - self.green_zone.store(0, Ordering::SeqCst); - *self.data.lock() = LruData::with_seed(LRU_SEED); - } -} - -impl LruData -where - Node: LruNode, -{ - fn with_seed(seed_str: &str) -> Self { - Self::with_rng(rng_with_seed(seed_str)) - } - - fn with_rng(rng: Rand64) -> Self { - LruData { end_yellow_zone: 0, end_green_zone: 0, end_red_zone: 0, entries: Vec::new(), rng } - } - - fn green_zone(&self) -> std::ops::Range { - 0..self.end_green_zone - } - - fn yellow_zone(&self) -> std::ops::Range { - self.end_green_zone..self.end_yellow_zone - } - - fn red_zone(&self) -> std::ops::Range { - self.end_yellow_zone..self.end_red_zone - } - - fn resize(&mut self, len_green_zone: u16, len_yellow_zone: u16, len_red_zone: u16) { - self.end_green_zone = len_green_zone; - self.end_yellow_zone = self.end_green_zone + len_yellow_zone; - self.end_red_zone = self.end_yellow_zone + len_red_zone; - let entries = - std::mem::replace(&mut self.entries, Vec::with_capacity(self.end_red_zone as usize)); - - tracing::trace!("green_zone = {:?}", self.green_zone()); - tracing::trace!("yellow_zone = {:?}", self.yellow_zone()); - tracing::trace!("red_zone = {:?}", self.red_zone()); - - // We expect to resize when the LRU cache is basically empty. - // So just forget all the old LRU indices to start. - for entry in entries { - entry.lru_index().clear(); - } - } - - /// Records that a node was used. If it is already a member of the - /// LRU list, it is promoted to the green zone (unless it's - /// already there). Otherwise, it is added to the list first and - /// *then* promoted to the green zone. Adding a new node to the - /// list may displace an old member of the red zone, in which case - /// that is returned. - fn record_use(&mut self, node: &Arc) -> Option> { - tracing::trace!("record_use(node={:?})", node); - - // NB: When this is invoked, we have typically already loaded - // the LRU index (to check if it is in green zone). But that - // check was done outside the lock and -- for all we know -- - // the index may have changed since. So we always reload. - let index = node.lru_index().load(); - - if index < self.end_green_zone { - None - } else if index < self.end_yellow_zone { - self.promote_yellow_to_green(node, index); - None - } else if index < self.end_red_zone { - self.promote_red_to_green(node, index); - None - } else { - self.insert_new(node) - } - } - - /// Inserts a node that is not yet a member of the LRU list. If - /// the list is at capacity, this can displace an existing member. - fn insert_new(&mut self, node: &Arc) -> Option> { - debug_assert!(!node.lru_index().is_in_lru()); - - // Easy case: we still have capacity. Push it, and then promote - // it up to the appropriate zone. - let len = self.entries.len() as u16; - if len < self.end_red_zone { - self.entries.push(node.clone()); - node.lru_index().store(len); - tracing::trace!("inserted node {:?} at {}", node, len); - return self.record_use(node); - } - - // Harder case: no capacity. Create some by evicting somebody from red - // zone and then promoting. - let victim_index = self.pick_index(self.red_zone()); - let victim_node = std::mem::replace(&mut self.entries[victim_index as usize], node.clone()); - tracing::trace!("evicting red node {:?} from {}", victim_node, victim_index); - victim_node.lru_index().clear(); - self.promote_red_to_green(node, victim_index); - Some(victim_node) - } - - /// Promotes the node `node`, stored at `red_index` (in the red - /// zone), into a green index, demoting yellow/green nodes at - /// random. - /// - /// NB: It is not required that `node.lru_index()` is up-to-date - /// when entering this method. - fn promote_red_to_green(&mut self, node: &Arc, red_index: u16) { - debug_assert!(self.red_zone().contains(&red_index)); - - // Pick a yellow at random and switch places with it. - // - // Subtle: we do not update `node.lru_index` *yet* -- we're - // going to invoke `self.promote_yellow` next, and it will get - // updated then. - let yellow_index = self.pick_index(self.yellow_zone()); - tracing::trace!( - "demoting yellow node {:?} from {} to red at {}", - self.entries[yellow_index as usize], - yellow_index, - red_index, - ); - self.entries.swap(yellow_index as usize, red_index as usize); - self.entries[red_index as usize].lru_index().store(red_index); - - // Now move ourselves up into the green zone. - self.promote_yellow_to_green(node, yellow_index); - } - - /// Promotes the node `node`, stored at `yellow_index` (in the - /// yellow zone), into a green index, demoting a green node at - /// random to replace it. - /// - /// NB: It is not required that `node.lru_index()` is up-to-date - /// when entering this method. - fn promote_yellow_to_green(&mut self, node: &Arc, yellow_index: u16) { - debug_assert!(self.yellow_zone().contains(&yellow_index)); - - // Pick a yellow at random and switch places with it. - let green_index = self.pick_index(self.green_zone()); - tracing::trace!( - "demoting green node {:?} from {} to yellow at {}", - self.entries[green_index as usize], - green_index, - yellow_index - ); - self.entries.swap(green_index as usize, yellow_index as usize); - self.entries[yellow_index as usize].lru_index().store(yellow_index); - node.lru_index().store(green_index); - - tracing::trace!("promoted {:?} to green index {}", node, green_index); - } - - fn pick_index(&mut self, zone: std::ops::Range) -> u16 { - let end_index = std::cmp::min(zone.end, self.entries.len() as u16); - self.rng.rand_range(zone.start as u64..end_index as u64) as u16 - } -} - -impl Default for LruIndex { - fn default() -> Self { - Self { index: AtomicU16::new(u16::MAX) } - } -} - -impl LruIndex { - fn load(&self) -> u16 { - self.index.load(Ordering::Acquire) // see note on ordering below - } - - fn store(&self, value: u16) { - self.index.store(value, Ordering::Release) // see note on ordering below - } - - fn clear(&self) { - self.store(u16::MAX); - } - - fn is_in_lru(&self) -> bool { - self.load() != u16::MAX - } -} - -fn rng_with_seed(seed_str: &str) -> Rand64 { - let mut seed: [u8; 16] = [0; 16]; - for (i, &b) in seed_str.as_bytes().iter().take(16).enumerate() { - seed[i] = b; - } - Rand64::new(u128::from_le_bytes(seed)) -} - -// A note on ordering: -// -// I chose to use AcqRel for the ordering but I don't think it's -// strictly needed. All writes occur under a lock, so they should be -// ordered w/r/t one another. As for the reads, they can occur -// outside the lock, but they don't themselves enable dependent reads -// -- if the reads are out of bounds, we would acquire a lock. diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/plumbing.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/plumbing.rs deleted file mode 100644 index e96b9daa979fc..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/plumbing.rs +++ /dev/null @@ -1,245 +0,0 @@ -#![allow(missing_docs)] - -use crate::debug::TableEntry; -use crate::durability::Durability; -use crate::Cycle; -use crate::Database; -use crate::Query; -use crate::QueryTable; -use crate::QueryTableMut; -use std::borrow::Borrow; -use std::fmt::Debug; -use std::hash::Hash; -use triomphe::Arc; - -pub use crate::derived::MemoizedStorage; -pub use crate::derived_lru::DependencyStorage as LruDependencyStorage; -pub use crate::derived_lru::MemoizedStorage as LruMemoizedStorage; -pub use crate::input::{InputStorage, UnitInputStorage}; -pub use crate::interned::InternedStorage; -pub use crate::interned::LookupInternedStorage; -pub use crate::{revision::Revision, DatabaseKeyIndex, QueryDb, Runtime}; - -/// Defines various associated types. An impl of this -/// should be generated for your query-context type automatically by -/// the `database_storage` macro, so you shouldn't need to mess -/// with this trait directly. -pub trait DatabaseStorageTypes: Database { - /// Defines the "storage type", where all the query data is kept. - /// This type is defined by the `database_storage` macro. - type DatabaseStorage: Default; -} - -/// Internal operations that the runtime uses to operate on the database. -pub trait DatabaseOps { - /// Upcast this type to a `dyn Database`. - fn ops_database(&self) -> &dyn Database; - - /// Gives access to the underlying salsa runtime. - fn ops_salsa_runtime(&self) -> &Runtime; - - /// A "synthetic write" causes the system to act *as though* some - /// input of durability `durability` has changed. This is mostly - /// useful for profiling scenarios. - /// - /// **WARNING:** Just like an ordinary write, this method triggers - /// cancellation. If you invoke it while a snapshot exists, it - /// will block until that snapshot is dropped -- if that snapshot - /// is owned by the current thread, this could trigger deadlock. - fn synthetic_write(&mut self, durability: Durability); - - /// Formats a database key index in a human readable fashion. - fn fmt_index( - &self, - index: DatabaseKeyIndex, - fmt: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result; - - /// True if the computed value for `input` may have changed since `revision`. - fn maybe_changed_after(&self, input: DatabaseKeyIndex, revision: Revision) -> bool; - - /// Find the `CycleRecoveryStrategy` for a given input. - fn cycle_recovery_strategy(&self, input: DatabaseKeyIndex) -> CycleRecoveryStrategy; - - /// Executes the callback for each kind of query. - fn for_each_query(&self, op: &mut dyn FnMut(&dyn QueryStorageMassOps)); -} - -/// Internal operations performed on the query storage as a whole -/// (note that these ops do not need to know the identity of the -/// query, unlike `QueryStorageOps`). -pub trait QueryStorageMassOps { - fn purge(&self); -} - -pub trait DatabaseKey: Clone + Debug + Eq + Hash {} - -pub trait QueryFunction: Query { - /// See `CycleRecoveryStrategy` - const CYCLE_STRATEGY: CycleRecoveryStrategy; - - fn execute(db: &>::DynDb, key: Self::Key) -> Self::Value; - - fn cycle_fallback( - db: &>::DynDb, - cycle: &Cycle, - key: &Self::Key, - ) -> Self::Value { - let _ = (db, cycle, key); - panic!("query `{:?}` doesn't support cycle fallback", Self::default()) - } -} - -/// Cycle recovery strategy: Is this query capable of recovering from -/// a cycle that results from executing the function? If so, how? -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum CycleRecoveryStrategy { - /// Cannot recover from cycles: panic. - /// - /// This is the default. It is also what happens if a cycle - /// occurs and the queries involved have different recovery - /// strategies. - /// - /// In the case of a failure due to a cycle, the panic - /// value will be XXX (FIXME). - Panic, - - /// Recovers from cycles by storing a sentinel value. - /// - /// This value is computed by the `QueryFunction::cycle_fallback` - /// function. - Fallback, -} - -/// Create a query table, which has access to the storage for the query -/// and offers methods like `get`. -pub fn get_query_table<'me, Q>(db: &'me >::DynDb) -> QueryTable<'me, Q> -where - Q: Query + 'me, - Q::Storage: QueryStorageOps, -{ - let group_storage: &Q::GroupStorage = HasQueryGroup::group_storage(db); - let query_storage: &Q::Storage = Q::query_storage(group_storage); - QueryTable::new(db, query_storage) -} - -/// Create a mutable query table, which has access to the storage -/// for the query and offers methods like `set`. -pub fn get_query_table_mut<'me, Q>(db: &'me mut >::DynDb) -> QueryTableMut<'me, Q> -where - Q: Query, -{ - let (group_storage, runtime) = HasQueryGroup::group_storage_mut(db); - let query_storage = Q::query_storage_mut(group_storage); - QueryTableMut::new(runtime, &**query_storage) -} - -pub trait QueryGroup: Sized { - type GroupStorage; - - /// Dyn version of the associated database trait. - type DynDb: ?Sized + Database + HasQueryGroup; -} - -/// Trait implemented by a database for each group that it supports. -/// `S` and `K` are the types for *group storage* and *group key*, respectively. -pub trait HasQueryGroup: Database -where - G: QueryGroup, -{ - /// Access the group storage struct from the database. - fn group_storage(&self) -> &G::GroupStorage; - - /// Access the group storage struct from the database. - /// Also returns a ref to the `Runtime`, since otherwise - /// the database is borrowed and one cannot get access to it. - fn group_storage_mut(&mut self) -> (&G::GroupStorage, &mut Runtime); -} - -// ANCHOR:QueryStorageOps -pub trait QueryStorageOps -where - Self: QueryStorageMassOps, - Q: Query, -{ - // ANCHOR_END:QueryStorageOps - - /// See CycleRecoveryStrategy - const CYCLE_STRATEGY: CycleRecoveryStrategy; - - fn new(group_index: u16) -> Self; - - /// Format a database key index in a suitable way. - fn fmt_index( - &self, - db: &>::DynDb, - index: u32, - fmt: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result; - - // ANCHOR:maybe_changed_after - /// True if the value of `input`, which must be from this query, may have - /// changed after the given revision ended. - /// - /// This function should only be invoked with a revision less than the current - /// revision. - fn maybe_changed_after( - &self, - db: &>::DynDb, - index: u32, - revision: Revision, - ) -> bool; - // ANCHOR_END:maybe_changed_after - - fn cycle_recovery_strategy(&self) -> CycleRecoveryStrategy { - Self::CYCLE_STRATEGY - } - - // ANCHOR:fetch - /// Execute the query, returning the result (often, the result - /// will be memoized). This is the "main method" for - /// queries. - /// - /// Returns `Err` in the event of a cycle, meaning that computing - /// the value for this `key` is recursively attempting to fetch - /// itself. - fn fetch(&self, db: &>::DynDb, key: &Q::Key) -> Q::Value; - // ANCHOR_END:fetch - - /// Returns the durability associated with a given key. - fn durability(&self, db: &>::DynDb, key: &Q::Key) -> Durability; - - /// Get the (current) set of the entries in the query storage - fn entries(&self, db: &>::DynDb) -> C - where - C: std::iter::FromIterator>; -} - -/// An optional trait that is implemented for "user mutable" storage: -/// that is, storage whose value is not derived from other storage but -/// is set independently. -pub trait InputQueryStorageOps -where - Q: Query, -{ - fn set(&self, runtime: &mut Runtime, key: &Q::Key, new_value: Q::Value, durability: Durability); -} - -/// An optional trait that is implemented for "user mutable" storage: -/// that is, storage whose value is not derived from other storage but -/// is set independently. -pub trait LruQueryStorageOps { - fn set_lru_capacity(&self, new_capacity: u16); -} - -pub trait DerivedQueryStorageOps -where - Q: Query, -{ - fn invalidate(&self, runtime: &mut Runtime, key: &S) - where - S: Eq + Hash, - Q::Key: Borrow; -} - -pub type CycleParticipants = Arc>; diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/revision.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/revision.rs deleted file mode 100644 index 7f4c333fb1995..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/revision.rs +++ /dev/null @@ -1,66 +0,0 @@ -use std::num::NonZeroU32; -use std::sync::atomic::{AtomicU32, Ordering}; - -/// Value of the initial revision, as a u32. We don't use 0 -/// because we want to use a `NonZeroU32`. -const START: u32 = 1; - -/// A unique identifier for the current version of the database; each -/// time an input is changed, the revision number is incremented. -/// `Revision` is used internally to track which values may need to be -/// recomputed, but is not something you should have to interact with -/// directly as a user of salsa. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct Revision { - generation: NonZeroU32, -} - -impl Revision { - pub(crate) fn start() -> Self { - Self::from(START) - } - - pub(crate) fn from(g: u32) -> Self { - Self { generation: NonZeroU32::new(g).unwrap() } - } - - pub(crate) fn next(self) -> Revision { - Self::from(self.generation.get() + 1) - } - - fn as_u32(self) -> u32 { - self.generation.get() - } -} - -impl std::fmt::Debug for Revision { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(fmt, "R{}", self.generation) - } -} - -#[derive(Debug)] -pub(crate) struct AtomicRevision { - data: AtomicU32, -} - -impl AtomicRevision { - pub(crate) const fn start() -> Self { - Self { data: AtomicU32::new(START) } - } - - pub(crate) fn load(&self) -> Revision { - Revision::from(self.data.load(Ordering::SeqCst)) - } - - pub(crate) fn store(&self, r: Revision) { - self.data.store(r.as_u32(), Ordering::SeqCst); - } - - /// Increment by 1, returning previous value. - pub(crate) fn fetch_then_increment(&self) -> Revision { - let v = self.data.fetch_add(1, Ordering::SeqCst); - assert!(v != u32::MAX, "revision overflow"); - Revision::from(v) - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/runtime.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/runtime.rs deleted file mode 100644 index cb16ba0044dfd..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/runtime.rs +++ /dev/null @@ -1,668 +0,0 @@ -use crate::durability::Durability; -use crate::hash::FxIndexSet; -use crate::plumbing::CycleRecoveryStrategy; -use crate::revision::{AtomicRevision, Revision}; -use crate::{Cancelled, Cycle, Database, DatabaseKeyIndex, Event, EventKind}; -use itertools::Itertools; -use parking_lot::lock_api::{RawRwLock, RawRwLockRecursive}; -use parking_lot::{Mutex, RwLock}; -use std::hash::Hash; -use std::panic::panic_any; -use std::sync::atomic::{AtomicU32, Ordering}; -use tracing::trace; -use triomphe::{Arc, ThinArc}; - -mod dependency_graph; -use dependency_graph::DependencyGraph; - -pub(crate) mod local_state; -use local_state::LocalState; - -use self::local_state::{ActiveQueryGuard, QueryRevisions}; - -/// The salsa runtime stores the storage for all queries as well as -/// tracking the query stack and dependencies between cycles. -/// -/// Each new runtime you create (e.g., via `Runtime::new` or -/// `Runtime::default`) will have an independent set of query storage -/// associated with it. Normally, therefore, you only do this once, at -/// the start of your application. -pub struct Runtime { - /// Our unique runtime id. - id: RuntimeId, - - /// If this is a "forked" runtime, then the `revision_guard` will - /// be `Some`; this guard holds a read-lock on the global query - /// lock. - revision_guard: Option, - - /// Local state that is specific to this runtime (thread). - local_state: LocalState, - - /// Shared state that is accessible via all runtimes. - shared_state: Arc, -} - -#[derive(Clone, Debug)] -pub(crate) enum WaitResult { - Completed, - Panicked, - Cycle(Cycle), -} - -impl Default for Runtime { - fn default() -> Self { - Runtime { - id: RuntimeId { counter: 0 }, - revision_guard: None, - shared_state: Default::default(), - local_state: Default::default(), - } - } -} - -impl std::fmt::Debug for Runtime { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - fmt.debug_struct("Runtime") - .field("id", &self.id()) - .field("forked", &self.revision_guard.is_some()) - .field("shared_state", &self.shared_state) - .finish() - } -} - -impl Runtime { - /// Create a new runtime; equivalent to `Self::default`. This is - /// used when creating a new database. - pub fn new() -> Self { - Self::default() - } - - /// See [`crate::storage::Storage::snapshot`]. - pub(crate) fn snapshot(&self) -> Self { - if self.local_state.query_in_progress() { - panic!("it is not legal to `snapshot` during a query (see salsa-rs/salsa#80)"); - } - - let revision_guard = RevisionGuard::new(&self.shared_state); - - let id = RuntimeId { counter: self.shared_state.next_id.fetch_add(1, Ordering::SeqCst) }; - - Runtime { - id, - revision_guard: Some(revision_guard), - shared_state: self.shared_state.clone(), - local_state: Default::default(), - } - } - - /// A "synthetic write" causes the system to act *as though* some - /// input of durability `durability` has changed. This is mostly - /// useful for profiling scenarios. - /// - /// **WARNING:** Just like an ordinary write, this method triggers - /// cancellation. If you invoke it while a snapshot exists, it - /// will block until that snapshot is dropped -- if that snapshot - /// is owned by the current thread, this could trigger deadlock. - pub fn synthetic_write(&mut self, durability: Durability) { - self.with_incremented_revision(|_next_revision| Some(durability)); - } - - /// The unique identifier attached to this `SalsaRuntime`. Each - /// snapshotted runtime has a distinct identifier. - #[inline] - pub fn id(&self) -> RuntimeId { - self.id - } - - /// Returns the database-key for the query that this thread is - /// actively executing (if any). - pub fn active_query(&self) -> Option { - self.local_state.active_query() - } - - /// Read current value of the revision counter. - #[inline] - pub(crate) fn current_revision(&self) -> Revision { - self.shared_state.revisions[0].load() - } - - /// The revision in which values with durability `d` may have last - /// changed. For D0, this is just the current revision. But for - /// higher levels of durability, this value may lag behind the - /// current revision. If we encounter a value of durability Di, - /// then, we can check this function to get a "bound" on when the - /// value may have changed, which allows us to skip walking its - /// dependencies. - #[inline] - pub(crate) fn last_changed_revision(&self, d: Durability) -> Revision { - self.shared_state.revisions[d.index()].load() - } - - /// Read current value of the revision counter. - #[inline] - pub(crate) fn pending_revision(&self) -> Revision { - self.shared_state.pending_revision.load() - } - - #[cold] - pub(crate) fn unwind_cancelled(&self) { - self.report_untracked_read(); - Cancelled::PendingWrite.throw(); - } - - /// Acquires the **global query write lock** (ensuring that no queries are - /// executing) and then increments the current revision counter; invokes - /// `op` with the global query write lock still held. - /// - /// While we wait to acquire the global query write lock, this method will - /// also increment `pending_revision_increments`, thus signalling to queries - /// that their results are "cancelled" and they should abort as expeditiously - /// as possible. - /// - /// The `op` closure should actually perform the writes needed. It is given - /// the new revision as an argument, and its return value indicates whether - /// any pre-existing value was modified: - /// - /// - returning `None` means that no pre-existing value was modified (this - /// could occur e.g. when setting some key on an input that was never set - /// before) - /// - returning `Some(d)` indicates that a pre-existing value was modified - /// and it had the durability `d`. This will update the records for when - /// values with each durability were modified. - /// - /// Note that, given our writer model, we can assume that only one thread is - /// attempting to increment the global revision at a time. - pub(crate) fn with_incremented_revision(&mut self, op: F) - where - F: FnOnce(Revision) -> Option, - { - tracing::trace!("increment_revision()"); - - if !self.permits_increment() { - panic!("increment_revision invoked during a query computation"); - } - - // Set the `pending_revision` field so that people - // know current revision is cancelled. - let current_revision = self.shared_state.pending_revision.fetch_then_increment(); - - // To modify the revision, we need the lock. - let shared_state = self.shared_state.clone(); - let _lock = shared_state.query_lock.write(); - - let old_revision = self.shared_state.revisions[0].fetch_then_increment(); - assert_eq!(current_revision, old_revision); - - let new_revision = current_revision.next(); - - trace!("increment_revision: incremented to {:?}", new_revision); - - if let Some(d) = op(new_revision) { - for rev in &self.shared_state.revisions[1..=d.index()] { - rev.store(new_revision); - } - } - } - - pub(crate) fn permits_increment(&self) -> bool { - self.revision_guard.is_none() && !self.local_state.query_in_progress() - } - - #[inline] - pub(crate) fn push_query(&self, database_key_index: DatabaseKeyIndex) -> ActiveQueryGuard<'_> { - self.local_state.push_query(database_key_index) - } - - /// Reports that the currently active query read the result from - /// another query. - /// - /// Also checks whether the "cycle participant" flag is set on - /// the current stack frame -- if so, panics with `CycleParticipant` - /// value, which should be caught by the code executing the query. - /// - /// # Parameters - /// - /// - `database_key`: the query whose result was read - /// - `changed_revision`: the last revision in which the result of that - /// query had changed - pub(crate) fn report_query_read_and_unwind_if_cycle_resulted( - &self, - input: DatabaseKeyIndex, - durability: Durability, - changed_at: Revision, - ) { - self.local_state - .report_query_read_and_unwind_if_cycle_resulted(input, durability, changed_at); - } - - /// Reports that the query depends on some state unknown to salsa. - /// - /// Queries which report untracked reads will be re-executed in the next - /// revision. - pub fn report_untracked_read(&self) { - self.local_state.report_untracked_read(self.current_revision()); - } - - /// Acts as though the current query had read an input with the given durability; this will force the current query's durability to be at most `durability`. - /// - /// This is mostly useful to control the durability level for [on-demand inputs](https://salsa-rs.github.io/salsa/common_patterns/on_demand_inputs.html). - pub fn report_synthetic_read(&self, durability: Durability) { - let changed_at = self.last_changed_revision(durability); - self.local_state.report_synthetic_read(durability, changed_at); - } - - /// Handles a cycle in the dependency graph that was detected when the - /// current thread tried to block on `database_key_index` which is being - /// executed by `to_id`. If this function returns, then `to_id` no longer - /// depends on the current thread, and so we should continue executing - /// as normal. Otherwise, the function will throw a `Cycle` which is expected - /// to be caught by some frame on our stack. This occurs either if there is - /// a frame on our stack with cycle recovery (possibly the top one!) or if there - /// is no cycle recovery at all. - fn unblock_cycle_and_maybe_throw( - &self, - db: &dyn Database, - dg: &mut DependencyGraph, - database_key_index: DatabaseKeyIndex, - to_id: RuntimeId, - ) { - trace!("unblock_cycle_and_maybe_throw(database_key={:?})", database_key_index); - - let mut from_stack = self.local_state.take_query_stack(); - let from_id = self.id(); - - // Make a "dummy stack frame". As we iterate through the cycle, we will collect the - // inputs from each participant. Then, if we are participating in cycle recovery, we - // will propagate those results to all participants. - let mut cycle_query = ActiveQuery::new(database_key_index); - - // Identify the cycle participants: - let cycle = { - let mut v = vec![]; - dg.for_each_cycle_participant( - from_id, - &mut from_stack, - database_key_index, - to_id, - |aqs| { - aqs.iter_mut().for_each(|aq| { - cycle_query.add_from(aq); - v.push(aq.database_key_index); - }); - }, - ); - - // We want to give the participants in a deterministic order - // (at least for this execution, not necessarily across executions), - // no matter where it started on the stack. Find the minimum - // key and rotate it to the front. - let index = v.iter().position_min().unwrap_or_default(); - v.rotate_left(index); - - // No need to store extra memory. - v.shrink_to_fit(); - - Cycle::new(Arc::new(v)) - }; - trace!("cycle {:?}, cycle_query {:#?}", cycle.debug(db), cycle_query,); - - // We can remove the cycle participants from the list of dependencies; - // they are a strongly connected component (SCC) and we only care about - // dependencies to things outside the SCC that control whether it will - // form again. - cycle_query.remove_cycle_participants(&cycle); - - // Mark each cycle participant that has recovery set, along with - // any frames that come after them on the same thread. Those frames - // are going to be unwound so that fallback can occur. - dg.for_each_cycle_participant(from_id, &mut from_stack, database_key_index, to_id, |aqs| { - aqs.iter_mut() - .skip_while(|aq| match db.cycle_recovery_strategy(aq.database_key_index) { - CycleRecoveryStrategy::Panic => true, - CycleRecoveryStrategy::Fallback => false, - }) - .for_each(|aq| { - trace!("marking {:?} for fallback", aq.database_key_index.debug(db)); - aq.take_inputs_from(&cycle_query); - assert!(aq.cycle.is_none()); - aq.cycle = Some(cycle.clone()); - }); - }); - - // Unblock every thread that has cycle recovery with a `WaitResult::Cycle`. - // They will throw the cycle, which will be caught by the frame that has - // cycle recovery so that it can execute that recovery. - let (me_recovered, others_recovered) = - dg.maybe_unblock_runtimes_in_cycle(from_id, &from_stack, database_key_index, to_id); - - self.local_state.restore_query_stack(from_stack); - - if me_recovered { - // If the current thread has recovery, we want to throw - // so that it can begin. - cycle.throw() - } else if others_recovered { - // If other threads have recovery but we didn't: return and we will block on them. - } else { - // if nobody has recover, then we panic - panic_any(cycle); - } - } - - /// Block until `other_id` completes executing `database_key`; - /// panic or unwind in the case of a cycle. - /// - /// `query_mutex_guard` is the guard for the current query's state; - /// it will be dropped after we have successfully registered the - /// dependency. - /// - /// # Propagating panics - /// - /// If the thread `other_id` panics, then our thread is considered - /// cancelled, so this function will panic with a `Cancelled` value. - /// - /// # Cycle handling - /// - /// If the thread `other_id` already depends on the current thread, - /// and hence there is a cycle in the query graph, then this function - /// will unwind instead of returning normally. The method of unwinding - /// depends on the [`Self::mutual_cycle_recovery_strategy`] - /// of the cycle participants: - /// - /// * [`CycleRecoveryStrategy::Panic`]: panic with the [`Cycle`] as the value. - /// * [`CycleRecoveryStrategy::Fallback`]: initiate unwinding with [`CycleParticipant::unwind`]. - pub(crate) fn block_on_or_unwind( - &self, - db: &dyn Database, - database_key: DatabaseKeyIndex, - other_id: RuntimeId, - query_mutex_guard: QueryMutexGuard, - ) { - let mut dg = self.shared_state.dependency_graph.lock(); - - if dg.depends_on(other_id, self.id()) { - self.unblock_cycle_and_maybe_throw(db, &mut dg, database_key, other_id); - - // If the above fn returns, then (via cycle recovery) it has unblocked the - // cycle, so we can continue. - assert!(!dg.depends_on(other_id, self.id())); - } - - db.salsa_event(Event { - runtime_id: self.id(), - kind: EventKind::WillBlockOn { other_runtime_id: other_id, database_key }, - }); - - let stack = self.local_state.take_query_stack(); - - let (stack, result) = DependencyGraph::block_on( - dg, - self.id(), - database_key, - other_id, - stack, - query_mutex_guard, - ); - - self.local_state.restore_query_stack(stack); - - match result { - WaitResult::Completed => (), - - // If the other thread panicked, then we consider this thread - // cancelled. The assumption is that the panic will be detected - // by the other thread and responded to appropriately. - WaitResult::Panicked => Cancelled::PropagatedPanic.throw(), - - WaitResult::Cycle(c) => c.throw(), - } - } - - /// Invoked when this runtime completed computing `database_key` with - /// the given result `wait_result` (`wait_result` should be `None` if - /// computing `database_key` panicked and could not complete). - /// This function unblocks any dependent queries and allows them - /// to continue executing. - pub(crate) fn unblock_queries_blocked_on( - &self, - database_key: DatabaseKeyIndex, - wait_result: WaitResult, - ) { - self.shared_state - .dependency_graph - .lock() - .unblock_runtimes_blocked_on(database_key, wait_result); - } -} - -/// State that will be common to all threads (when we support multiple threads) -struct SharedState { - /// Stores the next id to use for a snapshotted runtime (starts at 1). - next_id: AtomicU32, - - /// Whenever derived queries are executing, they acquire this lock - /// in read mode. Mutating inputs (and thus creating a new - /// revision) requires a write lock (thus guaranteeing that no - /// derived queries are in progress). Note that this is not needed - /// to prevent **race conditions** -- the revision counter itself - /// is stored in an `AtomicUsize` so it can be cheaply read - /// without acquiring the lock. Rather, the `query_lock` is used - /// to ensure a higher-level consistency property. - query_lock: RwLock<()>, - - /// This is typically equal to `revision` -- set to `revision+1` - /// when a new revision is pending (which implies that the current - /// revision is cancelled). - pending_revision: AtomicRevision, - - /// Stores the "last change" revision for values of each Durability. - /// This vector is always of length at least 1 (for Durability 0) - /// but its total length depends on the number of Durabilities. The - /// element at index 0 is special as it represents the "current - /// revision". In general, we have the invariant that revisions - /// in here are *declining* -- that is, `revisions[i] >= - /// revisions[i + 1]`, for all `i`. This is because when you - /// modify a value with durability D, that implies that values - /// with durability less than D may have changed too. - revisions: [AtomicRevision; Durability::LEN], - - /// The dependency graph tracks which runtimes are blocked on one - /// another, waiting for queries to terminate. - dependency_graph: Mutex, -} - -impl std::panic::RefUnwindSafe for SharedState {} - -impl Default for SharedState { - fn default() -> Self { - #[allow(clippy::declare_interior_mutable_const)] - const START: AtomicRevision = AtomicRevision::start(); - SharedState { - next_id: AtomicU32::new(1), - query_lock: Default::default(), - revisions: [START; Durability::LEN], - pending_revision: START, - dependency_graph: Default::default(), - } - } -} - -impl std::fmt::Debug for SharedState { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let query_lock = if self.query_lock.is_locked_exclusive() { - "" - } else if self.query_lock.is_locked() { - "" - } else { - "" - }; - fmt.debug_struct("SharedState") - .field("query_lock", &query_lock) - .field("revisions", &self.revisions) - .field("pending_revision", &self.pending_revision) - .finish() - } -} - -#[derive(Debug)] -struct ActiveQuery { - /// What query is executing - database_key_index: DatabaseKeyIndex, - - /// Minimum durability of inputs observed so far. - durability: Durability, - - /// Maximum revision of all inputs observed. If we observe an - /// untracked read, this will be set to the most recent revision. - changed_at: Revision, - - /// Set of subqueries that were accessed thus far, or `None` if - /// there was an untracked the read. - dependencies: Option>, - - /// Stores the entire cycle, if one is found and this query is part of it. - cycle: Option, -} - -impl ActiveQuery { - fn new(database_key_index: DatabaseKeyIndex) -> Self { - ActiveQuery { - database_key_index, - durability: Durability::MAX, - changed_at: Revision::start(), - dependencies: Some(FxIndexSet::default()), - cycle: None, - } - } - - fn add_read(&mut self, input: DatabaseKeyIndex, durability: Durability, revision: Revision) { - if let Some(set) = &mut self.dependencies { - set.insert(input); - } - - self.durability = self.durability.min(durability); - self.changed_at = self.changed_at.max(revision); - } - - fn add_untracked_read(&mut self, changed_at: Revision) { - self.dependencies = None; - self.durability = Durability::LOW; - self.changed_at = changed_at; - } - - fn add_synthetic_read(&mut self, durability: Durability, revision: Revision) { - self.dependencies = None; - self.durability = self.durability.min(durability); - self.changed_at = self.changed_at.max(revision); - } - - pub(crate) fn revisions(&self) -> QueryRevisions { - let (inputs, untracked) = match &self.dependencies { - None => (None, true), - - Some(dependencies) => ( - if dependencies.is_empty() { - None - } else { - Some(ThinArc::from_header_and_iter((), dependencies.iter().copied())) - }, - false, - ), - }; - - QueryRevisions { - changed_at: self.changed_at, - inputs, - untracked, - durability: self.durability, - } - } - - /// Adds any dependencies from `other` into `self`. - /// Used during cycle recovery, see [`Runtime::create_cycle_error`]. - fn add_from(&mut self, other: &ActiveQuery) { - self.changed_at = self.changed_at.max(other.changed_at); - self.durability = self.durability.min(other.durability); - if let Some(other_dependencies) = &other.dependencies { - if let Some(my_dependencies) = &mut self.dependencies { - my_dependencies.extend(other_dependencies.iter().copied()); - } - } else { - self.dependencies = None; - } - } - - /// Removes the participants in `cycle` from my dependencies. - /// Used during cycle recovery, see [`Runtime::create_cycle_error`]. - fn remove_cycle_participants(&mut self, cycle: &Cycle) { - if let Some(my_dependencies) = &mut self.dependencies { - for p in cycle.participant_keys() { - my_dependencies.swap_remove(&p); - } - } - } - - /// Copy the changed-at, durability, and dependencies from `cycle_query`. - /// Used during cycle recovery, see [`Runtime::create_cycle_error`]. - pub(crate) fn take_inputs_from(&mut self, cycle_query: &ActiveQuery) { - self.changed_at = cycle_query.changed_at; - self.durability = cycle_query.durability; - self.dependencies.clone_from(&cycle_query.dependencies); - } -} - -/// A unique identifier for a particular runtime. Each time you create -/// a snapshot, a fresh `RuntimeId` is generated. Once a snapshot is -/// complete, its `RuntimeId` may potentially be re-used. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct RuntimeId { - counter: u32, -} - -#[derive(Clone, Debug)] -pub(crate) struct StampedValue { - pub(crate) value: V, - pub(crate) durability: Durability, - pub(crate) changed_at: Revision, -} - -struct RevisionGuard { - shared_state: Arc, -} - -impl RevisionGuard { - fn new(shared_state: &Arc) -> Self { - // Subtle: we use a "recursive" lock here so that it is not an - // error to acquire a read-lock when one is already held (this - // happens when a query uses `snapshot` to spawn off parallel - // workers, for example). - // - // This has the side-effect that we are responsible to ensure - // that people contending for the write lock do not starve, - // but this is what we achieve via the cancellation mechanism. - // - // (In particular, since we only ever have one "mutating - // handle" to the database, the only contention for the global - // query lock occurs when there are "futures" evaluating - // queries in parallel, and those futures hold a read-lock - // already, so the starvation problem is more about them bring - // themselves to a close, versus preventing other people from - // *starting* work). - unsafe { - shared_state.query_lock.raw().lock_shared_recursive(); - } - - Self { shared_state: shared_state.clone() } - } -} - -impl Drop for RevisionGuard { - fn drop(&mut self) { - // Release our read-lock without using RAII. As documented in - // `Snapshot::new` above, this requires the unsafe keyword. - unsafe { - self.shared_state.query_lock.raw().unlock_shared(); - } - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/runtime/dependency_graph.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/runtime/dependency_graph.rs deleted file mode 100644 index ed1d499f63735..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/runtime/dependency_graph.rs +++ /dev/null @@ -1,250 +0,0 @@ -use triomphe::Arc; - -use crate::{DatabaseKeyIndex, RuntimeId}; -use parking_lot::{Condvar, MutexGuard}; -use rustc_hash::FxHashMap; -use smallvec::SmallVec; - -use super::{ActiveQuery, WaitResult}; - -type QueryStack = Vec; - -#[derive(Debug, Default)] -pub(super) struct DependencyGraph { - /// A `(K -> V)` pair in this map indicates that the runtime - /// `K` is blocked on some query executing in the runtime `V`. - /// This encodes a graph that must be acyclic (or else deadlock - /// will result). - edges: FxHashMap, - - /// Encodes the `RuntimeId` that are blocked waiting for the result - /// of a given query. - query_dependents: FxHashMap>, - - /// When a key K completes which had dependent queries Qs blocked on it, - /// it stores its `WaitResult` here. As they wake up, each query Q in Qs will - /// come here to fetch their results. - wait_results: FxHashMap, -} - -#[derive(Debug)] -struct Edge { - blocked_on_id: RuntimeId, - blocked_on_key: DatabaseKeyIndex, - stack: QueryStack, - - /// Signalled whenever a query with dependents completes. - /// Allows those dependents to check if they are ready to unblock. - condvar: Arc, -} - -impl DependencyGraph { - /// True if `from_id` depends on `to_id`. - /// - /// (i.e., there is a path from `from_id` to `to_id` in the graph.) - pub(super) fn depends_on(&mut self, from_id: RuntimeId, to_id: RuntimeId) -> bool { - let mut p = from_id; - while let Some(q) = self.edges.get(&p).map(|edge| edge.blocked_on_id) { - if q == to_id { - return true; - } - - p = q; - } - p == to_id - } - - /// Invokes `closure` with a `&mut ActiveQuery` for each query that participates in the cycle. - /// The cycle runs as follows: - /// - /// 1. The runtime `from_id`, which has the stack `from_stack`, would like to invoke `database_key`... - /// 2. ...but `database_key` is already being executed by `to_id`... - /// 3. ...and `to_id` is transitively dependent on something which is present on `from_stack`. - pub(super) fn for_each_cycle_participant( - &mut self, - from_id: RuntimeId, - from_stack: &mut QueryStack, - database_key: DatabaseKeyIndex, - to_id: RuntimeId, - mut closure: impl FnMut(&mut [ActiveQuery]), - ) { - debug_assert!(self.depends_on(to_id, from_id)); - - // To understand this algorithm, consider this [drawing](https://is.gd/TGLI9v): - // - // database_key = QB2 - // from_id = A - // to_id = B - // from_stack = [QA1, QA2, QA3] - // - // self.edges[B] = { C, QC2, [QB1..QB3] } - // self.edges[C] = { A, QA2, [QC1..QC3] } - // - // The cyclic - // edge we have - // failed to add. - // : - // A : B C - // : - // QA1 v QB1 QC1 - // ┌► QA2 ┌──► QB2 ┌─► QC2 - // │ QA3 ───┘ QB3 ──┘ QC3 ───┐ - // │ │ - // └───────────────────────────────┘ - // - // Final output: [QB2, QB3, QC2, QC3, QA2, QA3] - - let mut id = to_id; - let mut key = database_key; - while id != from_id { - // Looking at the diagram above, the idea is to - // take the edge from `to_id` starting at `key` - // (inclusive) and down to the end. We can then - // load up the next thread (i.e., we start at B/QB2, - // and then load up the dependency on C/QC2). - let edge = self.edges.get_mut(&id).unwrap(); - let prefix = edge.stack.iter_mut().take_while(|p| p.database_key_index != key).count(); - closure(&mut edge.stack[prefix..]); - id = edge.blocked_on_id; - key = edge.blocked_on_key; - } - - // Finally, we copy in the results from `from_stack`. - let prefix = from_stack.iter_mut().take_while(|p| p.database_key_index != key).count(); - closure(&mut from_stack[prefix..]); - } - - /// Unblock each blocked runtime (excluding the current one) if some - /// query executing in that runtime is participating in cycle fallback. - /// - /// Returns a boolean (Current, Others) where: - /// * Current is true if the current runtime has cycle participants - /// with fallback; - /// * Others is true if other runtimes were unblocked. - pub(super) fn maybe_unblock_runtimes_in_cycle( - &mut self, - from_id: RuntimeId, - from_stack: &QueryStack, - database_key: DatabaseKeyIndex, - to_id: RuntimeId, - ) -> (bool, bool) { - // See diagram in `for_each_cycle_participant`. - let mut id = to_id; - let mut key = database_key; - let mut others_unblocked = false; - while id != from_id { - let edge = self.edges.get(&id).unwrap(); - let prefix = edge.stack.iter().take_while(|p| p.database_key_index != key).count(); - let next_id = edge.blocked_on_id; - let next_key = edge.blocked_on_key; - - if let Some(cycle) = edge.stack[prefix..].iter().rev().find_map(|aq| aq.cycle.clone()) { - // Remove `id` from the list of runtimes blocked on `next_key`: - self.query_dependents.get_mut(&next_key).unwrap().retain(|r| *r != id); - - // Unblock runtime so that it can resume execution once lock is released: - self.unblock_runtime(id, WaitResult::Cycle(cycle)); - - others_unblocked = true; - } - - id = next_id; - key = next_key; - } - - let prefix = from_stack.iter().take_while(|p| p.database_key_index != key).count(); - let this_unblocked = from_stack[prefix..].iter().any(|aq| aq.cycle.is_some()); - - (this_unblocked, others_unblocked) - } - - /// Modifies the graph so that `from_id` is blocked - /// on `database_key`, which is being computed by - /// `to_id`. - /// - /// For this to be reasonable, the lock on the - /// results table for `database_key` must be held. - /// This ensures that computing `database_key` doesn't - /// complete before `block_on` executes. - /// - /// Preconditions: - /// * No path from `to_id` to `from_id` - /// (i.e., `me.depends_on(to_id, from_id)` is false) - /// * `held_mutex` is a read lock (or stronger) on `database_key` - pub(super) fn block_on( - mut me: MutexGuard<'_, Self>, - from_id: RuntimeId, - database_key: DatabaseKeyIndex, - to_id: RuntimeId, - from_stack: QueryStack, - query_mutex_guard: QueryMutexGuard, - ) -> (QueryStack, WaitResult) { - let condvar = me.add_edge(from_id, database_key, to_id, from_stack); - - // Release the mutex that prevents `database_key` - // from completing, now that the edge has been added. - drop(query_mutex_guard); - - loop { - if let Some(stack_and_result) = me.wait_results.remove(&from_id) { - debug_assert!(!me.edges.contains_key(&from_id)); - return stack_and_result; - } - condvar.wait(&mut me); - } - } - - /// Helper for `block_on`: performs actual graph modification - /// to add a dependency edge from `from_id` to `to_id`, which is - /// computing `database_key`. - fn add_edge( - &mut self, - from_id: RuntimeId, - database_key: DatabaseKeyIndex, - to_id: RuntimeId, - from_stack: QueryStack, - ) -> Arc { - assert_ne!(from_id, to_id); - debug_assert!(!self.edges.contains_key(&from_id)); - debug_assert!(!self.depends_on(to_id, from_id)); - - let condvar = Arc::new(Condvar::new()); - self.edges.insert( - from_id, - Edge { - blocked_on_id: to_id, - blocked_on_key: database_key, - stack: from_stack, - condvar: condvar.clone(), - }, - ); - self.query_dependents.entry(database_key).or_default().push(from_id); - condvar - } - - /// Invoked when runtime `to_id` completes executing - /// `database_key`. - pub(super) fn unblock_runtimes_blocked_on( - &mut self, - database_key: DatabaseKeyIndex, - wait_result: WaitResult, - ) { - let dependents = self.query_dependents.remove(&database_key).unwrap_or_default(); - - for from_id in dependents { - self.unblock_runtime(from_id, wait_result.clone()); - } - } - - /// Unblock the runtime with the given id with the given wait-result. - /// This will cause it resume execution (though it will have to grab - /// the lock on this data structure first, to recover the wait result). - fn unblock_runtime(&mut self, id: RuntimeId, wait_result: WaitResult) { - let edge = self.edges.remove(&id).expect("not blocked"); - self.wait_results.insert(id, (edge.stack, wait_result)); - - // Now that we have inserted the `wait_results`, - // notify the thread. - edge.condvar.notify_one(); - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/runtime/local_state.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/runtime/local_state.rs deleted file mode 100644 index 4ab4bad0cc508..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/runtime/local_state.rs +++ /dev/null @@ -1,204 +0,0 @@ -use tracing::trace; -use triomphe::ThinArc; - -use crate::durability::Durability; -use crate::runtime::ActiveQuery; -use crate::runtime::Revision; -use crate::Cycle; -use crate::DatabaseKeyIndex; -use std::cell::RefCell; - -/// State that is specific to a single execution thread. -/// -/// Internally, this type uses ref-cells. -/// -/// **Note also that all mutations to the database handle (and hence -/// to the local-state) must be undone during unwinding.** -pub(super) struct LocalState { - /// Vector of active queries. - /// - /// This is normally `Some`, but it is set to `None` - /// while the query is blocked waiting for a result. - /// - /// Unwinding note: pushes onto this vector must be popped -- even - /// during unwinding. - query_stack: RefCell>>, -} - -/// Summarizes "all the inputs that a query used" -#[derive(Debug, Clone)] -pub(crate) struct QueryRevisions { - /// The most revision in which some input changed. - pub(crate) changed_at: Revision, - - /// Minimum durability of the inputs to this query. - pub(crate) durability: Durability, - - /// Whether the input is untracked. - /// Invariant: if `untracked`, `inputs` is `None`. - /// Why is this encoded like this and not a proper enum? Struct size, this saves us 8 bytes. - pub(crate) untracked: bool, - - /// The inputs that went into our query, if we are tracking them. - pub(crate) inputs: Option>, -} - -impl Default for LocalState { - fn default() -> Self { - LocalState { query_stack: RefCell::new(Some(Vec::new())) } - } -} - -impl LocalState { - #[inline] - pub(super) fn push_query(&self, database_key_index: DatabaseKeyIndex) -> ActiveQueryGuard<'_> { - let mut query_stack = self.query_stack.borrow_mut(); - let query_stack = query_stack.as_mut().expect("local stack taken"); - query_stack.push(ActiveQuery::new(database_key_index)); - ActiveQueryGuard { local_state: self, database_key_index, push_len: query_stack.len() } - } - - fn with_query_stack(&self, c: impl FnOnce(&mut Vec) -> R) -> R { - c(self.query_stack.borrow_mut().as_mut().expect("query stack taken")) - } - - pub(super) fn query_in_progress(&self) -> bool { - self.with_query_stack(|stack| !stack.is_empty()) - } - - pub(super) fn active_query(&self) -> Option { - self.with_query_stack(|stack| { - stack.last().map(|active_query| active_query.database_key_index) - }) - } - - pub(super) fn report_query_read_and_unwind_if_cycle_resulted( - &self, - input: DatabaseKeyIndex, - durability: Durability, - changed_at: Revision, - ) { - trace!( - "report_query_read_and_unwind_if_cycle_resulted(input={:?}, durability={:?}, changed_at={:?})", - input, durability, changed_at - ); - self.with_query_stack(|stack| { - if let Some(top_query) = stack.last_mut() { - top_query.add_read(input, durability, changed_at); - - // We are a cycle participant: - // - // C0 --> ... --> Ci --> Ci+1 -> ... -> Cn --> C0 - // ^ ^ - // : | - // This edge -----+ | - // | - // | - // N0 - // - // In this case, the value we have just read from `Ci+1` - // is actually the cycle fallback value and not especially - // interesting. We unwind now with `CycleParticipant` to avoid - // executing the rest of our query function. This unwinding - // will be caught and our own fallback value will be used. - // - // Note that `Ci+1` may` have *other* callers who are not - // participants in the cycle (e.g., N0 in the graph above). - // They will not have the `cycle` marker set in their - // stack frames, so they will just read the fallback value - // from `Ci+1` and continue on their merry way. - if let Some(cycle) = &top_query.cycle { - cycle.clone().throw() - } - } - }) - } - - pub(super) fn report_untracked_read(&self, current_revision: Revision) { - self.with_query_stack(|stack| { - if let Some(top_query) = stack.last_mut() { - top_query.add_untracked_read(current_revision); - } - }) - } - - /// Update the top query on the stack to act as though it read a value - /// of durability `durability` which changed in `revision`. - pub(super) fn report_synthetic_read(&self, durability: Durability, revision: Revision) { - self.with_query_stack(|stack| { - if let Some(top_query) = stack.last_mut() { - top_query.add_synthetic_read(durability, revision); - } - }) - } - - /// Takes the query stack and returns it. This is used when - /// the current thread is blocking. The stack must be restored - /// with [`Self::restore_query_stack`] when the thread unblocks. - pub(super) fn take_query_stack(&self) -> Vec { - self.query_stack.take().expect("query stack already taken") - } - - /// Restores a query stack taken with [`Self::take_query_stack`] once - /// the thread unblocks. - pub(super) fn restore_query_stack(&self, stack: Vec) { - assert!(self.query_stack.borrow().is_none(), "query stack not taken"); - self.query_stack.replace(Some(stack)); - } -} - -impl std::panic::RefUnwindSafe for LocalState {} - -/// When a query is pushed onto the `active_query` stack, this guard -/// is returned to represent its slot. The guard can be used to pop -/// the query from the stack -- in the case of unwinding, the guard's -/// destructor will also remove the query. -pub(crate) struct ActiveQueryGuard<'me> { - local_state: &'me LocalState, - push_len: usize, - database_key_index: DatabaseKeyIndex, -} - -impl ActiveQueryGuard<'_> { - fn pop_helper(&self) -> ActiveQuery { - self.local_state.with_query_stack(|stack| { - // Sanity check: pushes and pops should be balanced. - assert_eq!(stack.len(), self.push_len); - debug_assert_eq!(stack.last().unwrap().database_key_index, self.database_key_index); - stack.pop().unwrap() - }) - } - - /// Invoked when the query has successfully completed execution. - pub(super) fn complete(self) -> ActiveQuery { - let query = self.pop_helper(); - std::mem::forget(self); - query - } - - /// Pops an active query from the stack. Returns the [`QueryRevisions`] - /// which summarizes the other queries that were accessed during this - /// query's execution. - #[inline] - pub(crate) fn pop(self) -> QueryRevisions { - // Extract accumulated inputs. - let popped_query = self.complete(); - - // If this frame were a cycle participant, it would have unwound. - assert!(popped_query.cycle.is_none()); - - popped_query.revisions() - } - - /// If the active query is registered as a cycle participant, remove and - /// return that cycle. - pub(crate) fn take_cycle(&self) -> Option { - self.local_state.with_query_stack(|stack| stack.last_mut()?.cycle.take()) - } -} - -impl Drop for ActiveQueryGuard<'_> { - fn drop(&mut self) { - self.pop_helper(); - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/storage.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/storage.rs deleted file mode 100644 index e0acf44041b49..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/src/storage.rs +++ /dev/null @@ -1,53 +0,0 @@ -use crate::{plumbing::DatabaseStorageTypes, Runtime}; -use triomphe::Arc; - -/// Stores the cached results and dependency information for all the queries -/// defined on your salsa database. Also embeds a [`Runtime`] which is used to -/// manage query execution. Every database must include a `storage: -/// Storage` field. -pub struct Storage { - query_store: Arc, - runtime: Runtime, -} - -impl Default for Storage { - fn default() -> Self { - Self { query_store: Default::default(), runtime: Default::default() } - } -} - -impl Storage { - /// Gives access to the underlying salsa runtime. - pub fn salsa_runtime(&self) -> &Runtime { - &self.runtime - } - - /// Gives access to the underlying salsa runtime. - pub fn salsa_runtime_mut(&mut self) -> &mut Runtime { - &mut self.runtime - } - - /// Access the query storage tables. Not meant to be used directly by end - /// users. - pub fn query_store(&self) -> &DB::DatabaseStorage { - &self.query_store - } - - /// Access the query storage tables. Not meant to be used directly by end - /// users. - pub fn query_store_mut(&mut self) -> (&DB::DatabaseStorage, &mut Runtime) { - (&self.query_store, &mut self.runtime) - } - - /// Returns a "snapshotted" storage, suitable for use in a forked database. - /// This snapshot hold a read-lock on the global state, which means that any - /// attempt to `set` an input will block until the forked runtime is - /// dropped. See `ParallelDatabase::snapshot` for more information. - /// - /// **Warning.** This second handle is intended to be used from a separate - /// thread. Using two database handles from the **same thread** can lead to - /// deadlock. - pub fn snapshot(&self) -> Self { - Storage { query_store: self.query_store.clone(), runtime: self.runtime.snapshot() } - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/cycles.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/cycles.rs deleted file mode 100644 index 3c3931e658538..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/cycles.rs +++ /dev/null @@ -1,492 +0,0 @@ -use std::panic::UnwindSafe; - -use expect_test::expect; -use ra_salsa::{Durability, ParallelDatabase, Snapshot}; - -// Axes: -// -// Threading -// * Intra-thread -// * Cross-thread -- part of cycle is on one thread, part on another -// -// Recovery strategies: -// * Panic -// * Fallback -// * Mixed -- multiple strategies within cycle participants -// -// Across revisions: -// * N/A -- only one revision -// * Present in new revision, not old -// * Present in old revision, not new -// * Present in both revisions -// -// Dependencies -// * Tracked -// * Untracked -- cycle participant(s) contain untracked reads -// -// Layers -// * Direct -- cycle participant is directly invoked from test -// * Indirect -- invoked a query that invokes the cycle -// -// -// | Thread | Recovery | Old, New | Dep style | Layers | Test Name | -// | ------ | -------- | -------- | --------- | ------ | --------- | -// | Intra | Panic | N/A | Tracked | direct | cycle_memoized | -// | Intra | Panic | N/A | Untracked | direct | cycle_volatile | -// | Intra | Fallback | N/A | Tracked | direct | cycle_cycle | -// | Intra | Fallback | N/A | Tracked | indirect | inner_cycle | -// | Intra | Fallback | Both | Tracked | direct | cycle_revalidate | -// | Intra | Fallback | New | Tracked | direct | cycle_appears | -// | Intra | Fallback | Old | Tracked | direct | cycle_disappears | -// | Intra | Fallback | Old | Tracked | direct | cycle_disappears_durability | -// | Intra | Mixed | N/A | Tracked | direct | cycle_mixed_1 | -// | Intra | Mixed | N/A | Tracked | direct | cycle_mixed_2 | -// | Cross | Fallback | N/A | Tracked | both | parallel/cycles.rs: recover_parallel_cycle | -// | Cross | Panic | N/A | Tracked | both | parallel/cycles.rs: panic_parallel_cycle | - -#[derive(PartialEq, Eq, Hash, Clone, Debug)] -struct Error { - cycle: Vec, -} - -#[ra_salsa::database(GroupStruct)] -#[derive(Default)] -struct DatabaseImpl { - storage: ra_salsa::Storage, -} - -impl ra_salsa::Database for DatabaseImpl {} - -impl ParallelDatabase for DatabaseImpl { - fn snapshot(&self) -> Snapshot { - Snapshot::new(DatabaseImpl { storage: self.storage.snapshot() }) - } -} - -/// The queries A, B, and C in `Database` can be configured -/// to invoke one another in arbitrary ways using this -/// enum. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -enum CycleQuery { - None, - A, - B, - C, - AthenC, -} - -#[ra_salsa::query_group(GroupStruct)] -trait Database: ra_salsa::Database { - // `a` and `b` depend on each other and form a cycle - fn memoized_a(&self) -> (); - fn memoized_b(&self) -> (); - fn volatile_a(&self) -> (); - fn volatile_b(&self) -> (); - - #[ra_salsa::input] - fn a_invokes(&self) -> CycleQuery; - - #[ra_salsa::input] - fn b_invokes(&self) -> CycleQuery; - - #[ra_salsa::input] - fn c_invokes(&self) -> CycleQuery; - - #[ra_salsa::cycle(recover_a)] - fn cycle_a(&self) -> Result<(), Error>; - - #[ra_salsa::cycle(recover_b)] - fn cycle_b(&self) -> Result<(), Error>; - - fn cycle_c(&self) -> Result<(), Error>; -} - -fn recover_a(db: &dyn Database, cycle: &ra_salsa::Cycle) -> Result<(), Error> { - Err(Error { cycle: cycle.all_participants(db) }) -} - -fn recover_b(db: &dyn Database, cycle: &ra_salsa::Cycle) -> Result<(), Error> { - Err(Error { cycle: cycle.all_participants(db) }) -} - -fn memoized_a(db: &dyn Database) { - db.memoized_b() -} - -fn memoized_b(db: &dyn Database) { - db.memoized_a() -} - -fn volatile_a(db: &dyn Database) { - db.salsa_runtime().report_untracked_read(); - db.volatile_b() -} - -fn volatile_b(db: &dyn Database) { - db.salsa_runtime().report_untracked_read(); - db.volatile_a() -} - -impl CycleQuery { - fn invoke(self, db: &dyn Database) -> Result<(), Error> { - match self { - CycleQuery::A => db.cycle_a(), - CycleQuery::B => db.cycle_b(), - CycleQuery::C => db.cycle_c(), - CycleQuery::AthenC => { - let _ = db.cycle_a(); - db.cycle_c() - } - CycleQuery::None => Ok(()), - } - } -} - -fn cycle_a(db: &dyn Database) -> Result<(), Error> { - db.a_invokes().invoke(db) -} - -fn cycle_b(db: &dyn Database) -> Result<(), Error> { - db.b_invokes().invoke(db) -} - -fn cycle_c(db: &dyn Database) -> Result<(), Error> { - db.c_invokes().invoke(db) -} - -#[track_caller] -fn extract_cycle(f: impl FnOnce() + UnwindSafe) -> ra_salsa::Cycle { - let v = std::panic::catch_unwind(f); - if let Err(d) = &v { - if let Some(cycle) = d.downcast_ref::() { - return cycle.clone(); - } - } - panic!("unexpected value: {v:?}") -} - -#[test] -fn cycle_memoized() { - let db = DatabaseImpl::default(); - let cycle = extract_cycle(|| db.memoized_a()); - expect![[r#" - [ - "cycles::MemoizedAQuery::memoized_a(())", - "cycles::MemoizedBQuery::memoized_b(())", - ] - "#]] - .assert_debug_eq(&cycle.unexpected_participants(&db)); -} - -#[test] -fn cycle_volatile() { - let db = DatabaseImpl::default(); - let cycle = extract_cycle(|| db.volatile_a()); - expect![[r#" - [ - "cycles::VolatileAQuery::volatile_a(())", - "cycles::VolatileBQuery::volatile_b(())", - ] - "#]] - .assert_debug_eq(&cycle.unexpected_participants(&db)); -} - -#[test] -fn cycle_cycle() { - let mut query = DatabaseImpl::default(); - - // A --> B - // ^ | - // +-----+ - - query.set_a_invokes(CycleQuery::B); - query.set_b_invokes(CycleQuery::A); - - assert!(query.cycle_a().is_err()); -} - -#[test] -fn inner_cycle() { - let mut query = DatabaseImpl::default(); - - // A --> B <-- C - // ^ | - // +-----+ - - query.set_a_invokes(CycleQuery::B); - query.set_b_invokes(CycleQuery::A); - query.set_c_invokes(CycleQuery::B); - - let err = query.cycle_c(); - assert!(err.is_err()); - let cycle = err.unwrap_err().cycle; - expect![[r#" - [ - "cycles::CycleAQuery::cycle_a(())", - "cycles::CycleBQuery::cycle_b(())", - ] - "#]] - .assert_debug_eq(&cycle); -} - -#[test] -fn cycle_revalidate() { - let mut db = DatabaseImpl::default(); - - // A --> B - // ^ | - // +-----+ - db.set_a_invokes(CycleQuery::B); - db.set_b_invokes(CycleQuery::A); - - assert!(db.cycle_a().is_err()); - db.set_b_invokes(CycleQuery::A); // same value as default - assert!(db.cycle_a().is_err()); -} - -#[test] -fn cycle_revalidate_unchanged_twice() { - let mut db = DatabaseImpl::default(); - - // A --> B - // ^ | - // +-----+ - db.set_a_invokes(CycleQuery::B); - db.set_b_invokes(CycleQuery::A); - - assert!(db.cycle_a().is_err()); - db.set_c_invokes(CycleQuery::A); // force new revision - - // on this run - expect![[r#" - Err( - Error { - cycle: [ - "cycles::CycleAQuery::cycle_a(())", - "cycles::CycleBQuery::cycle_b(())", - ], - }, - ) - "#]] - .assert_debug_eq(&db.cycle_a()); -} - -#[test] -fn cycle_appears() { - let mut db = DatabaseImpl::default(); - - // A --> B - db.set_a_invokes(CycleQuery::B); - db.set_b_invokes(CycleQuery::None); - assert!(db.cycle_a().is_ok()); - - // A --> B - // ^ | - // +-----+ - db.set_b_invokes(CycleQuery::A); - tracing::debug!("Set Cycle Leaf"); - assert!(db.cycle_a().is_err()); -} - -#[test] -fn cycle_disappears() { - let mut db = DatabaseImpl::default(); - - // A --> B - // ^ | - // +-----+ - db.set_a_invokes(CycleQuery::B); - db.set_b_invokes(CycleQuery::A); - assert!(db.cycle_a().is_err()); - - // A --> B - db.set_b_invokes(CycleQuery::None); - assert!(db.cycle_a().is_ok()); -} - -/// A variant on `cycle_disappears` in which the values of -/// `a_invokes` and `b_invokes` are set with durability values. -/// If we are not careful, this could cause us to overlook -/// the fact that the cycle will no longer occur. -#[test] -fn cycle_disappears_durability() { - let mut db = DatabaseImpl::default(); - db.set_a_invokes_with_durability(CycleQuery::B, Durability::LOW); - db.set_b_invokes_with_durability(CycleQuery::A, Durability::HIGH); - - let res = db.cycle_a(); - assert!(res.is_err()); - - // At this point, `a` read `LOW` input, and `b` read `HIGH` input. However, - // because `b` participates in the same cycle as `a`, its final durability - // should be `LOW`. - // - // Check that setting a `LOW` input causes us to re-execute `b` query, and - // observe that the cycle goes away. - db.set_a_invokes_with_durability(CycleQuery::None, Durability::LOW); - - let res = db.cycle_b(); - assert!(res.is_ok()); -} - -#[test] -fn cycle_mixed_1() { - let mut db = DatabaseImpl::default(); - // A --> B <-- C - // | ^ - // +-----+ - db.set_a_invokes(CycleQuery::B); - db.set_b_invokes(CycleQuery::C); - db.set_c_invokes(CycleQuery::B); - - let u = db.cycle_c(); - expect![[r#" - Err( - Error { - cycle: [ - "cycles::CycleBQuery::cycle_b(())", - "cycles::CycleCQuery::cycle_c(())", - ], - }, - ) - "#]] - .assert_debug_eq(&u); -} - -#[test] -fn cycle_mixed_2() { - let mut db = DatabaseImpl::default(); - - // Configuration: - // - // A --> B --> C - // ^ | - // +-----------+ - db.set_a_invokes(CycleQuery::B); - db.set_b_invokes(CycleQuery::C); - db.set_c_invokes(CycleQuery::A); - - let u = db.cycle_a(); - expect![[r#" - Err( - Error { - cycle: [ - "cycles::CycleAQuery::cycle_a(())", - "cycles::CycleBQuery::cycle_b(())", - "cycles::CycleCQuery::cycle_c(())", - ], - }, - ) - "#]] - .assert_debug_eq(&u); -} - -#[test] -fn cycle_deterministic_order() { - // No matter whether we start from A or B, we get the same set of participants: - let db = || { - let mut db = DatabaseImpl::default(); - // A --> B - // ^ | - // +-----+ - db.set_a_invokes(CycleQuery::B); - db.set_b_invokes(CycleQuery::A); - db - }; - let a = db().cycle_a(); - let b = db().cycle_b(); - expect![[r#" - ( - Err( - Error { - cycle: [ - "cycles::CycleAQuery::cycle_a(())", - "cycles::CycleBQuery::cycle_b(())", - ], - }, - ), - Err( - Error { - cycle: [ - "cycles::CycleAQuery::cycle_a(())", - "cycles::CycleBQuery::cycle_b(())", - ], - }, - ), - ) - "#]] - .assert_debug_eq(&(a, b)); -} - -#[test] -fn cycle_multiple() { - // No matter whether we start from A or B, we get the same set of participants: - let mut db = DatabaseImpl::default(); - - // Configuration: - // - // A --> B <-- C - // ^ | ^ - // +-----+ | - // | | - // +-----+ - // - // Here, conceptually, B encounters a cycle with A and then - // recovers. - db.set_a_invokes(CycleQuery::B); - db.set_b_invokes(CycleQuery::AthenC); - db.set_c_invokes(CycleQuery::B); - - let c = db.cycle_c(); - let b = db.cycle_b(); - let a = db.cycle_a(); - expect![[r#" - ( - Err( - Error { - cycle: [ - "cycles::CycleAQuery::cycle_a(())", - "cycles::CycleBQuery::cycle_b(())", - ], - }, - ), - Err( - Error { - cycle: [ - "cycles::CycleAQuery::cycle_a(())", - "cycles::CycleBQuery::cycle_b(())", - ], - }, - ), - Err( - Error { - cycle: [ - "cycles::CycleAQuery::cycle_a(())", - "cycles::CycleBQuery::cycle_b(())", - ], - }, - ), - ) - "#]] - .assert_debug_eq(&(a, b, c)); -} - -#[test] -fn cycle_recovery_set_but_not_participating() { - let mut db = DatabaseImpl::default(); - - // A --> C -+ - // ^ | - // +--+ - db.set_a_invokes(CycleQuery::C); - db.set_c_invokes(CycleQuery::C); - - // Here we expect C to panic and A not to recover: - let r = extract_cycle(|| drop(db.cycle_a())); - expect![[r#" - [ - "cycles::CycleCQuery::cycle_c(())", - ] - "#]] - .assert_debug_eq(&r.all_participants(&db)); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/dyn_trait.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/dyn_trait.rs deleted file mode 100644 index 6075ae5c11e32..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/dyn_trait.rs +++ /dev/null @@ -1,28 +0,0 @@ -//! Test that you can implement a query using a `dyn Trait` setup. - -#[ra_salsa::database(DynTraitStorage)] -#[derive(Default)] -struct DynTraitDatabase { - storage: ra_salsa::Storage, -} - -impl ra_salsa::Database for DynTraitDatabase {} - -#[ra_salsa::query_group(DynTraitStorage)] -trait DynTrait { - #[ra_salsa::input] - fn input(&self, x: u32) -> u32; - - fn output(&self, x: u32) -> u32; -} - -fn output(db: &dyn DynTrait, x: u32) -> u32 { - db.input(x) * 2 -} - -#[test] -fn dyn_trait() { - let mut query = DynTraitDatabase::default(); - query.set_input(22, 23); - assert_eq!(query.output(22), 46); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/constants.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/constants.rs deleted file mode 100644 index 6e51545b60a15..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/constants.rs +++ /dev/null @@ -1,145 +0,0 @@ -use crate::implementation::{TestContext, TestContextImpl}; -use ra_salsa::debug::DebugQueryTable; -use ra_salsa::Durability; - -#[ra_salsa::query_group(Constants)] -pub(crate) trait ConstantsDatabase: TestContext { - #[ra_salsa::input] - fn input(&self, key: char) -> usize; - - fn add(&self, key1: char, key2: char) -> usize; - - fn add3(&self, key1: char, key2: char, key3: char) -> usize; -} - -fn add(db: &dyn ConstantsDatabase, key1: char, key2: char) -> usize { - db.log().add(format!("add({key1}, {key2})")); - db.input(key1) + db.input(key2) -} - -fn add3(db: &dyn ConstantsDatabase, key1: char, key2: char, key3: char) -> usize { - db.log().add(format!("add3({key1}, {key2}, {key3})")); - db.add(key1, key2) + db.input(key3) -} - -// Test we can assign a constant and things will be correctly -// recomputed afterwards. -#[test] -fn invalidate_constant() { - let db = &mut TestContextImpl::default(); - db.set_input_with_durability('a', 44, Durability::HIGH); - db.set_input_with_durability('b', 22, Durability::HIGH); - assert_eq!(db.add('a', 'b'), 66); - - db.set_input_with_durability('a', 66, Durability::HIGH); - assert_eq!(db.add('a', 'b'), 88); -} - -#[test] -fn invalidate_constant_1() { - let db = &mut TestContextImpl::default(); - - // Not constant: - db.set_input('a', 44); - assert_eq!(db.add('a', 'a'), 88); - - // Becomes constant: - db.set_input_with_durability('a', 44, Durability::HIGH); - assert_eq!(db.add('a', 'a'), 88); - - // Invalidates: - db.set_input_with_durability('a', 33, Durability::HIGH); - assert_eq!(db.add('a', 'a'), 66); -} - -// Test cases where we assign same value to 'a' after declaring it a -// constant. -#[test] -fn set_after_constant_same_value() { - let db = &mut TestContextImpl::default(); - db.set_input_with_durability('a', 44, Durability::HIGH); - db.set_input_with_durability('a', 44, Durability::HIGH); - db.set_input('a', 44); -} - -#[test] -fn not_constant() { - let mut db = TestContextImpl::default(); - - db.set_input('a', 22); - db.set_input('b', 44); - assert_eq!(db.add('a', 'b'), 66); - assert_eq!(Durability::LOW, AddQuery.in_db(&db).durability(('a', 'b'))); -} - -#[test] -fn durability() { - let mut db = TestContextImpl::default(); - - db.set_input_with_durability('a', 22, Durability::HIGH); - db.set_input_with_durability('b', 44, Durability::HIGH); - assert_eq!(db.add('a', 'b'), 66); - assert_eq!(Durability::HIGH, AddQuery.in_db(&db).durability(('a', 'b'))); -} - -#[test] -fn mixed_constant() { - let mut db = TestContextImpl::default(); - - db.set_input_with_durability('a', 22, Durability::HIGH); - db.set_input('b', 44); - assert_eq!(db.add('a', 'b'), 66); - assert_eq!(Durability::LOW, AddQuery.in_db(&db).durability(('a', 'b'))); -} - -#[test] -fn becomes_constant_with_change() { - let mut db = TestContextImpl::default(); - - db.set_input('a', 22); - db.set_input('b', 44); - assert_eq!(db.add('a', 'b'), 66); - assert_eq!(Durability::LOW, AddQuery.in_db(&db).durability(('a', 'b'))); - - db.set_input_with_durability('a', 23, Durability::HIGH); - assert_eq!(db.add('a', 'b'), 67); - assert_eq!(Durability::LOW, AddQuery.in_db(&db).durability(('a', 'b'))); - - db.set_input_with_durability('b', 45, Durability::HIGH); - assert_eq!(db.add('a', 'b'), 68); - assert_eq!(Durability::HIGH, AddQuery.in_db(&db).durability(('a', 'b'))); - - db.set_input_with_durability('b', 45, Durability::MEDIUM); - assert_eq!(db.add('a', 'b'), 68); - assert_eq!(Durability::MEDIUM, AddQuery.in_db(&db).durability(('a', 'b'))); -} - -// Test a subtle case in which an input changes from constant to -// non-constant, but its value doesn't change. If we're not careful, -// this can cause us to incorrectly consider derived values as still -// being constant. -#[test] -fn constant_to_non_constant() { - let mut db = TestContextImpl::default(); - - db.set_input_with_durability('a', 11, Durability::HIGH); - db.set_input_with_durability('b', 22, Durability::HIGH); - db.set_input_with_durability('c', 33, Durability::HIGH); - - // Here, `add3` invokes `add`, which yields 33. Both calls are - // constant. - assert_eq!(db.add3('a', 'b', 'c'), 66); - - db.set_input('a', 11); - - // Here, `add3` invokes `add`, which *still* yields 33, but which - // is no longer constant. Since value didn't change, we might - // preserve `add3` unchanged, not noticing that it is no longer - // constant. - assert_eq!(db.add3('a', 'b', 'c'), 66); - - // In that case, we would not get the correct result here, when - // 'a' changes *again*. - db.set_input('a', 22); - assert_eq!(db.add3('a', 'b', 'c'), 77); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/counter.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/counter.rs deleted file mode 100644 index c04857e24c9e8..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/counter.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::cell::Cell; - -#[derive(Default)] -pub(crate) struct Counter { - value: Cell, -} - -impl Counter { - pub(crate) fn increment(&self) -> usize { - let v = self.value.get(); - self.value.set(v + 1); - v - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/implementation.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/implementation.rs deleted file mode 100644 index e9a59c4630451..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/implementation.rs +++ /dev/null @@ -1,59 +0,0 @@ -use crate::constants; -use crate::counter::Counter; -use crate::log::Log; -use crate::memoized_dep_inputs; -use crate::memoized_inputs; -use crate::memoized_volatile; - -pub(crate) trait TestContext: ra_salsa::Database { - fn clock(&self) -> &Counter; - fn log(&self) -> &Log; -} - -#[ra_salsa::database( - constants::Constants, - memoized_dep_inputs::MemoizedDepInputs, - memoized_inputs::MemoizedInputs, - memoized_volatile::MemoizedVolatile -)] -#[derive(Default)] -pub(crate) struct TestContextImpl { - storage: ra_salsa::Storage, - clock: Counter, - log: Log, -} - -impl TestContextImpl { - #[track_caller] - pub(crate) fn assert_log(&self, expected_log: &[&str]) { - let expected_text = &format!("{expected_log:#?}"); - let actual_text = &format!("{:#?}", self.log().take()); - - if expected_text == actual_text { - return; - } - - #[allow(clippy::print_stdout)] - for diff in dissimilar::diff(expected_text, actual_text) { - match diff { - dissimilar::Chunk::Delete(l) => println!("-{l}"), - dissimilar::Chunk::Equal(l) => println!(" {l}"), - dissimilar::Chunk::Insert(r) => println!("+{r}"), - } - } - - panic!("incorrect log results"); - } -} - -impl TestContext for TestContextImpl { - fn clock(&self) -> &Counter { - &self.clock - } - - fn log(&self) -> &Log { - &self.log - } -} - -impl ra_salsa::Database for TestContextImpl {} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/log.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/log.rs deleted file mode 100644 index 1ee57fe667d5f..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/log.rs +++ /dev/null @@ -1,16 +0,0 @@ -use std::cell::RefCell; - -#[derive(Default)] -pub(crate) struct Log { - data: RefCell>, -} - -impl Log { - pub(crate) fn add(&self, text: impl Into) { - self.data.borrow_mut().push(text.into()); - } - - pub(crate) fn take(&self) -> Vec { - self.data.take() - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/main.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/main.rs deleted file mode 100644 index bcd13c75f7157..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/main.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod constants; -mod counter; -mod implementation; -mod log; -mod memoized_dep_inputs; -mod memoized_inputs; -mod memoized_volatile; - -fn main() {} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_dep_inputs.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_dep_inputs.rs deleted file mode 100644 index 0043bb45745d8..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_dep_inputs.rs +++ /dev/null @@ -1,60 +0,0 @@ -use crate::implementation::{TestContext, TestContextImpl}; - -#[ra_salsa::query_group(MemoizedDepInputs)] -pub(crate) trait MemoizedDepInputsContext: TestContext { - fn dep_memoized2(&self) -> usize; - fn dep_memoized1(&self) -> usize; - #[ra_salsa::dependencies] - fn dep_derived1(&self) -> usize; - #[ra_salsa::input] - fn dep_input1(&self) -> usize; - #[ra_salsa::input] - fn dep_input2(&self) -> usize; -} - -fn dep_memoized2(db: &dyn MemoizedDepInputsContext) -> usize { - db.log().add("Memoized2 invoked"); - db.dep_memoized1() -} - -fn dep_memoized1(db: &dyn MemoizedDepInputsContext) -> usize { - db.log().add("Memoized1 invoked"); - db.dep_derived1() * 2 -} - -fn dep_derived1(db: &dyn MemoizedDepInputsContext) -> usize { - db.log().add("Derived1 invoked"); - db.dep_input1() / 2 -} - -#[test] -fn revalidate() { - let db = &mut TestContextImpl::default(); - - db.set_dep_input1(0); - - // Initial run starts from Memoized2: - let v = db.dep_memoized2(); - assert_eq!(v, 0); - db.assert_log(&["Memoized2 invoked", "Memoized1 invoked", "Derived1 invoked"]); - - // After that, we first try to validate Memoized1 but wind up - // running Memoized2. Note that we don't try to validate - // Derived1, so it is invoked by Memoized1. - db.set_dep_input1(44); - let v = db.dep_memoized2(); - assert_eq!(v, 44); - db.assert_log(&["Memoized1 invoked", "Derived1 invoked", "Memoized2 invoked"]); - - // Here validation of Memoized1 succeeds so Memoized2 never runs. - db.set_dep_input1(45); - let v = db.dep_memoized2(); - assert_eq!(v, 44); - db.assert_log(&["Memoized1 invoked", "Derived1 invoked"]); - - // Here, a change to input2 doesn't affect us, so nothing runs. - db.set_dep_input2(45); - let v = db.dep_memoized2(); - assert_eq!(v, 44); - db.assert_log(&[]); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_inputs.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_inputs.rs deleted file mode 100644 index 007dc3db95a34..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_inputs.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::implementation::{TestContext, TestContextImpl}; - -#[ra_salsa::query_group(MemoizedInputs)] -pub(crate) trait MemoizedInputsContext: TestContext { - fn max(&self) -> usize; - #[ra_salsa::input] - fn input1(&self) -> usize; - #[ra_salsa::input] - fn input2(&self) -> usize; -} - -fn max(db: &dyn MemoizedInputsContext) -> usize { - db.log().add("Max invoked"); - std::cmp::max(db.input1(), db.input2()) -} - -#[test] -fn revalidate() { - let db = &mut TestContextImpl::default(); - - db.set_input1(0); - db.set_input2(0); - - let v = db.max(); - assert_eq!(v, 0); - db.assert_log(&["Max invoked"]); - - let v = db.max(); - assert_eq!(v, 0); - db.assert_log(&[]); - - db.set_input1(44); - db.assert_log(&[]); - - let v = db.max(); - assert_eq!(v, 44); - db.assert_log(&["Max invoked"]); - - let v = db.max(); - assert_eq!(v, 44); - db.assert_log(&[]); - - db.set_input1(44); - db.assert_log(&[]); - db.set_input2(66); - db.assert_log(&[]); - db.set_input1(64); - db.assert_log(&[]); - - let v = db.max(); - assert_eq!(v, 66); - db.assert_log(&["Max invoked"]); - - let v = db.max(); - assert_eq!(v, 66); - db.assert_log(&[]); -} - -/// Test that invoking `set` on an input with the same value still -/// triggers a new revision. -#[test] -fn set_after_no_change() { - let db = &mut TestContextImpl::default(); - - db.set_input2(0); - - db.set_input1(44); - let v = db.max(); - assert_eq!(v, 44); - db.assert_log(&["Max invoked"]); - - db.set_input1(44); - let v = db.max(); - assert_eq!(v, 44); - db.assert_log(&["Max invoked"]); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_volatile.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_volatile.rs deleted file mode 100644 index cd00cc2e6ccb6..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/incremental/memoized_volatile.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::implementation::{TestContext, TestContextImpl}; -use ra_salsa::{Database, Durability}; - -#[ra_salsa::query_group(MemoizedVolatile)] -pub(crate) trait MemoizedVolatileContext: TestContext { - // Queries for testing a "volatile" value wrapped by - // memoization. - fn memoized2(&self) -> usize; - fn memoized1(&self) -> usize; - fn volatile(&self) -> usize; -} - -fn memoized2(db: &dyn MemoizedVolatileContext) -> usize { - db.log().add("Memoized2 invoked"); - db.memoized1() -} - -fn memoized1(db: &dyn MemoizedVolatileContext) -> usize { - db.log().add("Memoized1 invoked"); - let v = db.volatile(); - v / 2 -} - -fn volatile(db: &dyn MemoizedVolatileContext) -> usize { - db.log().add("Volatile invoked"); - db.salsa_runtime().report_untracked_read(); - db.clock().increment() -} - -#[test] -fn volatile_x2() { - let query = TestContextImpl::default(); - - // Invoking volatile twice doesn't execute twice, because volatile - // queries are memoized by default. - query.volatile(); - query.volatile(); - query.assert_log(&["Volatile invoked"]); -} - -/// Test that: -/// -/// - On the first run of R0, we recompute everything. -/// - On the second run of R1, we recompute nothing. -/// - On the first run of R1, we recompute Memoized1 but not Memoized2 (since Memoized1 result -/// did not change). -/// - On the second run of R1, we recompute nothing. -/// - On the first run of R2, we recompute everything (since Memoized1 result *did* change). -#[test] -fn revalidate() { - let mut query = TestContextImpl::default(); - - query.memoized2(); - query.assert_log(&["Memoized2 invoked", "Memoized1 invoked", "Volatile invoked"]); - - query.memoized2(); - query.assert_log(&[]); - - // Second generation: volatile will change (to 1) but memoized1 - // will not (still 0, as 1/2 = 0) - query.synthetic_write(Durability::LOW); - query.memoized2(); - query.assert_log(&["Volatile invoked", "Memoized1 invoked"]); - query.memoized2(); - query.assert_log(&[]); - - // Third generation: volatile will change (to 2) and memoized1 - // will too (to 1). Therefore, after validating that Memoized1 - // changed, we now invoke Memoized2. - query.synthetic_write(Durability::LOW); - - query.memoized2(); - query.assert_log(&["Volatile invoked", "Memoized1 invoked", "Memoized2 invoked"]); - - query.memoized2(); - query.assert_log(&[]); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/interned.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/interned.rs deleted file mode 100644 index 108b129fa3f76..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/interned.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! Test that you can implement a query using a `dyn Trait` setup. - -use ra_salsa::InternId; - -#[ra_salsa::database(InternStorage)] -#[derive(Default)] -struct Database { - storage: ra_salsa::Storage, -} - -impl ra_salsa::Database for Database {} - -impl ra_salsa::ParallelDatabase for Database { - fn snapshot(&self) -> ra_salsa::Snapshot { - ra_salsa::Snapshot::new(Database { storage: self.storage.snapshot() }) - } -} - -#[ra_salsa::query_group(InternStorage)] -trait Intern { - #[ra_salsa::interned] - fn intern1(&self, x: String) -> InternId; - - #[ra_salsa::interned] - fn intern2(&self, x: String, y: String) -> InternId; - - #[ra_salsa::interned] - fn intern_key(&self, x: String) -> InternKey; -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct InternKey(InternId); - -impl ra_salsa::InternKey for InternKey { - fn from_intern_id(v: InternId) -> Self { - InternKey(v) - } - - fn as_intern_id(&self) -> InternId { - self.0 - } -} - -#[test] -fn test_intern1() { - let db = Database::default(); - let foo0 = db.intern1("foo".to_owned()); - let bar0 = db.intern1("bar".to_owned()); - let foo1 = db.intern1("foo".to_owned()); - let bar1 = db.intern1("bar".to_owned()); - - assert_eq!(foo0, foo1); - assert_eq!(bar0, bar1); - assert_ne!(foo0, bar0); - - assert_eq!("foo".to_owned(), db.lookup_intern1(foo0)); - assert_eq!("bar".to_owned(), db.lookup_intern1(bar0)); -} - -#[test] -fn test_intern2() { - let db = Database::default(); - let foo0 = db.intern2("x".to_owned(), "foo".to_owned()); - let bar0 = db.intern2("x".to_owned(), "bar".to_owned()); - let foo1 = db.intern2("x".to_owned(), "foo".to_owned()); - let bar1 = db.intern2("x".to_owned(), "bar".to_owned()); - - assert_eq!(foo0, foo1); - assert_eq!(bar0, bar1); - assert_ne!(foo0, bar0); - - assert_eq!(("x".to_owned(), "foo".to_owned()), db.lookup_intern2(foo0)); - assert_eq!(("x".to_owned(), "bar".to_owned()), db.lookup_intern2(bar0)); -} - -#[test] -fn test_intern_key() { - let db = Database::default(); - let foo0 = db.intern_key("foo".to_owned()); - let bar0 = db.intern_key("bar".to_owned()); - let foo1 = db.intern_key("foo".to_owned()); - let bar1 = db.intern_key("bar".to_owned()); - - assert_eq!(foo0, foo1); - assert_eq!(bar0, bar1); - assert_ne!(foo0, bar0); - - assert_eq!("foo".to_owned(), db.lookup_intern_key(foo0)); - assert_eq!("bar".to_owned(), db.lookup_intern_key(bar0)); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/lru.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/lru.rs deleted file mode 100644 index f351f24246868..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/lru.rs +++ /dev/null @@ -1,104 +0,0 @@ -//! Test setting LRU actually limits the number of things in the database; -use std::sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, -}; - -#[derive(Debug, PartialEq, Eq)] -struct HotPotato(u32); - -static N_POTATOES: AtomicUsize = AtomicUsize::new(0); - -impl HotPotato { - fn new(id: u32) -> HotPotato { - N_POTATOES.fetch_add(1, Ordering::SeqCst); - HotPotato(id) - } -} - -impl Drop for HotPotato { - fn drop(&mut self) { - N_POTATOES.fetch_sub(1, Ordering::SeqCst); - } -} - -#[ra_salsa::query_group(QueryGroupStorage)] -trait QueryGroup: ra_salsa::Database { - #[ra_salsa::lru] - fn get(&self, x: u32) -> Arc; - #[ra_salsa::lru] - fn get_volatile(&self, x: u32) -> usize; -} - -fn get(_db: &dyn QueryGroup, x: u32) -> Arc { - Arc::new(HotPotato::new(x)) -} - -fn get_volatile(db: &dyn QueryGroup, _x: u32) -> usize { - static COUNTER: AtomicUsize = AtomicUsize::new(0); - db.salsa_runtime().report_untracked_read(); - COUNTER.fetch_add(1, Ordering::SeqCst) -} - -#[ra_salsa::database(QueryGroupStorage)] -#[derive(Default)] -struct Database { - storage: ra_salsa::Storage, -} - -impl ra_salsa::Database for Database {} - -#[test] -fn lru_works() { - let mut db = Database::default(); - GetQuery.in_db_mut(&mut db).set_lru_capacity(32); - assert_eq!(N_POTATOES.load(Ordering::SeqCst), 0); - - for i in 0..128u32 { - let p = db.get(i); - assert_eq!(p.0, i) - } - assert_eq!(N_POTATOES.load(Ordering::SeqCst), 32); - - for i in 0..128u32 { - let p = db.get(i); - assert_eq!(p.0, i) - } - assert_eq!(N_POTATOES.load(Ordering::SeqCst), 32); - - GetQuery.in_db_mut(&mut db).set_lru_capacity(32); - assert_eq!(N_POTATOES.load(Ordering::SeqCst), 32); - - GetQuery.in_db_mut(&mut db).set_lru_capacity(64); - assert_eq!(N_POTATOES.load(Ordering::SeqCst), 32); - for i in 0..128u32 { - let p = db.get(i); - assert_eq!(p.0, i) - } - assert_eq!(N_POTATOES.load(Ordering::SeqCst), 64); - - // Special case: setting capacity to zero disables LRU - GetQuery.in_db_mut(&mut db).set_lru_capacity(0); - assert_eq!(N_POTATOES.load(Ordering::SeqCst), 64); - for i in 0..128u32 { - let p = db.get(i); - assert_eq!(p.0, i) - } - assert_eq!(N_POTATOES.load(Ordering::SeqCst), 128); - - drop(db); - assert_eq!(N_POTATOES.load(Ordering::SeqCst), 0); -} - -#[test] -fn lru_doesnt_break_volatile_queries() { - let mut db = Database::default(); - GetVolatileQuery.in_db_mut(&mut db).set_lru_capacity(32); - // Here, we check that we execute each volatile query at most once, despite - // LRU. That does mean that we have more values in DB than the LRU capacity, - // but it's much better than inconsistent results from volatile queries! - for i in (0..3).flat_map(|_| 0..128usize) { - let x = db.get_volatile(i as u32); - assert_eq!(x, i) - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/macros.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/macros.rs deleted file mode 100644 index 7bb6369b500c1..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/macros.rs +++ /dev/null @@ -1,12 +0,0 @@ -#[ra_salsa::query_group(MyStruct)] -trait MyDatabase: ra_salsa::Database { - #[ra_salsa::invoke(another_module::another_name)] - fn my_query(&self, key: ()) -> (); -} - -mod another_module { - #[allow(dead_code)] - pub(crate) fn another_name(_: &dyn crate::MyDatabase, (): ()) {} -} - -fn main() {} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/no_send_sync.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/no_send_sync.rs deleted file mode 100644 index 56bd3f4a7ed18..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/no_send_sync.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::rc::Rc; - -#[ra_salsa::query_group(NoSendSyncStorage)] -trait NoSendSyncDatabase: ra_salsa::Database { - fn no_send_sync_value(&self, key: bool) -> Rc; - fn no_send_sync_key(&self, key: Rc) -> bool; -} - -fn no_send_sync_value(_db: &dyn NoSendSyncDatabase, key: bool) -> Rc { - Rc::new(key) -} - -fn no_send_sync_key(_db: &dyn NoSendSyncDatabase, key: Rc) -> bool { - *key -} - -#[ra_salsa::database(NoSendSyncStorage)] -#[derive(Default)] -struct DatabaseImpl { - storage: ra_salsa::Storage, -} - -impl ra_salsa::Database for DatabaseImpl {} - -#[test] -fn no_send_sync() { - let db = DatabaseImpl::default(); - - assert_eq!(db.no_send_sync_value(true), Rc::new(true)); - assert!(!db.no_send_sync_key(Rc::new(false))); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/on_demand_inputs.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/on_demand_inputs.rs deleted file mode 100644 index 4d7832f9ba05b..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/on_demand_inputs.rs +++ /dev/null @@ -1,147 +0,0 @@ -//! Test that "on-demand" input pattern works. -//! -//! On-demand inputs are inputs computed lazily on the fly. They are simulated -//! via a b query with zero inputs, which uses `add_synthetic_read` to -//! tweak durability and `invalidate` to clear the input. - -#![allow(clippy::disallowed_types, clippy::type_complexity)] - -use std::{cell::RefCell, collections::HashMap, rc::Rc}; - -use ra_salsa::{Database as _, Durability, EventKind}; - -#[ra_salsa::query_group(QueryGroupStorage)] -trait QueryGroup: ra_salsa::Database + AsRef> { - fn a(&self, x: u32) -> u32; - fn b(&self, x: u32) -> u32; - fn c(&self, x: u32) -> u32; -} - -fn a(db: &dyn QueryGroup, x: u32) -> u32 { - let durability = if x % 2 == 0 { Durability::LOW } else { Durability::HIGH }; - db.salsa_runtime().report_synthetic_read(durability); - let external_state: &HashMap = db.as_ref(); - external_state[&x] -} - -fn b(db: &dyn QueryGroup, x: u32) -> u32 { - db.a(x) -} - -fn c(db: &dyn QueryGroup, x: u32) -> u32 { - db.b(x) -} - -#[ra_salsa::database(QueryGroupStorage)] -#[derive(Default)] -struct Database { - storage: ra_salsa::Storage, - external_state: HashMap, - on_event: Option>, -} - -impl ra_salsa::Database for Database { - fn salsa_event(&self, event: ra_salsa::Event) { - if let Some(cb) = &self.on_event { - cb(self, event) - } - } -} - -impl AsRef> for Database { - fn as_ref(&self) -> &HashMap { - &self.external_state - } -} - -#[test] -fn on_demand_input_works() { - let mut db = Database::default(); - - db.external_state.insert(1, 10); - assert_eq!(db.b(1), 10); - assert_eq!(db.a(1), 10); - - // We changed external state, but haven't signaled about this yet, - // so we expect to see the old answer - db.external_state.insert(1, 92); - assert_eq!(db.b(1), 10); - assert_eq!(db.a(1), 10); - - AQuery.in_db_mut(&mut db).invalidate(&1); - assert_eq!(db.b(1), 92); - assert_eq!(db.a(1), 92); - - // Downstream queries should also be rerun if we call `a` first. - db.external_state.insert(1, 50); - AQuery.in_db_mut(&mut db).invalidate(&1); - assert_eq!(db.a(1), 50); - assert_eq!(db.b(1), 50); -} - -#[test] -fn on_demand_input_durability() { - let mut db = Database::default(); - - let events = Rc::new(RefCell::new(vec![])); - db.on_event = Some(Box::new({ - let events = events.clone(); - move |db, event| { - if let EventKind::WillCheckCancellation = event.kind { - // these events are not interesting - } else { - events.borrow_mut().push(format!("{:?}", event.debug(db))) - } - } - })); - - events.replace(vec![]); - db.external_state.insert(1, 10); - db.external_state.insert(2, 20); - assert_eq!(db.b(1), 10); - assert_eq!(db.b(2), 20); - expect_test::expect![[r#" - RefCell { - value: [ - "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::BQuery::b(1) } }", - "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(1) } }", - "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::BQuery::b(2) } }", - "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(2) } }", - ], - } - "#]].assert_debug_eq(&events); - - db.synthetic_write(Durability::LOW); - events.replace(vec![]); - assert_eq!(db.c(1), 10); - assert_eq!(db.c(2), 20); - // Re-execute `a(2)` because that has low durability, but not `a(1)` - expect_test::expect![[r#" - RefCell { - value: [ - "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::CQuery::c(1) } }", - "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::BQuery::b(1) } }", - "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::CQuery::c(2) } }", - "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(2) } }", - "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::BQuery::b(2) } }", - ], - } - "#]].assert_debug_eq(&events); - - db.synthetic_write(Durability::HIGH); - events.replace(vec![]); - assert_eq!(db.c(1), 10); - assert_eq!(db.c(2), 20); - // Re-execute both `a(1)` and `a(2)`, but we don't re-execute any `b` queries as the - // result didn't actually change. - expect_test::expect![[r#" - RefCell { - value: [ - "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(1) } }", - "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::CQuery::c(1) } }", - "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(2) } }", - "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::CQuery::c(2) } }", - ], - } - "#]].assert_debug_eq(&events); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/panic_safely.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/panic_safely.rs deleted file mode 100644 index 047a50eb4b2b4..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/panic_safely.rs +++ /dev/null @@ -1,93 +0,0 @@ -use ra_salsa::{Database, ParallelDatabase, Snapshot}; -use std::panic::{self, AssertUnwindSafe}; -use std::sync::atomic::{AtomicU32, Ordering::SeqCst}; - -#[ra_salsa::query_group(PanicSafelyStruct)] -trait PanicSafelyDatabase: ra_salsa::Database { - #[ra_salsa::input] - fn one(&self) -> usize; - - fn panic_safely(&self) -> (); - - fn outer(&self) -> (); -} - -fn panic_safely(db: &dyn PanicSafelyDatabase) { - assert_eq!(db.one(), 1); -} - -static OUTER_CALLS: AtomicU32 = AtomicU32::new(0); - -fn outer(db: &dyn PanicSafelyDatabase) { - OUTER_CALLS.fetch_add(1, SeqCst); - db.panic_safely(); -} - -#[ra_salsa::database(PanicSafelyStruct)] -#[derive(Default)] -struct DatabaseStruct { - storage: ra_salsa::Storage, -} - -impl ra_salsa::Database for DatabaseStruct {} - -impl ra_salsa::ParallelDatabase for DatabaseStruct { - fn snapshot(&self) -> Snapshot { - Snapshot::new(DatabaseStruct { storage: self.storage.snapshot() }) - } -} - -#[test] -fn should_panic_safely() { - let mut db = DatabaseStruct::default(); - db.set_one(0); - - // Invoke `db.panic_safely() without having set `db.one`. `db.one` will - // return 0 and we should catch the panic. - let result = panic::catch_unwind(AssertUnwindSafe({ - let db = db.snapshot(); - move || db.panic_safely() - })); - assert!(result.is_err()); - - // Set `db.one` to 1 and assert ok - db.set_one(1); - let result = panic::catch_unwind(AssertUnwindSafe(|| db.panic_safely())); - assert!(result.is_ok()); - - // Check, that memoized outer is not invalidated by a panic - { - assert_eq!(OUTER_CALLS.load(SeqCst), 0); - db.outer(); - assert_eq!(OUTER_CALLS.load(SeqCst), 1); - - db.set_one(0); - let result = panic::catch_unwind(AssertUnwindSafe(|| db.outer())); - assert!(result.is_err()); - assert_eq!(OUTER_CALLS.load(SeqCst), 1); - - db.set_one(1); - db.outer(); - assert_eq!(OUTER_CALLS.load(SeqCst), 2); - } -} - -#[test] -fn storages_are_unwind_safe() { - fn check_unwind_safe() {} - check_unwind_safe::<&DatabaseStruct>(); -} - -#[test] -fn panics_clear_query_stack() { - let db = DatabaseStruct::default(); - - // Invoke `db.panic_if_not_one() without having set `db.input`. `db.input` - // will default to 0 and we should catch the panic. - let result = panic::catch_unwind(AssertUnwindSafe(|| db.panic_safely())); - assert!(result.is_err()); - - // The database has been poisoned and any attempt to increment the - // revision should panic. - assert_eq!(db.salsa_runtime().active_query(), None); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/cancellation.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/cancellation.rs deleted file mode 100644 index e47a8ef9aa813..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/cancellation.rs +++ /dev/null @@ -1,132 +0,0 @@ -use crate::setup::{CancellationFlag, Knobs, ParDatabase, ParDatabaseImpl, WithValue}; -use ra_salsa::{Cancelled, ParallelDatabase}; - -macro_rules! assert_cancelled { - ($thread:expr) => { - match $thread.join() { - Ok(value) => panic!("expected cancellation, got {:?}", value), - Err(payload) => match payload.downcast::() { - Ok(_) => {} - Err(payload) => ::std::panic::resume_unwind(payload), - }, - } - }; -} - -/// Add test where a call to `sum` is cancelled by a simultaneous -/// write. Check that we recompute the result in next revision, even -/// though none of the inputs have changed. -#[test] -fn in_par_get_set_cancellation_immediate() { - let mut db = ParDatabaseImpl::default(); - - db.set_input('a', 100); - db.set_input('b', 10); - db.set_input('c', 1); - db.set_input('d', 0); - - let thread1 = std::thread::spawn({ - let db = db.snapshot(); - move || { - // This will not return until it sees cancellation is - // signaled. - db.knobs().sum_signal_on_entry.with_value(1, || { - db.knobs() - .sum_wait_for_cancellation - .with_value(CancellationFlag::Panic, || db.sum("abc")) - }) - } - }); - - // Wait until we have entered `sum` in the other thread. - db.wait_for(1); - - // Try to set the input. This will signal cancellation. - db.set_input('d', 1000); - - // This should re-compute the value (even though no input has changed). - let thread2 = std::thread::spawn({ - let db = db.snapshot(); - move || db.sum("abc") - }); - - assert_eq!(db.sum("d"), 1000); - assert_cancelled!(thread1); - assert_eq!(thread2.join().unwrap(), 111); -} - -/// Here, we check that `sum`'s cancellation is propagated -/// to `sum2` properly. -#[test] -fn in_par_get_set_cancellation_transitive() { - let mut db = ParDatabaseImpl::default(); - - db.set_input('a', 100); - db.set_input('b', 10); - db.set_input('c', 1); - db.set_input('d', 0); - - let thread1 = std::thread::spawn({ - let db = db.snapshot(); - move || { - // This will not return until it sees cancellation is - // signaled. - db.knobs().sum_signal_on_entry.with_value(1, || { - db.knobs() - .sum_wait_for_cancellation - .with_value(CancellationFlag::Panic, || db.sum2("abc")) - }) - } - }); - - // Wait until we have entered `sum` in the other thread. - db.wait_for(1); - - // Try to set the input. This will signal cancellation. - db.set_input('d', 1000); - - // This should re-compute the value (even though no input has changed). - let thread2 = std::thread::spawn({ - let db = db.snapshot(); - move || db.sum2("abc") - }); - - assert_eq!(db.sum2("d"), 1000); - assert_cancelled!(thread1); - assert_eq!(thread2.join().unwrap(), 111); -} - -/// https://github.com/ra_salsa-rs/ra_salsa/issues/66 -#[test] -fn no_back_dating_in_cancellation() { - let mut db = ParDatabaseImpl::default(); - - db.set_input('a', 1); - let thread1 = std::thread::spawn({ - let db = db.snapshot(); - move || { - // Here we compute a long-chain of queries, - // but the last one gets cancelled. - db.knobs().sum_signal_on_entry.with_value(1, || { - db.knobs() - .sum_wait_for_cancellation - .with_value(CancellationFlag::Panic, || db.sum3("a")) - }) - } - }); - - db.wait_for(1); - - // Set unrelated input to bump revision - db.set_input('b', 2); - - // Here we should recompuet the whole chain again, clearing the cancellation - // state. If we get `usize::max()` here, it is a bug! - assert_eq!(db.sum3("a"), 1); - - assert_cancelled!(thread1); - - db.set_input('a', 3); - db.set_input('a', 4); - assert_eq!(db.sum3("ab"), 6); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/frozen.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/frozen.rs deleted file mode 100644 index 9e42e26151750..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/frozen.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::setup::{ParDatabase, ParDatabaseImpl}; -use crate::signal::Signal; -use ra_salsa::{Database, ParallelDatabase}; -use std::{ - panic::{catch_unwind, AssertUnwindSafe}, - sync::Arc, -}; - -/// Add test where a call to `sum` is cancelled by a simultaneous -/// write. Check that we recompute the result in next revision, even -/// though none of the inputs have changed. -#[test] -fn in_par_get_set_cancellation() { - let mut db = ParDatabaseImpl::default(); - - db.set_input('a', 1); - - let signal = Arc::new(Signal::default()); - - let thread1 = std::thread::spawn({ - let db = db.snapshot(); - let signal = signal.clone(); - move || { - // Check that cancellation flag is not yet set, because - // `set` cannot have been called yet. - catch_unwind(AssertUnwindSafe(|| db.unwind_if_cancelled())).unwrap(); - - // Signal other thread to proceed. - signal.signal(1); - - // Wait for other thread to signal cancellation - catch_unwind(AssertUnwindSafe(|| loop { - db.unwind_if_cancelled(); - std::thread::yield_now(); - })) - .unwrap_err(); - } - }); - - let thread2 = std::thread::spawn({ - move || { - // Wait until thread 1 has asserted that they are not cancelled - // before we invoke `set.` - signal.wait_for(1); - - // This will block until thread1 drops the revision lock. - db.set_input('a', 2); - - db.input('a') - } - }); - - thread1.join().unwrap(); - - let c = thread2.join().unwrap(); - assert_eq!(c, 2); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/independent.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/independent.rs deleted file mode 100644 index cbbac0608d194..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/independent.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::setup::{ParDatabase, ParDatabaseImpl}; -use ra_salsa::ParallelDatabase; - -/// Test two `sum` queries (on distinct keys) executing in different -/// threads. Really just a test that `snapshot` etc compiles. -#[test] -fn in_par_two_independent_queries() { - let mut db = ParDatabaseImpl::default(); - - db.set_input('a', 100); - db.set_input('b', 10); - db.set_input('c', 1); - db.set_input('d', 200); - db.set_input('e', 20); - db.set_input('f', 2); - - let thread1 = std::thread::spawn({ - let db = db.snapshot(); - move || db.sum("abc") - }); - - let thread2 = std::thread::spawn({ - let db = db.snapshot(); - move || db.sum("def") - }); - - assert_eq!(thread1.join().unwrap(), 111); - assert_eq!(thread2.join().unwrap(), 222); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/main.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/main.rs deleted file mode 100644 index 31c0da1837570..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/main.rs +++ /dev/null @@ -1,13 +0,0 @@ -mod setup; - -mod cancellation; -mod frozen; -mod independent; -mod parallel_cycle_all_recover; -mod parallel_cycle_mid_recover; -mod parallel_cycle_none_recover; -mod parallel_cycle_one_recovers; -mod race; -mod signal; -mod stress; -mod true_parallel; diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_all_recover.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_all_recover.rs deleted file mode 100644 index dabdb3babc00b..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_all_recover.rs +++ /dev/null @@ -1,109 +0,0 @@ -//! Test for cycle recover spread across two threads. -//! See `../cycles.rs` for a complete listing of cycle tests, -//! both intra and cross thread. - -use crate::setup::{Knobs, ParDatabaseImpl}; -use ra_salsa::ParallelDatabase; - -// Recover cycle test: -// -// The pattern is as follows. -// -// Thread A Thread B -// -------- -------- -// a1 b1 -// | wait for stage 1 (blocks) -// signal stage 1 | -// wait for stage 2 (blocks) (unblocked) -// | signal stage 2 -// (unblocked) wait for stage 3 (blocks) -// a2 | -// b1 (blocks -> stage 3) | -// | (unblocked) -// | b2 -// | a1 (cycle detected, recovers) -// | b2 completes, recovers -// | b1 completes, recovers -// a2 sees cycle, recovers -// a1 completes, recovers - -#[test] -fn parallel_cycle_all_recover() { - let db = ParDatabaseImpl::default(); - db.knobs().signal_on_will_block.set(3); - - let thread_a = std::thread::spawn({ - let db = db.snapshot(); - move || db.a1(1) - }); - - let thread_b = std::thread::spawn({ - let db = db.snapshot(); - move || db.b1(1) - }); - - assert_eq!(thread_a.join().unwrap(), 11); - assert_eq!(thread_b.join().unwrap(), 21); -} - -#[ra_salsa::query_group(ParallelCycleAllRecover)] -pub(crate) trait TestDatabase: Knobs { - #[ra_salsa::cycle(recover_a1)] - fn a1(&self, key: i32) -> i32; - - #[ra_salsa::cycle(recover_a2)] - fn a2(&self, key: i32) -> i32; - - #[ra_salsa::cycle(recover_b1)] - fn b1(&self, key: i32) -> i32; - - #[ra_salsa::cycle(recover_b2)] - fn b2(&self, key: i32) -> i32; -} - -fn recover_a1(_db: &dyn TestDatabase, _cycle: &ra_salsa::Cycle, key: &i32) -> i32 { - tracing::debug!("recover_a1"); - key * 10 + 1 -} - -fn recover_a2(_db: &dyn TestDatabase, _cycle: &ra_salsa::Cycle, key: &i32) -> i32 { - tracing::debug!("recover_a2"); - key * 10 + 2 -} - -fn recover_b1(_db: &dyn TestDatabase, _cycle: &ra_salsa::Cycle, key: &i32) -> i32 { - tracing::debug!("recover_b1"); - key * 20 + 1 -} - -fn recover_b2(_db: &dyn TestDatabase, _cycle: &ra_salsa::Cycle, key: &i32) -> i32 { - tracing::debug!("recover_b2"); - key * 20 + 2 -} - -fn a1(db: &dyn TestDatabase, key: i32) -> i32 { - // Wait to create the cycle until both threads have entered - db.signal(1); - db.wait_for(2); - - db.a2(key) -} - -fn a2(db: &dyn TestDatabase, key: i32) -> i32 { - db.b1(key) -} - -fn b1(db: &dyn TestDatabase, key: i32) -> i32 { - // Wait to create the cycle until both threads have entered - db.wait_for(1); - db.signal(2); - - // Wait for thread A to block on this thread - db.wait_for(3); - - db.b2(key) -} - -fn b2(db: &dyn TestDatabase, key: i32) -> i32 { - db.a1(key) -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_mid_recover.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_mid_recover.rs deleted file mode 100644 index 20c508e0b8bf9..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_mid_recover.rs +++ /dev/null @@ -1,109 +0,0 @@ -//! Test for cycle recover spread across two threads. -//! See `../cycles.rs` for a complete listing of cycle tests, -//! both intra and cross thread. - -use crate::setup::{Knobs, ParDatabaseImpl}; -use ra_salsa::ParallelDatabase; - -// Recover cycle test: -// -// The pattern is as follows. -// -// Thread A Thread B -// -------- -------- -// a1 b1 -// | wait for stage 1 (blocks) -// signal stage 1 | -// wait for stage 2 (blocks) (unblocked) -// | | -// | b2 -// | b3 -// | a1 (blocks -> stage 2) -// (unblocked) | -// a2 (cycle detected) | -// b3 recovers -// b2 resumes -// b1 panics because bug - -#[test] -fn parallel_cycle_mid_recovers() { - let db = ParDatabaseImpl::default(); - db.knobs().signal_on_will_block.set(2); - - let thread_a = std::thread::spawn({ - let db = db.snapshot(); - move || db.a1(1) - }); - - let thread_b = std::thread::spawn({ - let db = db.snapshot(); - move || db.b1(1) - }); - - // We expect that the recovery function yields - // `1 * 20 + 2`, which is returned (and forwarded) - // to b1, and from there to a2 and a1. - assert_eq!(thread_a.join().unwrap(), 22); - assert_eq!(thread_b.join().unwrap(), 22); -} - -#[ra_salsa::query_group(ParallelCycleMidRecovers)] -pub(crate) trait TestDatabase: Knobs { - fn a1(&self, key: i32) -> i32; - - fn a2(&self, key: i32) -> i32; - - #[ra_salsa::cycle(recover_b1)] - fn b1(&self, key: i32) -> i32; - - fn b2(&self, key: i32) -> i32; - - #[ra_salsa::cycle(recover_b3)] - fn b3(&self, key: i32) -> i32; -} - -fn recover_b1(_db: &dyn TestDatabase, _cycle: &ra_salsa::Cycle, key: &i32) -> i32 { - tracing::debug!("recover_b1"); - key * 20 + 2 -} - -fn recover_b3(_db: &dyn TestDatabase, _cycle: &ra_salsa::Cycle, key: &i32) -> i32 { - tracing::debug!("recover_b1"); - key * 200 + 2 -} - -fn a1(db: &dyn TestDatabase, key: i32) -> i32 { - // tell thread b we have started - db.signal(1); - - // wait for thread b to block on a1 - db.wait_for(2); - - db.a2(key) -} - -fn a2(db: &dyn TestDatabase, key: i32) -> i32 { - // create the cycle - db.b1(key) -} - -fn b1(db: &dyn TestDatabase, key: i32) -> i32 { - // wait for thread a to have started - db.wait_for(1); - - db.b2(key); - - 0 -} - -fn b2(db: &dyn TestDatabase, key: i32) -> i32 { - // will encounter a cycle but recover - db.b3(key); - db.b1(key); // hasn't recovered yet - 0 -} - -fn b3(db: &dyn TestDatabase, key: i32) -> i32 { - // will block on thread a, signaling stage 2 - db.a1(key) -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_none_recover.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_none_recover.rs deleted file mode 100644 index 88d5fee0a22a4..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_none_recover.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! Test a cycle where no queries recover that occurs across threads. -//! See the `../cycles.rs` for a complete listing of cycle tests, -//! both intra and cross thread. - -use crate::setup::{Knobs, ParDatabaseImpl}; -use expect_test::expect; -use ra_salsa::ParallelDatabase; - -#[test] -fn parallel_cycle_none_recover() { - let db = ParDatabaseImpl::default(); - db.knobs().signal_on_will_block.set(3); - - let thread_a = std::thread::spawn({ - let db = db.snapshot(); - move || db.a(-1) - }); - - let thread_b = std::thread::spawn({ - let db = db.snapshot(); - move || db.b(-1) - }); - - // We expect B to panic because it detects a cycle (it is the one that calls A, ultimately). - // Right now, it panics with a string. - let err_b = thread_b.join().unwrap_err(); - if let Some(c) = err_b.downcast_ref::() { - expect![[r#" - [ - "parallel::parallel_cycle_none_recover::AQuery::a(-1)", - "parallel::parallel_cycle_none_recover::BQuery::b(-1)", - ] - "#]] - .assert_debug_eq(&c.unexpected_participants(&db)); - } else { - panic!("b failed in an unexpected way: {err_b:?}"); - } - - // We expect A to propagate a panic, which causes us to use the sentinel - // type `Canceled`. - assert!(thread_a.join().unwrap_err().downcast_ref::().is_some()); -} - -#[ra_salsa::query_group(ParallelCycleNoneRecover)] -pub(crate) trait TestDatabase: Knobs { - fn a(&self, key: i32) -> i32; - fn b(&self, key: i32) -> i32; -} - -fn a(db: &dyn TestDatabase, key: i32) -> i32 { - // Wait to create the cycle until both threads have entered - db.signal(1); - db.wait_for(2); - - db.b(key) -} - -fn b(db: &dyn TestDatabase, key: i32) -> i32 { - // Wait to create the cycle until both threads have entered - db.wait_for(1); - db.signal(2); - - // Wait for thread A to block on this thread - db.wait_for(3); - - // Now try to execute A - db.a(key) -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_one_recovers.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_one_recovers.rs deleted file mode 100644 index 074ed1bd349de..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/parallel_cycle_one_recovers.rs +++ /dev/null @@ -1,94 +0,0 @@ -//! Test for cycle recover spread across two threads. -//! See `../cycles.rs` for a complete listing of cycle tests, -//! both intra and cross thread. - -use crate::setup::{Knobs, ParDatabaseImpl}; -use ra_salsa::ParallelDatabase; - -// Recover cycle test: -// -// The pattern is as follows. -// -// Thread A Thread B -// -------- -------- -// a1 b1 -// | wait for stage 1 (blocks) -// signal stage 1 | -// wait for stage 2 (blocks) (unblocked) -// | signal stage 2 -// (unblocked) wait for stage 3 (blocks) -// a2 | -// b1 (blocks -> stage 3) | -// | (unblocked) -// | b2 -// | a1 (cycle detected) -// a2 recovery fn executes | -// a1 completes normally | -// b2 completes, recovers -// b1 completes, recovers - -#[test] -fn parallel_cycle_one_recovers() { - let db = ParDatabaseImpl::default(); - db.knobs().signal_on_will_block.set(3); - - let thread_a = std::thread::spawn({ - let db = db.snapshot(); - move || db.a1(1) - }); - - let thread_b = std::thread::spawn({ - let db = db.snapshot(); - move || db.b1(1) - }); - - // We expect that the recovery function yields - // `1 * 20 + 2`, which is returned (and forwarded) - // to b1, and from there to a2 and a1. - assert_eq!(thread_a.join().unwrap(), 22); - assert_eq!(thread_b.join().unwrap(), 22); -} - -#[ra_salsa::query_group(ParallelCycleOneRecovers)] -pub(crate) trait TestDatabase: Knobs { - fn a1(&self, key: i32) -> i32; - - #[ra_salsa::cycle(recover)] - fn a2(&self, key: i32) -> i32; - - fn b1(&self, key: i32) -> i32; - - fn b2(&self, key: i32) -> i32; -} - -fn recover(_db: &dyn TestDatabase, _cycle: &ra_salsa::Cycle, key: &i32) -> i32 { - tracing::debug!("recover"); - key * 20 + 2 -} - -fn a1(db: &dyn TestDatabase, key: i32) -> i32 { - // Wait to create the cycle until both threads have entered - db.signal(1); - db.wait_for(2); - - db.a2(key) -} - -fn a2(db: &dyn TestDatabase, key: i32) -> i32 { - db.b1(key) -} - -fn b1(db: &dyn TestDatabase, key: i32) -> i32 { - // Wait to create the cycle until both threads have entered - db.wait_for(1); - db.signal(2); - - // Wait for thread A to block on this thread - db.wait_for(3); - - db.b2(key) -} - -fn b2(db: &dyn TestDatabase, key: i32) -> i32 { - db.a1(key) -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/race.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/race.rs deleted file mode 100644 index 7aa6d4530b4a7..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/race.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::panic::AssertUnwindSafe; - -use crate::setup::{ParDatabase, ParDatabaseImpl}; -use ra_salsa::{Cancelled, ParallelDatabase}; - -/// Test where a read and a set are racing with one another. -/// Should be atomic. -#[test] -fn in_par_get_set_race() { - let mut db = ParDatabaseImpl::default(); - - db.set_input('a', 100); - db.set_input('b', 10); - db.set_input('c', 1); - - let thread1 = std::thread::spawn({ - let db = db.snapshot(); - move || Cancelled::catch(AssertUnwindSafe(|| db.sum("abc"))) - }); - - let thread2 = std::thread::spawn(move || { - db.set_input('a', 1000); - db.sum("a") - }); - - // If the 1st thread runs first, you get 111, otherwise you get - // 1011; if they run concurrently and the 1st thread observes the - // cancellation, it'll unwind. - let result1 = thread1.join().unwrap(); - if let Ok(value1) = result1 { - assert!(value1 == 111 || value1 == 1011, "illegal result {value1}"); - } - - // thread2 can not observe a cancellation because it performs a - // database write before running any other queries. - assert_eq!(thread2.join().unwrap(), 1000); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/setup.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/setup.rs deleted file mode 100644 index fd1f51326e320..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/setup.rs +++ /dev/null @@ -1,197 +0,0 @@ -use crate::signal::Signal; -use ra_salsa::Database; -use ra_salsa::ParallelDatabase; -use ra_salsa::Snapshot; -use std::sync::Arc; -use std::{ - cell::Cell, - panic::{catch_unwind, resume_unwind, AssertUnwindSafe}, -}; - -#[ra_salsa::query_group(Par)] -pub(crate) trait ParDatabase: Knobs { - #[ra_salsa::input] - fn input(&self, key: char) -> usize; - - fn sum(&self, key: &'static str) -> usize; - - /// Invokes `sum` - fn sum2(&self, key: &'static str) -> usize; - - /// Invokes `sum` but doesn't really care about the result. - fn sum2_drop_sum(&self, key: &'static str) -> usize; - - /// Invokes `sum2` - fn sum3(&self, key: &'static str) -> usize; - - /// Invokes `sum2_drop_sum` - fn sum3_drop_sum(&self, key: &'static str) -> usize; -} - -/// Various "knobs" and utilities used by tests to force -/// a certain behavior. -pub(crate) trait Knobs { - fn knobs(&self) -> &KnobsStruct; - - fn signal(&self, stage: usize); - - fn wait_for(&self, stage: usize); -} - -pub(crate) trait WithValue { - fn with_value(&self, value: T, closure: impl FnOnce() -> R) -> R; -} - -impl WithValue for Cell { - fn with_value(&self, value: T, closure: impl FnOnce() -> R) -> R { - let old_value = self.replace(value); - - let result = catch_unwind(AssertUnwindSafe(closure)); - - self.set(old_value); - - match result { - Ok(r) => r, - Err(payload) => resume_unwind(payload), - } - } -} - -#[derive(Default, Clone, Copy, PartialEq, Eq)] -pub(crate) enum CancellationFlag { - #[default] - Down, - Panic, -} - -/// Various "knobs" that can be used to customize how the queries -/// behave on one specific thread. Note that this state is -/// intentionally thread-local (apart from `signal`). -#[derive(Clone, Default)] -pub(crate) struct KnobsStruct { - /// A kind of flexible barrier used to coordinate execution across - /// threads to ensure we reach various weird states. - pub(crate) signal: Arc, - - /// When this database is about to block, send a signal. - pub(crate) signal_on_will_block: Cell, - - /// Invocations of `sum` will signal this stage on entry. - pub(crate) sum_signal_on_entry: Cell, - - /// Invocations of `sum` will wait for this stage on entry. - pub(crate) sum_wait_for_on_entry: Cell, - - /// If true, invocations of `sum` will panic before they exit. - pub(crate) sum_should_panic: Cell, - - /// If true, invocations of `sum` will wait for cancellation before - /// they exit. - pub(crate) sum_wait_for_cancellation: Cell, - - /// Invocations of `sum` will wait for this stage prior to exiting. - pub(crate) sum_wait_for_on_exit: Cell, - - /// Invocations of `sum` will signal this stage prior to exiting. - pub(crate) sum_signal_on_exit: Cell, - - /// Invocations of `sum3_drop_sum` will panic unconditionally - pub(crate) sum3_drop_sum_should_panic: Cell, -} - -fn sum(db: &dyn ParDatabase, key: &'static str) -> usize { - let mut sum = 0; - - db.signal(db.knobs().sum_signal_on_entry.get()); - - db.wait_for(db.knobs().sum_wait_for_on_entry.get()); - - if db.knobs().sum_should_panic.get() { - panic!("query set to panic before exit") - } - - for ch in key.chars() { - sum += db.input(ch); - } - - match db.knobs().sum_wait_for_cancellation.get() { - CancellationFlag::Down => (), - CancellationFlag::Panic => { - tracing::debug!("waiting for cancellation"); - loop { - db.unwind_if_cancelled(); - std::thread::yield_now(); - } - } - } - - db.wait_for(db.knobs().sum_wait_for_on_exit.get()); - - db.signal(db.knobs().sum_signal_on_exit.get()); - - sum -} - -fn sum2(db: &dyn ParDatabase, key: &'static str) -> usize { - db.sum(key) -} - -fn sum2_drop_sum(db: &dyn ParDatabase, key: &'static str) -> usize { - let _ = db.sum(key); - 22 -} - -fn sum3(db: &dyn ParDatabase, key: &'static str) -> usize { - db.sum2(key) -} - -fn sum3_drop_sum(db: &dyn ParDatabase, key: &'static str) -> usize { - if db.knobs().sum3_drop_sum_should_panic.get() { - panic!("sum3_drop_sum executed") - } - db.sum2_drop_sum(key) -} - -#[ra_salsa::database( - Par, - crate::parallel_cycle_all_recover::ParallelCycleAllRecover, - crate::parallel_cycle_none_recover::ParallelCycleNoneRecover, - crate::parallel_cycle_mid_recover::ParallelCycleMidRecovers, - crate::parallel_cycle_one_recovers::ParallelCycleOneRecovers -)] -#[derive(Default)] -pub(crate) struct ParDatabaseImpl { - storage: ra_salsa::Storage, - knobs: KnobsStruct, -} - -impl Database for ParDatabaseImpl { - fn salsa_event(&self, event: ra_salsa::Event) { - if let ra_salsa::EventKind::WillBlockOn { .. } = event.kind { - self.signal(self.knobs().signal_on_will_block.get()); - } - } -} - -impl ParallelDatabase for ParDatabaseImpl { - fn snapshot(&self) -> Snapshot { - Snapshot::new(ParDatabaseImpl { - storage: self.storage.snapshot(), - knobs: self.knobs.clone(), - }) - } -} - -impl Knobs for ParDatabaseImpl { - fn knobs(&self) -> &KnobsStruct { - &self.knobs - } - - fn signal(&self, stage: usize) { - self.knobs.signal.signal(stage); - } - - fn wait_for(&self, stage: usize) { - self.knobs.signal.wait_for(stage); - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/signal.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/signal.rs deleted file mode 100644 index 0af7b66e4826d..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/signal.rs +++ /dev/null @@ -1,40 +0,0 @@ -use parking_lot::{Condvar, Mutex}; - -#[derive(Default)] -pub(crate) struct Signal { - value: Mutex, - cond_var: Condvar, -} - -impl Signal { - pub(crate) fn signal(&self, stage: usize) { - tracing::debug!("signal({})", stage); - - // This check avoids acquiring the lock for things that will - // clearly be a no-op. Not *necessary* but helps to ensure we - // are more likely to encounter weird race conditions; - // otherwise calls to `sum` will tend to be unnecessarily - // synchronous. - if stage > 0 { - let mut v = self.value.lock(); - if stage > *v { - *v = stage; - self.cond_var.notify_all(); - } - } - } - - /// Waits until the given condition is true; the fn is invoked - /// with the current stage. - pub(crate) fn wait_for(&self, stage: usize) { - tracing::debug!("wait_for({})", stage); - - // As above, avoid lock if clearly a no-op. - if stage > 0 { - let mut v = self.value.lock(); - while *v < stage { - self.cond_var.wait(&mut v); - } - } - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/stress.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/stress.rs deleted file mode 100644 index f3a435b47f147..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/stress.rs +++ /dev/null @@ -1,168 +0,0 @@ -use rand::seq::SliceRandom; -use rand::Rng; - -use ra_salsa::ParallelDatabase; -use ra_salsa::Snapshot; -use ra_salsa::{Cancelled, Database}; - -// Number of operations a reader performs -const N_MUTATOR_OPS: usize = 100; -const N_READER_OPS: usize = 100; - -#[ra_salsa::query_group(Stress)] -trait StressDatabase: ra_salsa::Database { - #[ra_salsa::input] - fn a(&self, key: usize) -> usize; - - fn b(&self, key: usize) -> usize; - - fn c(&self, key: usize) -> usize; -} - -fn b(db: &dyn StressDatabase, key: usize) -> usize { - db.unwind_if_cancelled(); - db.a(key) -} - -fn c(db: &dyn StressDatabase, key: usize) -> usize { - db.b(key) -} - -#[ra_salsa::database(Stress)] -#[derive(Default)] -struct StressDatabaseImpl { - storage: ra_salsa::Storage, -} - -impl ra_salsa::Database for StressDatabaseImpl {} - -impl ra_salsa::ParallelDatabase for StressDatabaseImpl { - fn snapshot(&self) -> Snapshot { - Snapshot::new(StressDatabaseImpl { storage: self.storage.snapshot() }) - } -} - -#[derive(Clone, Copy, Debug)] -enum Query { - A, - B, - C, -} - -enum MutatorOp { - WriteOp(WriteOp), - LaunchReader { ops: Vec, check_cancellation: bool }, -} - -#[derive(Debug)] -enum WriteOp { - SetA(usize, usize), -} - -#[derive(Debug)] -enum ReadOp { - Get(Query, usize), -} - -impl rand::distributions::Distribution for rand::distributions::Standard { - fn sample(&self, rng: &mut R) -> Query { - *[Query::A, Query::B, Query::C].choose(rng).unwrap() - } -} - -impl rand::distributions::Distribution for rand::distributions::Standard { - fn sample(&self, rng: &mut R) -> MutatorOp { - if rng.gen_bool(0.5) { - MutatorOp::WriteOp(rng.gen()) - } else { - MutatorOp::LaunchReader { - ops: (0..N_READER_OPS).map(|_| rng.gen()).collect(), - check_cancellation: rng.gen(), - } - } - } -} - -impl rand::distributions::Distribution for rand::distributions::Standard { - fn sample(&self, rng: &mut R) -> WriteOp { - let key = rng.gen::() % 10; - let value = rng.gen::() % 10; - WriteOp::SetA(key, value) - } -} - -impl rand::distributions::Distribution for rand::distributions::Standard { - fn sample(&self, rng: &mut R) -> ReadOp { - let query = rng.gen::(); - let key = rng.gen::() % 10; - ReadOp::Get(query, key) - } -} - -fn db_reader_thread(db: &StressDatabaseImpl, ops: Vec, check_cancellation: bool) { - for op in ops { - if check_cancellation { - db.unwind_if_cancelled(); - } - op.execute(db); - } -} - -impl WriteOp { - fn execute(self, db: &mut StressDatabaseImpl) { - match self { - WriteOp::SetA(key, value) => { - db.set_a(key, value); - } - } - } -} - -impl ReadOp { - fn execute(self, db: &StressDatabaseImpl) { - match self { - ReadOp::Get(query, key) => match query { - Query::A => { - db.a(key); - } - Query::B => { - let _ = db.b(key); - } - Query::C => { - let _ = db.c(key); - } - }, - } - } -} - -#[test] -fn stress_test() { - let mut db = StressDatabaseImpl::default(); - for i in 0..10 { - db.set_a(i, i); - } - - let mut rng = rand::thread_rng(); - - // generate the ops that the mutator thread will perform - let write_ops: Vec = (0..N_MUTATOR_OPS).map(|_| rng.gen()).collect(); - - // execute the "main thread", which sometimes snapshots off other threads - let mut all_threads = vec![]; - for op in write_ops { - match op { - MutatorOp::WriteOp(w) => w.execute(&mut db), - MutatorOp::LaunchReader { ops, check_cancellation } => { - all_threads.push(std::thread::spawn({ - let db = db.snapshot(); - move || Cancelled::catch(|| db_reader_thread(&db, ops, check_cancellation)) - })) - } - } - } - - for thread in all_threads { - thread.join().unwrap().ok(); - } -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/true_parallel.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/true_parallel.rs deleted file mode 100644 index 44db17bd85253..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/parallel/true_parallel.rs +++ /dev/null @@ -1,125 +0,0 @@ -use crate::setup::{Knobs, ParDatabase, ParDatabaseImpl, WithValue}; -use ra_salsa::ParallelDatabase; -use std::panic::{self, AssertUnwindSafe}; - -/// Test where two threads are executing sum. We show that they can -/// both be executing sum in parallel by having thread1 wait for -/// thread2 to send a signal before it leaves (similarly, thread2 -/// waits for thread1 to send a signal before it enters). -#[test] -fn true_parallel_different_keys() { - let mut db = ParDatabaseImpl::default(); - - db.set_input('a', 100); - db.set_input('b', 10); - db.set_input('c', 1); - - // Thread 1 will signal stage 1 when it enters and wait for stage 2. - let thread1 = std::thread::spawn({ - let db = db.snapshot(); - move || { - let v = db - .knobs() - .sum_signal_on_entry - .with_value(1, || db.knobs().sum_wait_for_on_exit.with_value(2, || db.sum("a"))); - v - } - }); - - // Thread 2 will wait_for stage 1 when it enters and signal stage 2 - // when it leaves. - let thread2 = std::thread::spawn({ - let db = db.snapshot(); - move || { - let v = db - .knobs() - .sum_wait_for_on_entry - .with_value(1, || db.knobs().sum_signal_on_exit.with_value(2, || db.sum("b"))); - v - } - }); - - assert_eq!(thread1.join().unwrap(), 100); - assert_eq!(thread2.join().unwrap(), 10); -} - -/// Add a test that tries to trigger a conflict, where we fetch -/// `sum("abc")` from two threads simultaneously, and of them -/// therefore has to block. -#[test] -fn true_parallel_same_keys() { - let mut db = ParDatabaseImpl::default(); - - db.set_input('a', 100); - db.set_input('b', 10); - db.set_input('c', 1); - - // Thread 1 will wait_for a barrier in the start of `sum` - let thread1 = std::thread::spawn({ - let db = db.snapshot(); - move || { - let v = db - .knobs() - .sum_signal_on_entry - .with_value(1, || db.knobs().sum_wait_for_on_entry.with_value(2, || db.sum("abc"))); - v - } - }); - - // Thread 2 will wait until Thread 1 has entered sum and then -- - // once it has set itself to block -- signal Thread 1 to - // continue. This way, we test out the mechanism of one thread - // blocking on another. - let thread2 = std::thread::spawn({ - let db = db.snapshot(); - move || { - db.knobs().signal.wait_for(1); - db.knobs().signal_on_will_block.set(2); - db.sum("abc") - } - }); - - assert_eq!(thread1.join().unwrap(), 111); - assert_eq!(thread2.join().unwrap(), 111); -} - -/// Add a test that tries to trigger a conflict, where we fetch `sum("a")` -/// from two threads simultaneously. After `thread2` begins blocking, -/// we force `thread1` to panic and should see that propagate to `thread2`. -#[test] -fn true_parallel_propagate_panic() { - let mut db = ParDatabaseImpl::default(); - - db.set_input('a', 1); - - // `thread1` will wait_for a barrier in the start of `sum`. Once it can - // continue, it will panic. - let thread1 = std::thread::spawn({ - let db = db.snapshot(); - move || { - let v = db.knobs().sum_signal_on_entry.with_value(1, || { - db.knobs() - .sum_wait_for_on_entry - .with_value(2, || db.knobs().sum_should_panic.with_value(true, || db.sum("a"))) - }); - v - } - }); - - // `thread2` will wait until `thread1` has entered sum and then -- once it - // has set itself to block -- signal `thread1` to continue. - let thread2 = std::thread::spawn({ - let db = db.snapshot(); - move || { - db.knobs().signal.wait_for(1); - db.knobs().signal_on_will_block.set(2); - db.sum("a") - } - }); - - let result1 = panic::catch_unwind(AssertUnwindSafe(|| thread1.join().unwrap())); - let result2 = panic::catch_unwind(AssertUnwindSafe(|| thread2.join().unwrap())); - - assert!(result1.is_err()); - assert!(result2.is_err()); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/implementation.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/implementation.rs deleted file mode 100644 index 39b2befd15b71..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/implementation.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::queries; -use std::cell::Cell; - -#[ra_salsa::database(queries::GroupStruct)] -#[derive(Default)] -pub(crate) struct DatabaseImpl { - storage: ra_salsa::Storage, - counter: Cell, -} - -impl queries::Counter for DatabaseImpl { - fn increment(&self) -> usize { - let v = self.counter.get(); - self.counter.set(v + 1); - v - } -} - -impl ra_salsa::Database for DatabaseImpl {} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/main.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/main.rs deleted file mode 100644 index e92c61740e0c8..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/main.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod implementation; -mod queries; -mod tests; - -fn main() {} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/queries.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/queries.rs deleted file mode 100644 index bc9b10ae7bb24..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/queries.rs +++ /dev/null @@ -1,22 +0,0 @@ -pub(crate) trait Counter: ra_salsa::Database { - fn increment(&self) -> usize; -} - -#[ra_salsa::query_group(GroupStruct)] -pub(crate) trait Database: Counter { - fn memoized(&self) -> usize; - fn volatile(&self) -> usize; -} - -/// Because this query is memoized, we only increment the counter -/// the first time it is invoked. -fn memoized(db: &dyn Database) -> usize { - db.volatile() -} - -/// Because this query is volatile, each time it is invoked, -/// we will increment the counter. -fn volatile(db: &dyn Database) -> usize { - db.salsa_runtime().report_untracked_read(); - db.increment() -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/tests.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/tests.rs deleted file mode 100644 index 7c33bbfc7475b..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/storage_varieties/tests.rs +++ /dev/null @@ -1,49 +0,0 @@ -#![cfg(test)] - -use crate::implementation::DatabaseImpl; -use crate::queries::Database; -use ra_salsa::Database as _Database; -use ra_salsa::Durability; - -#[test] -fn memoized_twice() { - let db = DatabaseImpl::default(); - let v1 = db.memoized(); - let v2 = db.memoized(); - assert_eq!(v1, v2); -} - -#[test] -fn volatile_twice() { - let mut db = DatabaseImpl::default(); - let v1 = db.volatile(); - let v2 = db.volatile(); // volatiles are cached, so 2nd read returns the same - assert_eq!(v1, v2); - - db.synthetic_write(Durability::LOW); // clears volatile caches - - let v3 = db.volatile(); // will re-increment the counter - let v4 = db.volatile(); // second call will be cached - assert_eq!(v1 + 1, v3); - assert_eq!(v3, v4); -} - -#[test] -fn intermingled() { - let mut db = DatabaseImpl::default(); - let v1 = db.volatile(); - let v2 = db.memoized(); - let v3 = db.volatile(); // cached - let v4 = db.memoized(); // cached - - assert_eq!(v1, v2); - assert_eq!(v1, v3); - assert_eq!(v2, v4); - - db.synthetic_write(Durability::LOW); // clears volatile caches - - let v5 = db.memoized(); // re-executes volatile, caches new result - let v6 = db.memoized(); // re-use cached result - assert_eq!(v4 + 1, v5); - assert_eq!(v5, v6); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/transparent.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/transparent.rs deleted file mode 100644 index 886f46410658b..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/transparent.rs +++ /dev/null @@ -1,39 +0,0 @@ -//! Test that transparent (uncached) queries work - -#[ra_salsa::query_group(QueryGroupStorage)] -trait QueryGroup { - #[ra_salsa::input] - fn input(&self, x: u32) -> u32; - #[ra_salsa::transparent] - fn wrap(&self, x: u32) -> u32; - fn get(&self, x: u32) -> u32; -} - -fn wrap(db: &dyn QueryGroup, x: u32) -> u32 { - db.input(x) -} - -fn get(db: &dyn QueryGroup, x: u32) -> u32 { - db.wrap(x) -} - -#[ra_salsa::database(QueryGroupStorage)] -#[derive(Default)] -struct Database { - storage: ra_salsa::Storage, -} - -impl ra_salsa::Database for Database {} - -#[test] -fn transparent_queries_work() { - let mut db = Database::default(); - - db.set_input(1, 10); - assert_eq!(db.get(1), 10); - assert_eq!(db.get(1), 10); - - db.set_input(1, 92); - assert_eq!(db.get(1), 92); - assert_eq!(db.get(1), 92); -} diff --git a/src/tools/rust-analyzer/crates/ra-salsa/tests/variadic.rs b/src/tools/rust-analyzer/crates/ra-salsa/tests/variadic.rs deleted file mode 100644 index 11a6d13ebe214..0000000000000 --- a/src/tools/rust-analyzer/crates/ra-salsa/tests/variadic.rs +++ /dev/null @@ -1,51 +0,0 @@ -#[ra_salsa::query_group(HelloWorld)] -trait HelloWorldDatabase: ra_salsa::Database { - #[ra_salsa::input] - fn input(&self, a: u32, b: u32) -> u32; - - fn none(&self) -> u32; - - fn one(&self, k: u32) -> u32; - - fn two(&self, a: u32, b: u32) -> u32; - - fn trailing(&self, a: u32, b: u32) -> u32; -} - -fn none(_db: &dyn HelloWorldDatabase) -> u32 { - 22 -} - -fn one(_db: &dyn HelloWorldDatabase, k: u32) -> u32 { - k * 2 -} - -fn two(_db: &dyn HelloWorldDatabase, a: u32, b: u32) -> u32 { - a * b -} - -fn trailing(_db: &dyn HelloWorldDatabase, a: u32, b: u32) -> u32 { - a - b -} - -#[ra_salsa::database(HelloWorld)] -#[derive(Default)] -struct DatabaseStruct { - storage: ra_salsa::Storage, -} - -impl ra_salsa::Database for DatabaseStruct {} - -#[test] -fn execute() { - let mut db = DatabaseStruct::default(); - - // test what happens with inputs: - db.set_input(1, 2, 3); - assert_eq!(db.input(1, 2), 3); - - assert_eq!(db.none(), 22); - assert_eq!(db.one(11), 22); - assert_eq!(db.two(11, 2), 22); - assert_eq!(db.trailing(24, 2), 22); -} diff --git a/src/tools/rust-analyzer/xtask/src/tidy.rs b/src/tools/rust-analyzer/xtask/src/tidy.rs index 0e4208e096738..59427d29992b4 100644 --- a/src/tools/rust-analyzer/xtask/src/tidy.rs +++ b/src/tools/rust-analyzer/xtask/src/tidy.rs @@ -135,7 +135,6 @@ Apache-2.0 OR MIT Apache-2.0 WITH LLVM-exception Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT Apache-2.0/MIT -BSD-2-Clause OR Apache-2.0 OR MIT CC0-1.0 ISC MIT @@ -223,7 +222,7 @@ struct TidyDocs { impl TidyDocs { fn visit(&mut self, path: &Path, text: &str) { // Tests and diagnostic fixes don't need module level comments. - if is_exclude_dir(path, &["tests", "test_data", "fixes", "grammar", "ra-salsa", "stdx"]) { + if is_exclude_dir(path, &["tests", "test_data", "fixes", "grammar", "stdx"]) { return; } From f2d36158bc54f3828d1a7bf1bac99ec2472310c1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 15 Mar 2025 16:07:52 +0100 Subject: [PATCH 0129/2248] chore: Remove legacy `SyntaxContextId` re-export --- .../crates/hir-def/src/expander.rs | 6 +- .../crates/hir-def/src/expr_store.rs | 6 +- .../crates/hir-def/src/hir/format_args.rs | 4 +- .../crates/hir-def/src/item_tree.rs | 4 +- .../crates/hir-def/src/item_tree/lower.rs | 6 +- .../rust-analyzer/crates/hir-def/src/lib.rs | 6 +- .../hir-def/src/nameres/attr_resolution.rs | 4 +- .../crates/hir-def/src/nameres/collector.rs | 6 +- .../crates/hir-def/src/resolver.rs | 6 +- .../crates/hir-def/src/visibility.rs | 6 +- .../crates/hir-expand/src/attrs.rs | 4 +- .../hir-expand/src/builtin/derive_macro.rs | 6 +- .../crates/hir-expand/src/builtin/quote.rs | 4 +- .../rust-analyzer/crates/hir-expand/src/db.rs | 16 ++-- .../crates/hir-expand/src/declarative.rs | 6 +- .../crates/hir-expand/src/eager.rs | 8 +- .../crates/hir-expand/src/files.rs | 16 ++-- .../crates/hir-expand/src/fixup.rs | 4 +- .../crates/hir-expand/src/hygiene.rs | 87 ++++--------------- .../crates/hir-expand/src/lib.rs | 22 ++--- .../crates/hir-expand/src/mod_path.rs | 8 +- .../crates/hir-expand/src/name.rs | 10 +-- .../crates/hir-expand/src/proc_macro.rs | 2 +- .../crates/hir-expand/src/span_map.rs | 4 +- .../rust-analyzer/crates/hir/src/semantics.rs | 10 +-- .../rust-analyzer/crates/ide-db/src/rename.rs | 6 +- .../crates/ide/src/expand_macro.rs | 8 +- src/tools/rust-analyzer/crates/mbe/src/lib.rs | 8 +- .../rust-analyzer/crates/mbe/src/parser.rs | 12 +-- .../rust-analyzer/crates/mbe/src/tests.rs | 8 +- .../proc-macro-api/src/legacy_protocol/msg.rs | 20 ++--- .../src/legacy_protocol/msg/flat.rs | 6 +- .../src/server_impl/rust_analyzer_span.rs | 6 +- .../crates/proc-macro-srv/src/tests/utils.rs | 8 +- .../rust-analyzer/crates/span/src/hygiene.rs | 34 ++++---- .../rust-analyzer/crates/span/src/lib.rs | 5 +- .../rust-analyzer/crates/span/src/map.rs | 4 +- .../crates/syntax-bridge/src/lib.rs | 6 +- 38 files changed, 164 insertions(+), 228 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs index c5ce8c454ce35..343d8aa1c9f10 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs @@ -9,7 +9,7 @@ use hir_expand::{ attrs::RawAttrs, mod_path::ModPath, span_map::SpanMap, ExpandError, ExpandErrorKind, ExpandResult, HirFileId, InFile, Lookup, MacroCallId, }; -use span::{Edition, SyntaxContextId}; +use span::{Edition, SyntaxContext}; use syntax::{ast, Parse}; use triomphe::Arc; @@ -57,9 +57,9 @@ impl Expander { self.module.krate } - pub fn syntax_context(&self) -> SyntaxContextId { + pub fn syntax_context(&self) -> SyntaxContext { // FIXME: - SyntaxContextId::root(Edition::CURRENT) + SyntaxContext::root(Edition::CURRENT) } pub fn enter_expand( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs index 616d2c9fd89a4..7e7ccbfa91a74 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs @@ -37,13 +37,13 @@ pub use self::body::{Body, BodySourceMap}; /// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct HygieneId(span::SyntaxContextId); +pub struct HygieneId(span::SyntaxContext); impl HygieneId { // The edition doesn't matter here, we only use this for comparisons and to lookup the macro. - pub const ROOT: Self = Self(span::SyntaxContextId::root(Edition::Edition2015)); + pub const ROOT: Self = Self(span::SyntaxContext::root(Edition::Edition2015)); - pub fn new(mut ctx: span::SyntaxContextId) -> Self { + pub fn new(mut ctx: span::SyntaxContext) -> Self { // See `Name` for why we're doing that. ctx.remove_root_edition(); Self(ctx) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index 28c824fd31d73..6331861a992e8 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs @@ -4,7 +4,7 @@ use either::Either; use hir_expand::name::Name; use intern::Symbol; use rustc_parse_format as parse; -use span::SyntaxContextId; +use span::SyntaxContext; use stdx::TupleExt; use syntax::{ ast::{self, IsString}, @@ -176,7 +176,7 @@ pub(crate) fn parse( is_direct_literal: bool, mut synth: impl FnMut(Name, Option) -> ExprId, mut record_usage: impl FnMut(Name, Option), - call_ctx: SyntaxContextId, + call_ctx: SyntaxContext, ) -> FormatArgs { let Ok(text) = s.value() else { return FormatArgs { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index d42104faa2e04..b9fc9c9489bad 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -51,7 +51,7 @@ use intern::{Interned, Symbol}; use la_arena::{Arena, Idx, RawIdx}; use rustc_hash::FxHashMap; use smallvec::SmallVec; -use span::{AstIdNode, Edition, FileAstId, SyntaxContextId}; +use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::never; use syntax::{ast, match_ast, SyntaxKind}; use triomphe::Arc; @@ -1098,7 +1098,7 @@ pub struct MacroCall { pub path: Interned, pub ast_id: FileAstId, pub expand_to: ExpandTo, - pub ctxt: SyntaxContextId, + pub ctxt: SyntaxContext, } #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 05b99ae31f423..b0cc7ead8c0dd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -11,7 +11,7 @@ use hir_expand::{ use intern::{sym, Symbol}; use la_arena::Arena; use rustc_hash::FxHashMap; -use span::{AstIdMap, SyntaxContextId}; +use span::{AstIdMap, SyntaxContext}; use stdx::thin_vec::ThinVec; use syntax::{ ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString}, @@ -968,7 +968,7 @@ impl UseTreeLowering<'_> { fn lower_use_tree( &mut self, tree: ast::UseTree, - span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId, + span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext, ) -> Option { if let Some(use_tree_list) = tree.use_tree_list() { let prefix = match tree.path() { @@ -1035,7 +1035,7 @@ impl UseTreeLowering<'_> { pub(crate) fn lower_use_tree( db: &dyn DefDatabase, tree: ast::UseTree, - span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId, + span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext, ) -> Option<(UseTree, Arena)> { let mut lowering = UseTreeLowering { db, mapping: Arena::new() }; let tree = lowering.lower_use_tree(tree, span_for_range)?; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 5f8cd0fde04ab..209ed46b7a85f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -85,7 +85,7 @@ use hir_expand::{ use item_tree::ExternBlock; use la_arena::Idx; use nameres::DefMap; -use span::{AstIdNode, Edition, FileAstId, SyntaxContextId}; +use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::impl_from; use syntax::{ast, AstNode}; @@ -1451,7 +1451,7 @@ impl AstIdWithPath { fn macro_call_as_call_id( db: &dyn ExpandDatabase, call: &AstIdWithPath, - call_site: SyntaxContextId, + call_site: SyntaxContext, expand_to: ExpandTo, krate: Crate, resolver: impl Fn(&path::ModPath) -> Option + Copy, @@ -1473,7 +1473,7 @@ fn macro_call_as_call_id_with_eager( db: &dyn ExpandDatabase, ast_id: AstId, path: &path::ModPath, - call_site: SyntaxContextId, + call_site: SyntaxContext, expand_to: ExpandTo, krate: Crate, resolver: impl FnOnce(&path::ModPath) -> Option, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs index 289b9e2fb7e9f..c35a7fdc96d2a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs @@ -6,7 +6,7 @@ use hir_expand::{ inert_attr_macro::find_builtin_attr_idx, MacroCallId, MacroCallKind, MacroDefId, }; -use span::SyntaxContextId; +use span::SyntaxContext; use syntax::ast; use triomphe::Arc; @@ -137,7 +137,7 @@ pub(super) fn derive_macro_as_call_id( item_attr: &AstIdWithPath, derive_attr_index: AttrId, derive_pos: u32, - call_site: SyntaxContextId, + call_site: SyntaxContext, krate: Crate, resolver: impl Fn(&path::ModPath) -> Option<(MacroId, MacroDefId)>, derive_macro_id: MacroCallId, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 371e99433469f..43b011e57f46a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -20,7 +20,7 @@ use intern::{sym, Interned}; use itertools::{izip, Itertools}; use la_arena::Idx; use rustc_hash::{FxHashMap, FxHashSet}; -use span::{Edition, EditionedFileId, FileAstId, SyntaxContextId}; +use span::{Edition, EditionedFileId, FileAstId, SyntaxContext}; use syntax::ast; use triomphe::Arc; @@ -192,13 +192,13 @@ enum MacroDirectiveKind { FnLike { ast_id: AstIdWithPath, expand_to: ExpandTo, - ctxt: SyntaxContextId, + ctxt: SyntaxContext, }, Derive { ast_id: AstIdWithPath, derive_attr: AttrId, derive_pos: usize, - ctxt: SyntaxContextId, + ctxt: SyntaxContext, /// The "parent" macro it is resolved to. derive_macro_id: MacroCallId, }, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 0ed26ca853e80..997a12a328e10 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -7,7 +7,7 @@ use intern::{sym, Symbol}; use itertools::Itertools as _; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; -use span::SyntaxContextId; +use span::SyntaxContext; use triomphe::Arc; use crate::{ @@ -903,7 +903,7 @@ impl Resolver { fn handle_macro_def_scope( db: &dyn DefDatabase, hygiene_id: &mut HygieneId, - hygiene_info: &mut Option<(SyntaxContextId, MacroDefId)>, + hygiene_info: &mut Option<(SyntaxContext, MacroDefId)>, macro_id: &MacroDefId, ) { if let Some((parent_ctx, label_macro_id)) = hygiene_info { @@ -924,7 +924,7 @@ fn handle_macro_def_scope( fn hygiene_info( db: &dyn DefDatabase, hygiene_id: HygieneId, -) -> Option<(SyntaxContextId, MacroDefId)> { +) -> Option<(SyntaxContext, MacroDefId)> { if !hygiene_id.is_root() { let ctx = hygiene_id.lookup(); ctx.outer_expn(db).map(|expansion| { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs index c4473e454a1bc..86a2d02a9f46e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs @@ -4,7 +4,7 @@ use std::iter; use intern::Interned; use la_arena::ArenaMap; -use span::SyntaxContextId; +use span::SyntaxContext; use syntax::ast; use triomphe::Arc; @@ -37,7 +37,7 @@ impl RawVisibility { pub(crate) fn from_ast( db: &dyn DefDatabase, node: Option, - span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId, + span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext, ) -> RawVisibility { let node = match node { None => return RawVisibility::private(), @@ -49,7 +49,7 @@ impl RawVisibility { fn from_ast_with_span_map( db: &dyn DefDatabase, node: ast::Visibility, - span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId, + span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext, ) -> RawVisibility { let path = match node.kind() { ast::VisibilityKind::In(path) => { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index 64b9b49b3e472..6bfef1d28b720 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -8,7 +8,7 @@ use intern::{sym, Interned, Symbol}; use mbe::{DelimiterKind, Punct}; use smallvec::{smallvec, SmallVec}; -use span::{Span, SyntaxContextId}; +use span::{Span, SyntaxContext}; use syntax::unescape; use syntax::{ast, match_ast, AstNode, AstToken, SyntaxNode}; use syntax_bridge::{desugar_doc_comment_text, syntax_node_to_token_tree, DocCommentDesugarMode}; @@ -210,7 +210,7 @@ pub struct Attr { pub id: AttrId, pub path: Interned, pub input: Option>, - pub ctxt: SyntaxContextId, + pub ctxt: SyntaxContext, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs index 28b6812139446..ff50ccef0f48e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs @@ -4,7 +4,7 @@ use intern::sym; use itertools::{izip, Itertools}; use parser::SyntaxKind; use rustc_hash::FxHashSet; -use span::{Edition, MacroCallId, Span, SyntaxContextId}; +use span::{Edition, MacroCallId, Span, SyntaxContext}; use stdx::never; use syntax_bridge::DocCommentDesugarMode; use tracing::debug; @@ -237,7 +237,7 @@ fn parse_adt( fn parse_adt_from_syntax( adt: &ast::Adt, - tm: &span::SpanMap, + tm: &span::SpanMap, call_site: Span, ) -> Result { let (name, generic_param_list, where_clause, shape) = match &adt { @@ -389,7 +389,7 @@ fn to_adt_syntax( db: &dyn ExpandDatabase, tt: &tt::TopSubtree, call_site: Span, -) -> Result<(ast::Adt, span::SpanMap), ExpandError> { +) -> Result<(ast::Adt, span::SpanMap), ExpandError> { let (parsed, tm) = crate::db::token_tree_to_syntax_node( db, tt, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs index a961df181db23..4c8eb74486bbf 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs @@ -226,7 +226,7 @@ mod tests { use ::tt::IdentIsRaw; use expect_test::expect; use intern::Symbol; - use span::{Edition, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; + use span::{Edition, SpanAnchor, SyntaxContext, ROOT_ERASED_FILE_AST_ID}; use syntax::{TextRange, TextSize}; use super::quote; @@ -240,7 +240,7 @@ mod tests { ), ast_id: ROOT_ERASED_FILE_AST_ID, }, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }; #[test] diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 112327f11e1a8..884d2a0b0b116 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -7,7 +7,7 @@ use rustc_hash::FxHashSet; use salsa::plumbing::AsId; use span::{ AstIdMap, Edition, EditionedFileId, HirFileId, HirFileIdRepr, MacroCallId, MacroFileId, Span, - SyntaxContextId, + SyntaxContext, }; use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T}; use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode}; @@ -96,10 +96,6 @@ pub trait ExpandDatabase: RootQueryDb { #[salsa::transparent] fn lookup_intern_macro_call(&self, macro_call: MacroCallId) -> MacroCallLoc; - #[salsa::transparent] - #[salsa::invoke(crate::hygiene::dump_syntax_contexts)] - fn dump_syntax_contexts(&self) -> String; - /// Lowers syntactic macro call to a token tree representation. That's a firewall /// query, only typing in the macro call itself changes the returned /// subtree. @@ -148,7 +144,7 @@ pub trait ExpandDatabase: RootQueryDb { ) -> Option>>>; #[salsa::transparent] - fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContextId; + fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext; } #[salsa::interned(no_lifetime, id = span::MacroCallId)] @@ -164,14 +160,14 @@ fn lookup_intern_macro_call(db: &dyn ExpandDatabase, macro_call: MacroCallId) -> MacroCallWrapper::ingredient(db).data(db.as_dyn_database(), macro_call.as_id()).0.clone() } -#[salsa::interned(no_lifetime, id = span::SyntaxContextId)] +#[salsa::interned(no_lifetime, id = span::SyntaxContext)] pub struct SyntaxContextWrapper { - pub data: SyntaxContextId, + pub data: SyntaxContext, } -fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId, edition: Edition) -> SyntaxContextId { +fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId, edition: Edition) -> SyntaxContext { match file.repr() { - HirFileIdRepr::FileId(_) => SyntaxContextId::root(edition), + HirFileIdRepr::FileId(_) => SyntaxContext::root(edition), HirFileIdRepr::MacroFile(m) => { let kind = db.lookup_intern_macro_call(m.macro_call_id).kind; db.macro_arg_considering_derives(m.macro_call_id, &kind).2.ctx diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs index fbce320756645..a0b614add4974 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs @@ -2,7 +2,7 @@ use base_db::Crate; use intern::sym; -use span::{Edition, HirFileIdRepr, MacroCallId, Span, SyntaxContextId}; +use span::{Edition, HirFileIdRepr, MacroCallId, Span, SyntaxContext}; use stdx::TupleExt; use syntax::{ast, AstNode}; use syntax_bridge::DocCommentDesugarMode; @@ -100,7 +100,7 @@ impl DeclarativeMacroExpander { _ => None, } }; - let ctx_edition = |ctx: SyntaxContextId| { + let ctx_edition = |ctx: SyntaxContext| { if ctx.is_root() { def_crate.data(db).edition } else { @@ -161,7 +161,7 @@ impl DeclarativeMacroExpander { }; let edition = ctx_edition(match id.file_id.repr() { HirFileIdRepr::MacroFile(macro_file) => macro_file.macro_call_id.lookup(db).ctxt, - HirFileIdRepr::FileId(file) => SyntaxContextId::root(file.edition()), + HirFileIdRepr::FileId(file) => SyntaxContext::root(file.edition()), }); Arc::new(DeclarativeMacroExpander { mac, transparency, edition }) } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs index 02dc75a4a6d87..fcf3929eaab06 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs @@ -19,7 +19,7 @@ //! //! See the full discussion : use base_db::Crate; -use span::SyntaxContextId; +use span::SyntaxContext; use syntax::{ted, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent}; use syntax_bridge::DocCommentDesugarMode; use triomphe::Arc; @@ -38,7 +38,7 @@ pub fn expand_eager_macro_input( macro_call: &ast::MacroCall, ast_id: AstId, def: MacroDefId, - call_site: SyntaxContextId, + call_site: SyntaxContext, resolver: &dyn Fn(&ModPath) -> Option, ) -> ExpandResult> { let expand_to = ExpandTo::from_call_site(macro_call); @@ -116,7 +116,7 @@ fn lazy_expand( macro_call: &ast::MacroCall, ast_id: AstId, krate: Crate, - call_site: SyntaxContextId, + call_site: SyntaxContext, ) -> ExpandResult<(InFile>, Arc)> { let expand_to = ExpandTo::from_call_site(macro_call); let id = def.make_call( @@ -138,7 +138,7 @@ fn eager_macro_recur( mut offset: TextSize, curr: InFile, krate: Crate, - call_site: SyntaxContextId, + call_site: SyntaxContext, macro_resolver: &dyn Fn(&ModPath) -> Option, ) -> ExpandResult> { let original = curr.value.clone_for_update(); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs index 5810d11338cb9..3a26c62e1f200 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs @@ -4,7 +4,7 @@ use std::borrow::Borrow; use either::Either; use span::{ AstIdNode, EditionedFileId, ErasedFileAstId, FileAstId, HirFileId, HirFileIdRepr, MacroFileId, - SyntaxContextId, + SyntaxContext, }; use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextSize}; @@ -311,7 +311,7 @@ impl InFile<&SyntaxNode> { pub fn original_file_range_opt( self, db: &dyn db::ExpandDatabase, - ) -> Option<(FileRange, SyntaxContextId)> { + ) -> Option<(FileRange, SyntaxContext)> { self.borrow().map(SyntaxNode::text_range).original_node_file_range_opt(db) } } @@ -376,7 +376,7 @@ impl InFile { } impl InMacroFile { - pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> (FileRange, SyntaxContextId) { + pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> (FileRange, SyntaxContext) { span_for_offset(db, &db.expansion_span_map(self.file_id), self.value) } } @@ -385,17 +385,17 @@ impl InFile { pub fn original_node_file_range( self, db: &dyn db::ExpandDatabase, - ) -> (FileRange, SyntaxContextId) { + ) -> (FileRange, SyntaxContext) { match self.file_id.repr() { HirFileIdRepr::FileId(file_id) => { - (FileRange { file_id, range: self.value }, SyntaxContextId::root(file_id.edition())) + (FileRange { file_id, range: self.value }, SyntaxContext::root(file_id.edition())) } HirFileIdRepr::MacroFile(mac_file) => { match map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) { Some(it) => it, None => { let loc = db.lookup_intern_macro_call(mac_file.macro_call_id); - (loc.kind.original_call_range(db), SyntaxContextId::root(loc.def.edition)) + (loc.kind.original_call_range(db), SyntaxContext::root(loc.def.edition)) } } } @@ -438,11 +438,11 @@ impl InFile { pub fn original_node_file_range_opt( self, db: &dyn db::ExpandDatabase, - ) -> Option<(FileRange, SyntaxContextId)> { + ) -> Option<(FileRange, SyntaxContext)> { match self.file_id.repr() { HirFileIdRepr::FileId(file_id) => Some(( FileRange { file_id, range: self.value }, - SyntaxContextId::root(file_id.edition()), + SyntaxContext::root(file_id.edition()), )), HirFileIdRepr::MacroFile(mac_file) => { map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs index 28894537d48f7..076dd75cde35f 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs @@ -4,7 +4,7 @@ use intern::sym; use rustc_hash::{FxHashMap, FxHashSet}; use span::{ - ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, FIXUP_ERASED_FILE_AST_ID_MARKER, + ErasedFileAstId, Span, SpanAnchor, SyntaxContext, FIXUP_ERASED_FILE_AST_ID_MARKER, ROOT_ERASED_FILE_AST_ID, }; use stdx::never; @@ -353,7 +353,7 @@ pub(crate) fn reverse_fixups(tt: &mut TopSubtree, undo_info: &SyntaxFixupUndoInf let span = |file_id| Span { range: TextRange::empty(TextSize::new(0)), anchor: SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID }, - ctx: SyntaxContextId::root(span::Edition::Edition2015), + ctx: SyntaxContext::root(span::Edition::Edition2015), }; delimiter.open = span(delimiter.open.anchor.file_id); delimiter.close = span(delimiter.close.anchor.file_id); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs index b53468ccacdca..20694e7d6b80b 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs @@ -24,9 +24,9 @@ use std::{convert::identity, iter}; -use span::{Edition, MacroCallId, Span, SyntaxContextId}; +use span::{Edition, MacroCallId, Span, SyntaxContext}; -use crate::db::{ExpandDatabase, MacroCallWrapper}; +use crate::db::ExpandDatabase; pub use span::Transparency; @@ -65,18 +65,18 @@ fn span_with_ctxt_from_mark( edition: Edition, ) -> Span { Span { - ctx: apply_mark(db, SyntaxContextId::root(edition), expn_id, transparency, edition), + ctx: apply_mark(db, SyntaxContext::root(edition), expn_id, transparency, edition), ..span } } pub(super) fn apply_mark( db: &dyn ExpandDatabase, - ctxt: span::SyntaxContextId, + ctxt: span::SyntaxContext, call_id: span::MacroCallId, transparency: Transparency, edition: Edition, -) -> SyntaxContextId { +) -> SyntaxContext { if transparency == Transparency::Opaque { return apply_mark_internal(db, ctxt, call_id, transparency, edition); } @@ -109,11 +109,11 @@ pub(super) fn apply_mark( fn apply_mark_internal( db: &dyn ExpandDatabase, - ctxt: SyntaxContextId, + ctxt: SyntaxContext, call_id: MacroCallId, transparency: Transparency, edition: Edition, -) -> SyntaxContextId { +) -> SyntaxContext { let call_id = Some(call_id); let mut opaque = ctxt.opaque(db); @@ -121,18 +121,17 @@ fn apply_mark_internal( if transparency >= Transparency::Opaque { let parent = opaque; - opaque = - SyntaxContextId::new(db, call_id, transparency, edition, parent, identity, identity); + opaque = SyntaxContext::new(db, call_id, transparency, edition, parent, identity, identity); } if transparency >= Transparency::SemiTransparent { let parent = opaque_and_semitransparent; opaque_and_semitransparent = - SyntaxContextId::new(db, call_id, transparency, edition, parent, |_| opaque, identity); + SyntaxContext::new(db, call_id, transparency, edition, parent, |_| opaque, identity); } let parent = ctxt; - SyntaxContextId::new( + SyntaxContext::new( db, call_id, transparency, @@ -144,9 +143,9 @@ fn apply_mark_internal( } pub trait SyntaxContextExt { - fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId; - fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId; - fn parent_ctxt(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId; + fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> span::SyntaxContext; + fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> span::SyntaxContext; + fn parent_ctxt(self, db: &dyn ExpandDatabase) -> span::SyntaxContext; fn remove_mark(&mut self, db: &dyn ExpandDatabase) -> (Option, Transparency); fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option, Transparency); @@ -154,14 +153,14 @@ pub trait SyntaxContextExt { fn is_opaque(self, db: &dyn ExpandDatabase) -> bool; } -impl SyntaxContextExt for SyntaxContextId { - fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId { +impl SyntaxContextExt for SyntaxContext { + fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> span::SyntaxContext { self.opaque_and_semitransparent(db) } - fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId { + fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> span::SyntaxContext { self.opaque(db) } - fn parent_ctxt(self, db: &dyn ExpandDatabase) -> span::SyntaxContextId { + fn parent_ctxt(self, db: &dyn ExpandDatabase) -> span::SyntaxContext { self.parent(db) } fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option, Transparency) { @@ -188,7 +187,7 @@ impl SyntaxContextExt for SyntaxContextId { // FIXME: Make this a SyntaxContextExt method once we have RPIT pub fn marks_rev( - ctxt: SyntaxContextId, + ctxt: SyntaxContext, db: &dyn ExpandDatabase, ) -> impl Iterator + '_ { iter::successors(Some(ctxt), move |&mark| Some(mark.parent_ctxt(db))) @@ -200,53 +199,3 @@ pub fn marks_rev( (mark.0.unwrap(), mark.1) }) } - -pub(crate) fn dump_syntax_contexts(db: &dyn ExpandDatabase) -> String { - let mut s = String::from("Expansions:"); - let entries = - MacroCallWrapper::ingredient(db).entries(db.as_dyn_database()).collect::>(); - for loc in entries { - let expn_data = &loc.fields().0; - - s.push_str(&format!( - "parent: {:?}, call_site_ctxt: {:?}, kind: {:?}", - expn_data.kind.file_id(), - expn_data.ctxt, - expn_data.kind.descr(), - )); - } - - s.push_str("\n\nSyntaxContexts:\n"); - let entries = SyntaxContextId::ingredient(db).entries(db.as_dyn_database()).collect::>(); - for e in entries { - struct SyntaxContextDebug<'a>( - &'a dyn ExpandDatabase, - &'a span::SyntaxContextUnderlyingData, - ); - - impl std::fmt::Debug for SyntaxContextDebug<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - fancy_debug(self.1, self.0, f) - } - } - - fn fancy_debug( - this: &span::SyntaxContextUnderlyingData, - db: &dyn ExpandDatabase, - f: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - write!(f, "parent: #{}, outer_mark: (", this.parent)?; - match this.outer_expn { - Some(id) => { - write!(f, "{:?}::{{{{expn{:?}}}}}", db.lookup_intern_macro_call(id).krate, id)? - } - None => write!(f, "root")?, - } - write!(f, ", {:?})", this.outer_transparency) - } - - let dbg = SyntaxContextDebug(db, e.fields()); - stdx::format_to!(s, "{:?}\n", dbg); - } - s -} diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index a1e484c08bcbf..ca5c40c9fac34 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -37,7 +37,7 @@ use base_db::Crate; use either::Either; use span::{ Edition, EditionedFileId, ErasedFileAstId, FileAstId, HirFileIdRepr, Span, SpanAnchor, - SyntaxContextId, + SyntaxContext, }; use syntax::{ ast::{self, AstNode}, @@ -252,7 +252,7 @@ pub struct MacroCallLoc { pub def: MacroDefId, pub krate: Crate, pub kind: MacroCallKind, - pub ctxt: SyntaxContextId, + pub ctxt: SyntaxContext, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -527,7 +527,7 @@ impl MacroDefId { db: &dyn ExpandDatabase, krate: Crate, kind: MacroCallKind, - ctxt: SyntaxContextId, + ctxt: SyntaxContext, ) -> MacroCallId { db.intern_macro_call(MacroCallLoc { def: self, krate, kind, ctxt }) } @@ -683,7 +683,7 @@ impl MacroCallLoc { } impl MacroCallKind { - fn descr(&self) -> &'static str { + pub fn descr(&self) -> &'static str { match self { MacroCallKind::FnLike { .. } => "macro call", MacroCallKind::Derive { .. } => "derive macro", @@ -831,7 +831,7 @@ impl ExpansionInfo { pub fn map_range_down_exact( &self, span: Span, - ) -> Option + '_>> { + ) -> Option + '_>> { let tokens = self.exp_map.ranges_with_span_exact(span).flat_map(move |(range, ctx)| { self.expanded.value.covering_element(range).into_token().zip(Some(ctx)) }); @@ -846,7 +846,7 @@ impl ExpansionInfo { pub fn map_range_down( &self, span: Span, - ) -> Option + '_>> { + ) -> Option + '_>> { let tokens = self.exp_map.ranges_with_span(span).flat_map(move |(range, ctx)| { self.expanded.value.covering_element(range).into_token().zip(Some(ctx)) }); @@ -859,7 +859,7 @@ impl ExpansionInfo { &self, db: &dyn ExpandDatabase, offset: TextSize, - ) -> (FileRange, SyntaxContextId) { + ) -> (FileRange, SyntaxContext) { debug_assert!(self.expanded.value.text_range().contains(offset)); span_for_offset(db, &self.exp_map, offset) } @@ -869,7 +869,7 @@ impl ExpansionInfo { &self, db: &dyn ExpandDatabase, range: TextRange, - ) -> Option<(FileRange, SyntaxContextId)> { + ) -> Option<(FileRange, SyntaxContext)> { debug_assert!(self.expanded.value.text_range().contains_range(range)); map_node_range_up(db, &self.exp_map, range) } @@ -953,7 +953,7 @@ pub fn map_node_range_up( db: &dyn ExpandDatabase, exp_map: &ExpansionSpanMap, range: TextRange, -) -> Option<(FileRange, SyntaxContextId)> { +) -> Option<(FileRange, SyntaxContext)> { let mut spans = exp_map.spans_for_range(range); let Span { range, anchor, ctx } = spans.next()?; let mut start = range.start(); @@ -980,7 +980,7 @@ pub fn map_node_range_up_aggregated( db: &dyn ExpandDatabase, exp_map: &ExpansionSpanMap, range: TextRange, -) -> FxHashMap<(SpanAnchor, SyntaxContextId), TextRange> { +) -> FxHashMap<(SpanAnchor, SyntaxContext), TextRange> { let mut map = FxHashMap::default(); for span in exp_map.spans_for_range(range) { let range = map.entry((span.anchor, span.ctx)).or_insert_with(|| span.range); @@ -1002,7 +1002,7 @@ pub fn span_for_offset( db: &dyn ExpandDatabase, exp_map: &ExpansionSpanMap, offset: TextSize, -) -> (FileRange, SyntaxContextId) { +) -> (FileRange, SyntaxContext) { let span = exp_map.span_at(offset); let anchor_offset = db .ast_id_map(span.anchor.file_id.into()) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs index 40b10cb4380af..5c160240a2ba2 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs @@ -14,7 +14,7 @@ use crate::{ use base_db::Crate; use intern::sym; use smallvec::SmallVec; -use span::{Edition, SyntaxContextId}; +use span::{Edition, SyntaxContext}; use syntax::{ast, AstNode}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -44,7 +44,7 @@ impl ModPath { pub fn from_src( db: &dyn ExpandDatabase, path: ast::Path, - span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId, + span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext, ) -> Option { convert_path(db, path, span_for_range) } @@ -209,7 +209,7 @@ fn display_fmt_path( fn convert_path( db: &dyn ExpandDatabase, path: ast::Path, - span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId, + span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext, ) -> Option { let mut segments = path.segments(); @@ -333,7 +333,7 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: tt::TokenTreesView<'_>) -> Optio Some(ModPath { kind, segments }) } -pub fn resolve_crate_root(db: &dyn ExpandDatabase, mut ctxt: SyntaxContextId) -> Option { +pub fn resolve_crate_root(db: &dyn ExpandDatabase, mut ctxt: SyntaxContext) -> Option { // When resolving `$crate` from a `macro_rules!` invoked in a `macro`, // we don't want to pretend that the `macro_rules!` definition is in the `macro` // as described in `SyntaxContextId::apply_mark`, so we ignore prepended opaque marks. diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index 51721effa355d..79860a002afe7 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -3,7 +3,7 @@ use std::fmt; use intern::{sym, Symbol}; -use span::{Edition, SyntaxContextId}; +use span::{Edition, SyntaxContext}; use syntax::utils::is_raw_identifier; use syntax::{ast, format_smolstr}; @@ -74,7 +74,7 @@ impl Name { Name { symbol: Symbol::intern(text), ctx: () } } - pub fn new(text: &str, mut ctx: SyntaxContextId) -> Name { + pub fn new(text: &str, mut ctx: SyntaxContext) -> Name { // For comparisons etc. we remove the edition, because sometimes we search for some `Name` // and we don't know which edition it came from. // Can't do that for all `SyntaxContextId`s because it breaks Salsa. @@ -88,7 +88,7 @@ impl Name { pub fn new_root(text: &str) -> Name { // The edition doesn't matter for hygiene. - Self::new(text, SyntaxContextId::root(Edition::Edition2015)) + Self::new(text, SyntaxContext::root(Edition::Edition2015)) } pub fn new_tuple_field(idx: usize) -> Name { @@ -122,7 +122,7 @@ impl Name { } } - pub fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self { + pub fn new_symbol(symbol: Symbol, ctx: SyntaxContext) -> Self { debug_assert!(!symbol.as_str().starts_with("r#")); _ = ctx; Self { symbol, ctx: () } @@ -130,7 +130,7 @@ impl Name { // FIXME: This needs to go once we have hygiene pub fn new_symbol_root(sym: Symbol) -> Self { - Self::new_symbol(sym, SyntaxContextId::root(Edition::Edition2015)) + Self::new_symbol(sym, SyntaxContext::root(Edition::Edition2015)) } /// A fake name for things missing in the source code. diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs index cdf63e92a89b5..1330f6af9fd37 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs @@ -154,7 +154,7 @@ impl CrateProcMacros { /// Fetch the [`CustomProcMacroExpander`]s and their corresponding names for the given crate. pub fn list( &self, - def_site_ctx: span::SyntaxContextId, + def_site_ctx: span::SyntaxContext, ) -> Option> { match &self.0 { Ok(proc_macros) => Some( diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs b/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs index ab99cb14f9562..55fe42e271f4d 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs @@ -1,6 +1,6 @@ //! Span maps for real files and macro expansions. -use span::{EditionedFileId, HirFileId, HirFileIdRepr, MacroFileId, Span, SyntaxContextId}; +use span::{EditionedFileId, HirFileId, HirFileIdRepr, MacroFileId, Span, SyntaxContext}; use stdx::TupleExt; use syntax::{ast, AstNode, TextRange}; use triomphe::Arc; @@ -9,7 +9,7 @@ pub use span::RealSpanMap; use crate::{attrs::collect_attrs, db::ExpandDatabase}; -pub type ExpansionSpanMap = span::SpanMap; +pub type ExpansionSpanMap = span::SpanMap; /// Spanmap for a macro file or a real file #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 15cd69f320d33..b971b2e9f1a38 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -36,7 +36,7 @@ use intern::{sym, Symbol}; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; use smallvec::{smallvec, SmallVec}; -use span::{AstIdMap, EditionedFileId, FileId, HirFileIdRepr, SyntaxContextId}; +use span::{AstIdMap, EditionedFileId, FileId, HirFileIdRepr, SyntaxContext}; use stdx::TupleExt; use syntax::{ algo::skip_trivia_token, @@ -877,7 +877,7 @@ impl<'db> SemanticsImpl<'db> { pub fn descend_into_macros_cb( &self, token: SyntaxToken, - mut cb: impl FnMut(InFile, SyntaxContextId), + mut cb: impl FnMut(InFile, SyntaxContext), ) { if let Ok(token) = self.wrap_token_infile(token).into_real_file() { self.descend_into_macros_impl(token, &mut |t, ctx| { @@ -921,7 +921,7 @@ impl<'db> SemanticsImpl<'db> { pub fn descend_into_macros_breakable( &self, token: InRealFile, - mut cb: impl FnMut(InFile, SyntaxContextId) -> ControlFlow, + mut cb: impl FnMut(InFile, SyntaxContext) -> ControlFlow, ) -> Option { self.descend_into_macros_impl(token.clone(), &mut cb) } @@ -979,7 +979,7 @@ impl<'db> SemanticsImpl<'db> { fn descend_into_macros_impl( &self, InRealFile { value: token, file_id }: InRealFile, - f: &mut dyn FnMut(InFile, SyntaxContextId) -> ControlFlow, + f: &mut dyn FnMut(InFile, SyntaxContext) -> ControlFlow, ) -> Option { let _p = tracing::info_span!("descend_into_macros_impl").entered(); @@ -1016,7 +1016,7 @@ impl<'db> SemanticsImpl<'db> { None => { stack.push(( file_id.into(), - smallvec![(token, SyntaxContextId::root(file_id.edition()))], + smallvec![(token, SyntaxContext::root(file_id.edition()))], )); } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs index a7584f67f118c..902ead977e582 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs @@ -29,7 +29,7 @@ use crate::{ use base_db::AnchoredPathBuf; use either::Either; use hir::{FieldSource, FileRange, HirFileIdExt, InFile, ModuleSource, Semantics}; -use span::{Edition, EditionedFileId, FileId, SyntaxContextId}; +use span::{Edition, EditionedFileId, FileId, SyntaxContext}; use stdx::{never, TupleExt}; use syntax::{ ast::{self, HasName}, @@ -113,7 +113,7 @@ impl Definition { /// renamed and extern crate names will report its range, though a rename will introduce /// an alias instead. pub fn range_for_rename(self, sema: &Semantics<'_, RootDatabase>) -> Option { - let syn_ctx_is_root = |(range, ctx): (_, SyntaxContextId)| ctx.is_root().then_some(range); + let syn_ctx_is_root = |(range, ctx): (_, SyntaxContext)| ctx.is_root().then_some(range); let res = match self { Definition::Macro(mac) => { let src = sema.source(mac)?; @@ -220,7 +220,7 @@ impl Definition { fn name_range( def: D, sema: &Semantics<'_, RootDatabase>, - ) -> Option<(FileRange, SyntaxContextId)> + ) -> Option<(FileRange, SyntaxContext)> where D: hir::HasSource, D::Ast: ast::HasName, diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index 3771efc17b69d..a18eb9049ff67 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -4,7 +4,7 @@ use ide_db::{ base_db::Crate, helpers::pick_best_token, syntax_helpers::prettify_macro_expansion, FileId, RootDatabase, }; -use span::{Edition, SpanMap, SyntaxContextId, TextRange, TextSize}; +use span::{Edition, SpanMap, SyntaxContext, TextRange, TextSize}; use stdx::format_to; use syntax::{ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T}; @@ -142,7 +142,7 @@ fn expand_macro_recur( sema: &Semantics<'_, RootDatabase>, macro_call: &ast::Item, error: &mut String, - result_span_map: &mut SpanMap, + result_span_map: &mut SpanMap, offset_in_original_node: TextSize, ) -> Option { let ExpandResult { value: expanded, err } = match macro_call { @@ -170,7 +170,7 @@ fn expand( sema: &Semantics<'_, RootDatabase>, expanded: SyntaxNode, error: &mut String, - result_span_map: &mut SpanMap, + result_span_map: &mut SpanMap, mut offset_in_original_node: i32, ) -> SyntaxNode { let children = expanded.descendants().filter_map(ast::Item::cast); @@ -207,7 +207,7 @@ fn format( kind: SyntaxKind, file_id: FileId, expanded: SyntaxNode, - span_map: &SpanMap, + span_map: &SpanMap, krate: Crate, ) -> String { let expansion = prettify_macro_expansion(db, expanded, span_map, krate).to_string(); diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs index bebd29ef74700..6bc019bf333e9 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs @@ -21,7 +21,7 @@ mod benchmark; #[cfg(test)] mod tests; -use span::{Edition, Span, SyntaxContextId}; +use span::{Edition, Span, SyntaxContext}; use syntax_bridge::to_parser_input; use tt::iter::TtIter; use tt::DelimSpan; @@ -149,7 +149,7 @@ impl DeclarativeMacro { /// The old, `macro_rules! m {}` flavor. pub fn parse_macro_rules( tt: &tt::TopSubtree, - ctx_edition: impl Copy + Fn(SyntaxContextId) -> Edition, + ctx_edition: impl Copy + Fn(SyntaxContext) -> Edition, ) -> DeclarativeMacro { // Note: this parsing can be implemented using mbe machinery itself, by // matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing @@ -189,7 +189,7 @@ impl DeclarativeMacro { pub fn parse_macro2( args: Option<&tt::TopSubtree>, body: &tt::TopSubtree, - ctx_edition: impl Copy + Fn(SyntaxContextId) -> Edition, + ctx_edition: impl Copy + Fn(SyntaxContext) -> Edition, ) -> DeclarativeMacro { let mut rules = Vec::new(); let mut err = None; @@ -262,7 +262,7 @@ impl DeclarativeMacro { impl Rule { fn parse( - edition: impl Copy + Fn(SyntaxContextId) -> Edition, + edition: impl Copy + Fn(SyntaxContext) -> Edition, src: &mut TtIter<'_, Span>, ) -> Result { let (_, lhs) = diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs index 0a670053c9882..9d91387a07417 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use arrayvec::ArrayVec; use intern::{sym, Symbol}; -use span::{Edition, Span, SyntaxContextId}; +use span::{Edition, Span, SyntaxContext}; use tt::iter::{TtElement, TtIter}; use crate::ParseError; @@ -28,14 +28,14 @@ pub(crate) struct MetaTemplate(pub(crate) Box<[Op]>); impl MetaTemplate { pub(crate) fn parse_pattern( - edition: impl Copy + Fn(SyntaxContextId) -> Edition, + edition: impl Copy + Fn(SyntaxContext) -> Edition, pattern: TtIter<'_, Span>, ) -> Result { MetaTemplate::parse(edition, pattern, Mode::Pattern) } pub(crate) fn parse_template( - edition: impl Copy + Fn(SyntaxContextId) -> Edition, + edition: impl Copy + Fn(SyntaxContext) -> Edition, template: TtIter<'_, Span>, ) -> Result { MetaTemplate::parse(edition, template, Mode::Template) @@ -46,7 +46,7 @@ impl MetaTemplate { } fn parse( - edition: impl Copy + Fn(SyntaxContextId) -> Edition, + edition: impl Copy + Fn(SyntaxContext) -> Edition, mut src: TtIter<'_, Span>, mode: Mode, ) -> Result { @@ -179,7 +179,7 @@ enum Mode { } fn next_op( - edition: impl Copy + Fn(SyntaxContextId) -> Edition, + edition: impl Copy + Fn(SyntaxContext) -> Edition, first_peeked: TtElement<'_, Span>, src: &mut TtIter<'_, Span>, mode: Mode, @@ -287,7 +287,7 @@ fn next_op( } fn eat_fragment_kind( - edition: impl Copy + Fn(SyntaxContextId) -> Edition, + edition: impl Copy + Fn(SyntaxContext) -> Edition, src: &mut TtIter<'_, Span>, mode: Mode, ) -> Result, ParseError> { diff --git a/src/tools/rust-analyzer/crates/mbe/src/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/tests.rs index 462c206bebfa7..7d9538a4b4dd6 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/tests.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/tests.rs @@ -3,7 +3,7 @@ // FIXME: Move more of the nameres independent tests from // crates\hir-def\src\macro_expansion_tests\mod.rs to this use expect_test::expect; -use span::{Edition, EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContextId}; +use span::{Edition, EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContext}; use stdx::format_to; use tt::{TextRange, TextSize}; @@ -26,7 +26,7 @@ fn check_( file_id: EditionedFileId::new(FileId::from_raw(0), def_edition), ast_id: ErasedFileAstId::from_raw(0), }, - SyntaxContextId::root(Edition::CURRENT), + SyntaxContext::root(Edition::CURRENT), decl, ) .unwrap(); @@ -42,7 +42,7 @@ fn check_( let arg_tt = syntax_bridge::parse_to_token_tree( call_edition, call_anchor, - SyntaxContextId::root(Edition::CURRENT), + SyntaxContext::root(Edition::CURRENT), arg, ) .unwrap(); @@ -52,7 +52,7 @@ fn check_( Span { range: TextRange::up_to(TextSize::of(arg)), anchor: call_anchor, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }, def_edition, ); diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs index 4b831e4acebb9..4178b04767a99 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -159,7 +159,7 @@ type ProtocolWrite = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str) #[cfg(test)] mod tests { use intern::{sym, Symbol}; - use span::{Edition, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TextSize}; + use span::{Edition, ErasedFileAstId, Span, SpanAnchor, SyntaxContext, TextRange, TextSize}; use tt::{ Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, TopSubtree, TopSubtreeBuilder, @@ -180,12 +180,12 @@ mod tests { open: Span { range: TextRange::empty(TextSize::new(0)), anchor, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }, close: Span { range: TextRange::empty(TextSize::new(19)), anchor, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }, kind: DelimiterKind::Invisible, }); @@ -196,7 +196,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(0), TextSize::of("struct")), anchor, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }, is_raw: tt::IdentIsRaw::No, } @@ -208,7 +208,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(5), TextSize::of("r#Foo")), anchor, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }, is_raw: tt::IdentIsRaw::Yes, } @@ -219,7 +219,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(10), TextSize::of("\"Foo\"")), anchor, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }, kind: tt::LitKind::Str, suffix: None, @@ -229,7 +229,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(13), TextSize::of('@')), anchor, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }, spacing: Spacing::Joint, })); @@ -238,7 +238,7 @@ mod tests { Span { range: TextRange::at(TextSize::new(14), TextSize::of('{')), anchor, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }, ); builder.push(Leaf::Literal(Literal { @@ -246,7 +246,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(15), TextSize::of("0u32")), anchor, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }, kind: tt::LitKind::Integer, suffix: Some(sym::u32.clone()), @@ -254,7 +254,7 @@ mod tests { builder.close(Span { range: TextRange::at(TextSize::new(19), TextSize::of('}')), anchor, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }); builder.build() diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs index c194f301714fc..101c4b3105ad0 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs @@ -40,9 +40,7 @@ use std::collections::VecDeque; use intern::Symbol; use rustc_hash::FxHashMap; use serde_derive::{Deserialize, Serialize}; -use span::{ - EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TokenId, -}; +use span::{EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SyntaxContext, TextRange, TokenId}; use crate::legacy_protocol::msg::{ENCODE_CLOSE_SPAN_VERSION, EXTENDED_LEAF_DATA}; @@ -74,7 +72,7 @@ pub fn deserialize_span_data_index_map(map: &[u32]) -> SpanDataIndexMap { ast_id: ErasedFileAstId::from_raw(ast_id), }, range: TextRange::new(start.into(), end.into()), - ctx: SyntaxContextId::from_u32(e), + ctx: SyntaxContext::from_u32(e), } }) .collect() diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index 59293ee3f9659..f7cb0ab4655fa 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -428,7 +428,7 @@ impl server::Server for RaSpanServer { #[cfg(test)] mod tests { - use span::{EditionedFileId, FileId, SyntaxContextId}; + use span::{EditionedFileId, FileId, SyntaxContext}; use super::*; @@ -440,7 +440,7 @@ mod tests { file_id: EditionedFileId::current_edition(FileId::from_raw(0)), ast_id: span::ErasedFileAstId::from_raw(0), }, - ctx: SyntaxContextId::root(span::Edition::CURRENT), + ctx: SyntaxContext::root(span::Edition::CURRENT), }; let s = TokenStream { token_trees: vec![ @@ -482,7 +482,7 @@ mod tests { file_id: EditionedFileId::current_edition(FileId::from_raw(0)), ast_id: span::ErasedFileAstId::from_raw(0), }, - ctx: SyntaxContextId::root(span::Edition::CURRENT), + ctx: SyntaxContext::root(span::Edition::CURRENT), }; let subtree_paren_a = vec![ tt::TokenTree::Subtree(tt::Subtree { diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs index 1b085520d5656..584a27468f847 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs @@ -1,7 +1,7 @@ //! utils used in proc-macro tests use expect_test::Expect; -use span::{EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContextId, TokenId}; +use span::{EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContext, TokenId}; use tt::TextRange; use crate::{dylib, proc_macro_test_dylib_path, EnvSnapshot, ProcMacroSrv}; @@ -17,7 +17,7 @@ fn parse_string(call_site: TokenId, src: &str) -> crate::server_impl::TokenStrea fn parse_string_spanned( anchor: SpanAnchor, - call_site: SyntaxContextId, + call_site: SyntaxContext, src: &str, ) -> crate::server_impl::TokenStream { crate::server_impl::TokenStream::with_subtree(crate::server_impl::TopSubtree( @@ -81,7 +81,7 @@ fn assert_expand_impl( file_id: EditionedFileId::current_edition(FileId::from_raw(41)), ast_id: ErasedFileAstId::from_raw(1), }, - ctx: SyntaxContextId::root(span::Edition::CURRENT), + ctx: SyntaxContext::root(span::Edition::CURRENT), }; let call_site = Span { range: TextRange::new(0.into(), 100.into()), @@ -89,7 +89,7 @@ fn assert_expand_impl( file_id: EditionedFileId::current_edition(FileId::from_raw(42)), ast_id: ErasedFileAstId::from_raw(2), }, - ctx: SyntaxContextId::root(span::Edition::CURRENT), + ctx: SyntaxContext::root(span::Edition::CURRENT), }; let mixed_site = call_site; diff --git a/src/tools/rust-analyzer/crates/span/src/hygiene.rs b/src/tools/rust-analyzer/crates/span/src/hygiene.rs index a6402e870150e..7cb1676a29de8 100644 --- a/src/tools/rust-analyzer/crates/span/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/span/src/hygiene.rs @@ -23,9 +23,6 @@ use std::fmt; use crate::{Edition, MacroCallId}; -// Recursive expansion of interned macro -// ====================================== - /// A syntax context describes a hierarchy tracking order of macro definitions. #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] pub struct SyntaxContext( @@ -33,22 +30,21 @@ pub struct SyntaxContext( std::marker::PhantomData<&'static salsa::plumbing::interned::Value>, ); -/// The underlying data interned by Salsa. -#[derive(Clone, Eq, Debug)] -pub struct SyntaxContextUnderlyingData { - pub outer_expn: Option, - pub outer_transparency: Transparency, - pub edition: Edition, - pub parent: SyntaxContext, - pub opaque: SyntaxContext, - pub opaque_and_semitransparent: SyntaxContext, -} - const _: () = { use salsa::plumbing as zalsa_; use salsa::plumbing::interned as zalsa_struct_; - impl PartialEq for SyntaxContextUnderlyingData { + #[derive(Clone, Eq, Debug)] + pub struct SyntaxContextData { + outer_expn: Option, + outer_transparency: Transparency, + edition: Edition, + parent: SyntaxContext, + opaque: SyntaxContext, + opaque_and_semitransparent: SyntaxContext, + } + + impl PartialEq for SyntaxContextData { fn eq(&self, other: &Self) -> bool { self.outer_expn == other.outer_expn && self.outer_transparency == other.outer_transparency @@ -57,7 +53,7 @@ const _: () = { } } - impl std::hash::Hash for SyntaxContextUnderlyingData { + impl std::hash::Hash for SyntaxContextData { fn hash(&self, state: &mut H) { self.outer_expn.hash(state); self.outer_transparency.hash(state); @@ -71,7 +67,7 @@ const _: () = { struct StructKey<'db, T0, T1, T2, T3>(T0, T1, T2, T3, std::marker::PhantomData<&'db ()>); impl<'db, T0, T1, T2, T3> zalsa_::interned::HashEqLike> - for SyntaxContextUnderlyingData + for SyntaxContextData where Option: zalsa_::interned::HashEqLike, Transparency: zalsa_::interned::HashEqLike, @@ -93,7 +89,7 @@ const _: () = { } impl zalsa_struct_::Configuration for SyntaxContext { const DEBUG_NAME: &'static str = "SyntaxContextData"; - type Fields<'a> = SyntaxContextUnderlyingData; + type Fields<'a> = SyntaxContextData; type Struct<'a> = SyntaxContext; fn struct_from_id<'db>(id: salsa::Id) -> Self::Struct<'db> { SyntaxContext(id, std::marker::PhantomData) @@ -189,7 +185,7 @@ const _: () = { parent, std::marker::PhantomData, ), - |id, data| SyntaxContextUnderlyingData { + |id, data| SyntaxContextData { outer_expn: zalsa_::interned::Lookup::into_owned(data.0), outer_transparency: zalsa_::interned::Lookup::into_owned(data.1), edition: zalsa_::interned::Lookup::into_owned(data.2), diff --git a/src/tools/rust-analyzer/crates/span/src/lib.rs b/src/tools/rust-analyzer/crates/span/src/lib.rs index 7abdacee2b970..fbd1b25cffcaf 100644 --- a/src/tools/rust-analyzer/crates/span/src/lib.rs +++ b/src/tools/rust-analyzer/crates/span/src/lib.rs @@ -11,9 +11,6 @@ pub use self::{ map::{RealSpanMap, SpanMap}, }; -// Remove this -pub use self::hygiene::{SyntaxContext as SyntaxContextId, SyntaxContextUnderlyingData}; - pub use syntax::Edition; pub use text_size::{TextRange, TextSize}; pub use vfs::FileId; @@ -31,7 +28,7 @@ pub const FIXUP_ERASED_FILE_AST_ID_MARKER: ErasedFileAstId = // is required to be stable for the proc-macro-server ErasedFileAstId::from_raw(!0 - 1); -pub type Span = SpanData; +pub type Span = SpanData; impl Span { pub fn cover(self, other: Span) -> Span { diff --git a/src/tools/rust-analyzer/crates/span/src/map.rs b/src/tools/rust-analyzer/crates/span/src/map.rs index dc35de67fd8db..9eb22d6e0b931 100644 --- a/src/tools/rust-analyzer/crates/span/src/map.rs +++ b/src/tools/rust-analyzer/crates/span/src/map.rs @@ -6,7 +6,7 @@ use std::{fmt, hash::Hash}; use stdx::{always, itertools::Itertools}; use crate::{ - EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SpanData, SyntaxContextId, TextRange, + EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SpanData, SyntaxContext, TextRange, TextSize, ROOT_ERASED_FILE_AST_ID, }; @@ -208,7 +208,7 @@ impl RealSpanMap { Span { range: range - offset, anchor: SpanAnchor { file_id: self.file_id, ast_id }, - ctx: SyntaxContextId::root(self.file_id.edition()), + ctx: SyntaxContext::root(self.file_id.edition()), } } } diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs index a59a3270c9d9d..2dde236f0d279 100644 --- a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs @@ -45,7 +45,7 @@ impl> SpanMapper for &SM { /// Dummy things for testing where spans don't matter. pub mod dummy_test_span_utils { - use span::{Span, SyntaxContextId}; + use span::{Span, SyntaxContext}; use super::*; @@ -58,7 +58,7 @@ pub mod dummy_test_span_utils { ), ast_id: span::ROOT_ERASED_FILE_AST_ID, }, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), }; pub struct DummyTestSpanMap; @@ -74,7 +74,7 @@ pub mod dummy_test_span_utils { ), ast_id: span::ROOT_ERASED_FILE_AST_ID, }, - ctx: SyntaxContextId::root(Edition::CURRENT), + ctx: SyntaxContext::root(Edition::CURRENT), } } } From 17351bd503b87758f52f9f3d8648fdee95cceacf Mon Sep 17 00:00:00 2001 From: blyxyas Date: Sun, 16 Feb 2025 21:50:58 +0100 Subject: [PATCH 0130/2248] Change frequency to 3000 --- lintcheck/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs index ab86f6ad6f917..c8b4a2c9e2073 100644 --- a/lintcheck/src/main.rs +++ b/lintcheck/src/main.rs @@ -128,6 +128,7 @@ impl Crate { "-g", // Enable call-graph, useful for flamegraphs and produces richer reports "--quiet", // Do not tamper with lintcheck's normal output "--compression-level=22", + "--freq=3000", // Slow down program to capture all events "-o", &perf_data_filename, "--", From 3bec5066bc1575a4ca0964439bb3874a037e65bc Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 15 Mar 2025 21:27:18 +0200 Subject: [PATCH 0131/2248] Do not error for actions with no data to resolve Same as the other resolve code handlers in the same file. https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#version_3_17_0 does not forbid resolving with no data, so instead of erroring, just consider such items resolved already. --- .../rust-analyzer/crates/rust-analyzer/src/handlers/request.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 170481ea70164..5f27567c31ed7 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -1480,7 +1480,7 @@ pub(crate) fn handle_code_action_resolve( ) -> anyhow::Result { let _p = tracing::info_span!("handle_code_action_resolve").entered(); let Some(params) = code_action.data.take() else { - return Err(invalid_params_error("code action without data".to_owned()).into()); + return Ok(code_action); }; let file_id = from_proto::file_id(&snap, ¶ms.code_action_params.text_document.uri)? From c6033c831dfac958d2365501d164a390b511de8c Mon Sep 17 00:00:00 2001 From: Neil Date: Sat, 15 Mar 2025 12:31:56 -0700 Subject: [PATCH 0132/2248] refactor: Simplify by removing ? operator `out.flush()` already returns a `io::Result<()>`, so there is no need for `?` operator and `Ok(())` --- .../crates/proc-macro-api/src/legacy_protocol/json.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/json.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/json.rs index ec89f6a9e65d2..30e35f8f14343 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/json.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/json.rs @@ -30,6 +30,5 @@ pub fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> { tracing::debug!("> {}", msg); out.write_all(msg.as_bytes())?; out.write_all(b"\n")?; - out.flush()?; - Ok(()) + out.flush() } From b12d934cede0092b26d642f8fdcca80a44d6c563 Mon Sep 17 00:00:00 2001 From: BenjaminBrienen Date: Mon, 10 Mar 2025 12:37:43 +0100 Subject: [PATCH 0133/2248] Fix 2024 syntax errors --- .../hir-expand/src/builtin/derive_macro.rs | 26 +++++++++---------- .../crates/hir-expand/src/builtin/fn_macro.rs | 4 +-- .../crates/hir-expand/src/builtin/quote.rs | 2 +- .../crates/hir-ty/src/mir/lower.rs | 4 +-- src/tools/rust-analyzer/crates/hir/src/lib.rs | 7 +++-- .../rust-analyzer/crates/hir/src/semantics.rs | 2 +- .../crates/ide-diagnostics/src/lib.rs | 3 ++- .../crates/ide/src/inlay_hints/lifetime.rs | 4 +-- .../crates/rust-analyzer/src/bin/main.rs | 6 +++-- .../rust-analyzer/tests/slow-tests/support.rs | 3 ++- .../crates/syntax/src/ast/node_ext.rs | 2 +- 11 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs index ff50ccef0f48e..149ab73ec5477 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs @@ -117,7 +117,7 @@ impl VariantShape { quote! {span => #it : #mapped , } }); quote! {span => - #path { ##fields } + #path { # #fields } } } &VariantShape::Tuple(n) => { @@ -128,7 +128,7 @@ impl VariantShape { } }); quote! {span => - #path ( ##fields ) + #path ( # #fields ) } } VariantShape::Unit => path, @@ -523,7 +523,7 @@ fn expand_simple_derive_with_parsed( let name = info.name; quote! {invoc_span => - impl < ##params #extra_impl_params > #trait_path for #name < ##args > where ##where_block { #trait_body } + impl < # #params #extra_impl_params > #trait_path for #name < # #args > where # #where_block { #trait_body } } } @@ -572,7 +572,7 @@ fn clone_expand( quote! {span => fn clone(&self) -> Self { match self { - ##arms + # #arms } } } @@ -650,7 +650,7 @@ fn debug_expand( } }); quote! {span => - f.debug_struct(#name) ##for_fields .finish() + f.debug_struct(#name) # #for_fields .finish() } } VariantShape::Tuple(n) => { @@ -660,7 +660,7 @@ fn debug_expand( } }); quote! {span => - f.debug_tuple(#name) ##for_fields .finish() + f.debug_tuple(#name) # #for_fields .finish() } } VariantShape::Unit => quote! {span => @@ -703,7 +703,7 @@ fn debug_expand( quote! {span => fn fmt(&self, f: &mut #krate::fmt::Formatter) -> #krate::fmt::Result { match self { - ##arms + # #arms } } } @@ -736,7 +736,7 @@ fn hash_expand( let it = names.iter().map(|it| quote! {span => #it . hash(ra_expand_state); }); quote! {span => { - ##it + # #it } } }; let fat_arrow = fat_arrow(span); @@ -754,7 +754,7 @@ fn hash_expand( fn hash(&self, ra_expand_state: &mut H) { #check_discriminant match self { - ##arms + # #arms } } } @@ -803,7 +803,7 @@ fn partial_eq_expand( let t2 = tt::Ident::new(&format!("{}_other", first.sym), first.span); quote!(span =>#t1 .eq( #t2 )) }; - quote!(span =>#first ##rest) + quote!(span =>#first # #rest) } }; quote! {span => ( #pat1 , #pat2 ) #fat_arrow #body , } @@ -814,7 +814,7 @@ fn partial_eq_expand( quote! {span => fn eq(&self, other: &Self) -> bool { match (self, other) { - ##arms + # #arms _unused #fat_arrow false } } @@ -891,7 +891,7 @@ fn ord_expand( let fat_arrow = fat_arrow(span); let mut body = quote! {span => match (self, other) { - ##arms + # #arms _unused #fat_arrow #krate::cmp::Ordering::Equal } }; @@ -961,7 +961,7 @@ fn partial_ord_expand( right, quote! {span => match (self, other) { - ##arms + # #arms _unused #fat_arrow #krate::option::Option::Some(#krate::cmp::Ordering::Equal) } }, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs index b56ec3d04c07e..2fb1f96350cd5 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs @@ -240,9 +240,9 @@ fn assert_expand( let dollar_crate = dollar_crate(span); let panic_args = rest.iter(); let mac = if use_panic_2021(db, span) { - quote! {call_site_span => #dollar_crate::panic::panic_2021!(##panic_args) } + quote! {call_site_span => #dollar_crate::panic::panic_2021!(# #panic_args) } } else { - quote! {call_site_span => #dollar_crate::panic!(##panic_args) } + quote! {call_site_span => #dollar_crate::panic!(# #panic_args) } }; let value = cond.value; let expanded = quote! {call_site_span =>{ diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs index 4c8eb74486bbf..9dd2b77b525c4 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs @@ -61,7 +61,7 @@ macro_rules! quote_impl__ { $crate::builtin::quote::__quote!($span $builder $($tail)*); }; - ($span:ident $builder:ident ## $first:ident $($tail:tt)* ) => {{ + ($span:ident $builder:ident # # $first:ident $($tail:tt)* ) => {{ ::std::iter::IntoIterator::into_iter($first).for_each(|it| $crate::builtin::quote::ToTokenTree::to_tokens(it, $span, $builder)); $crate::builtin::quote::__quote!($span $builder $($tail)*); }}; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 102048b3f4dca..38924d7c95495 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -518,7 +518,7 @@ impl<'ctx> MirLowerCtx<'ctx> { let Some(def) = self.owner.as_generic_def_id(self.db.upcast()) else { not_supported!("owner without generic def id"); }; - let gen = generics(self.db.upcast(), def); + let generics = generics(self.db.upcast(), def); let ty = self.expr_ty_without_adjust(expr_id); self.push_assignment( current, @@ -528,7 +528,7 @@ impl<'ctx> MirLowerCtx<'ctx> { ty, value: chalk_ir::ConstValue::BoundVar(BoundVar::new( DebruijnIndex::INNERMOST, - gen.type_or_const_param_idx(p.into()).ok_or( + generics.type_or_const_param_idx(p.into()).ok_or( MirLowerError::TypeError( "fail to lower const generic param", ), diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 9f91f155ea77b..caf00665a1e6b 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -5261,7 +5261,7 @@ impl Type { /// Returns types that this type dereferences to (including this type itself). The returned /// iterator won't yield the same type more than once even if the deref chain contains a cycle. - pub fn autoderef(&self, db: &dyn HirDatabase) -> impl Iterator + '_ { + pub fn autoderef<'db>(&self, db: &'db dyn HirDatabase) -> impl Iterator + use<'_, 'db> { self.autoderef_(db).map(move |ty| self.derived(ty)) } @@ -5637,7 +5637,10 @@ impl Type { .map(Trait::from) } - pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option> { + pub fn as_impl_traits( + &self, + db: &dyn HirDatabase, + ) -> Option + use<>> { self.ty.impl_trait_bounds(db).map(|it| { it.into_iter().filter_map(|pred| match pred.skip_binders() { hir_ty::WhereClause::Implemented(trait_ref) => { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index b971b2e9f1a38..a1c0521a5eb57 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -2087,7 +2087,7 @@ impl SemanticsScope<'_> { ) } - pub fn resolve_mod_path(&self, path: &ModPath) -> impl Iterator { + pub fn resolve_mod_path(&self, path: &ModPath) -> impl Iterator + use<> { let items = self.resolver.resolve_module_path_in_items(self.db.upcast(), path); items.iter_items().map(|(item, _)| item.into()) } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index dc6fd1f5eaeb7..c6f60a9a9654e 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -780,7 +780,8 @@ fn fill_lint_attrs( } }); - let all_matching_groups = lint_groups(&diag.code, edition) + let lints = lint_groups(&diag.code, edition); + let all_matching_groups = lints .iter() .filter_map(|lint_group| cached.get(lint_group)); let cached_severity = diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs index 1fdd698991710..7b0b3e19f2f08 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs @@ -268,13 +268,13 @@ fn hints_( ctx.lifetime_stacks.iter().flat_map(|it| it.iter()).cloned().zip(iter::repeat(0)).collect(); // allocate names let mut gen_idx_name = { - let mut gen = (0u8..).map(|idx| match idx { + let mut generic = (0u8..).map(|idx| match idx { idx if idx < 10 => SmolStr::from_iter(['\'', (idx + 48) as char]), idx => format_smolstr!("'{idx}"), }); let ctx = &*ctx; move || { - gen.by_ref() + generic.by_ref() .find(|s| ctx.lifetime_stacks.iter().flat_map(|it| it.iter()).all(|n| n != s)) .unwrap_or_default() } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs index 1a9cdef256d28..f2e96197ecd9e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs @@ -123,13 +123,15 @@ fn setup_logging(log_file_flag: Option) -> anyhow::Result<()> { // https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/nf-dbghelp-syminitialize if let Ok(path) = env::current_exe() { if let Some(path) = path.parent() { - env::set_var("_NT_SYMBOL_PATH", path); + // SAFETY: This is safe because this is single-threaded. + unsafe { env::set_var("_NT_SYMBOL_PATH", path); } } } } if env::var("RUST_BACKTRACE").is_err() { - env::set_var("RUST_BACKTRACE", "short"); + // SAFETY: This is safe because this is single-threaded. + unsafe { env::set_var("RUST_BACKTRACE", "short"); } } let log_file = env::var("RA_LOG_FILE").ok().map(PathBuf::from).or(log_file_flag); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs index 1f52f366c5469..8496068d67665 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs @@ -148,7 +148,8 @@ impl Project<'_> { let guard = CONFIG_DIR_LOCK.lock(); let test_dir = TestDir::new(); let value = test_dir.path().to_owned(); - env::set_var("__TEST_RA_USER_CONFIG_DIR", &value); + // SAFETY: This is safe because this is single-threaded. + unsafe { env::set_var("__TEST_RA_USER_CONFIG_DIR", &value); } (guard, test_dir) }) } else { diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs index 56f94b965e320..2b330f085866a 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs @@ -1066,7 +1066,7 @@ impl ast::GenericParamList { ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None, }) } - pub fn type_or_const_params(&self) -> impl Iterator { + pub fn type_or_const_params(&self) -> impl Iterator + use<> { self.generic_params().filter_map(|param| match param { ast::GenericParam::TypeParam(it) => Some(ast::TypeOrConstParam::Type(it)), ast::GenericParam::LifetimeParam(_) => None, From ebb85886abb8ea49c922601d6166b30e9e9cc8b3 Mon Sep 17 00:00:00 2001 From: BenjaminBrienen Date: Mon, 10 Mar 2025 12:41:24 +0100 Subject: [PATCH 0134/2248] rust-version = "1.85" --- src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml | 2 +- src/tools/rust-analyzer/lib/la-arena/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml index c2c6dac72de1e..4d639777c3292 100644 --- a/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml @@ -3,7 +3,7 @@ name = "syntax-fuzz" version = "0.0.1" publish = false edition = "2021" -rust-version = "1.78" +rust-version = "1.85" [package.metadata] cargo-fuzz = true diff --git a/src/tools/rust-analyzer/lib/la-arena/Cargo.toml b/src/tools/rust-analyzer/lib/la-arena/Cargo.toml index 589d026142bb7..5fb53a7a557ed 100644 --- a/src/tools/rust-analyzer/lib/la-arena/Cargo.toml +++ b/src/tools/rust-analyzer/lib/la-arena/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/la-aren documentation = "https://docs.rs/la-arena" categories = ["data-structures", "memory-management", "rust-patterns"] edition = "2021" -rust-version = "1.56" +rust-version = "1.85" [lints] workspace = true From 87228245cf4e4ada84709b98e12f36db22b40a9e Mon Sep 17 00:00:00 2001 From: BenjaminBrienen Date: Mon, 10 Mar 2025 12:41:35 +0100 Subject: [PATCH 0135/2248] edition = "2024" --- src/tools/rust-analyzer/Cargo.toml | 2 +- .../crates/proc-macro-srv/proc-macro-test/Cargo.toml | 2 +- .../crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml | 2 +- src/tools/rust-analyzer/docs/book/book.toml | 2 +- src/tools/rust-analyzer/lib/la-arena/Cargo.toml | 2 +- src/tools/rust-analyzer/lib/line-index/Cargo.toml | 2 +- src/tools/rust-analyzer/lib/lsp-server/Cargo.toml | 2 +- src/tools/rust-analyzer/xtask/Cargo.toml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index e9d70bea346dc..03ecc8f2741e3 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -5,7 +5,7 @@ resolver = "2" [workspace.package] rust-version = "1.85" -edition = "2021" +edition = "2024" license = "MIT OR Apache-2.0" authors = ["rust-analyzer team"] repository = "https://github.com/rust-lang/rust-analyzer" diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml index 16fcc92962072..2a5bfdd2572f4 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml @@ -3,7 +3,7 @@ name = "proc-macro-test" version = "0.0.0" publish = false -edition = "2021" +edition = "2024" license = "MIT OR Apache-2.0" [lib] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml index fb98d758a8b7b..33b7c2bb0ad66 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml @@ -2,7 +2,7 @@ name = "proc-macro-test-impl" version = "0.0.0" license = "MIT OR Apache-2.0" -edition = "2021" +edition = "2024" publish = false [lib] diff --git a/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml index 4d639777c3292..8910911ff0259 100644 --- a/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml @@ -2,7 +2,7 @@ name = "syntax-fuzz" version = "0.0.1" publish = false -edition = "2021" +edition = "2024" rust-version = "1.85" [package.metadata] diff --git a/src/tools/rust-analyzer/docs/book/book.toml b/src/tools/rust-analyzer/docs/book/book.toml index a6f6a6ed784db..edf11fadf0831 100644 --- a/src/tools/rust-analyzer/docs/book/book.toml +++ b/src/tools/rust-analyzer/docs/book/book.toml @@ -6,7 +6,7 @@ src = "src" title = "rust-analyzer" [rust] -edition = "2021" +edition = "2024" [output.html] edit-url-template = "https://github.com/rust-lang/rust-analyzer/edit/master/docs/book/{path}" diff --git a/src/tools/rust-analyzer/lib/la-arena/Cargo.toml b/src/tools/rust-analyzer/lib/la-arena/Cargo.toml index 5fb53a7a557ed..1c330e0e37e17 100644 --- a/src/tools/rust-analyzer/lib/la-arena/Cargo.toml +++ b/src/tools/rust-analyzer/lib/la-arena/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/la-arena" documentation = "https://docs.rs/la-arena" categories = ["data-structures", "memory-management", "rust-patterns"] -edition = "2021" +edition = "2024" rust-version = "1.85" [lints] diff --git a/src/tools/rust-analyzer/lib/line-index/Cargo.toml b/src/tools/rust-analyzer/lib/line-index/Cargo.toml index 14196ba3d0973..f15c2e39372da 100644 --- a/src/tools/rust-analyzer/lib/line-index/Cargo.toml +++ b/src/tools/rust-analyzer/lib/line-index/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.2" description = "Maps flat `TextSize` offsets to/from `(line, column)` representation." license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/line-index" -edition = "2021" +edition = "2024" [dependencies] text-size = "1.1.1" diff --git a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml index 2fa3272e6593f..39b931561bda8 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml +++ b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml @@ -4,7 +4,7 @@ version = "0.7.8" description = "Generic LSP server scaffold." license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-server" -edition = "2021" +edition = "2024" [dependencies] log = "0.4.17" diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml index ebd8903ad8ac3..01a561dcb9f38 100644 --- a/src/tools/rust-analyzer/xtask/Cargo.toml +++ b/src/tools/rust-analyzer/xtask/Cargo.toml @@ -3,7 +3,7 @@ name = "xtask" version = "0.1.0" publish = false license = "MIT OR Apache-2.0" -edition = "2021" +edition = "2024" rust-version.workspace = true [dependencies] From b5b7a54e95f6a9220008f6e2cb95e2d03fe97e1c Mon Sep 17 00:00:00 2001 From: BenjaminBrienen Date: Mon, 10 Mar 2025 12:41:51 +0100 Subject: [PATCH 0136/2248] cargo clippy --fix --- .../rust-analyzer/crates/hir-def/src/item_tree/lower.rs | 2 +- src/tools/rust-analyzer/crates/hir-ty/src/builder.rs | 6 +++--- src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs | 4 ++-- src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs | 4 ++-- .../rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs | 2 +- src/tools/rust-analyzer/crates/ide/src/signature_help.rs | 6 +++--- .../rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index b0cc7ead8c0dd..3c85d5bacb459 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -932,7 +932,7 @@ impl<'a> Ctx<'a> { fn desugar_future_path(ctx: &mut LowerCtx<'_>, orig: TypeRefId) -> PathId { let path = path![core::future::Future]; let mut generic_args: Vec<_> = - std::iter::repeat(None).take(path.segments().len() - 1).collect(); + std::iter::repeat_n(None, path.segments().len() - 1).collect(); let binding = AssociatedTypeBinding { name: Name::new_symbol_root(sym::Output.clone()), args: None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs index 76d9c60f6f903..4c35db0c9b98c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs @@ -263,7 +263,7 @@ impl TyBuilder<()> { .as_generic_def_id(db.upcast()) .map(|p| generics(db.upcast(), p).placeholder_subst(db)); // These represent resume type, yield type, and return type of coroutine. - let params = std::iter::repeat(ParamKind::Type).take(3).collect(); + let params = std::iter::repeat_n(ParamKind::Type, 3).collect(); TyBuilder::new((), params, parent_subst) } @@ -340,7 +340,7 @@ impl TyBuilder { pub struct Tuple(usize); impl TyBuilder { pub fn tuple(size: usize) -> TyBuilder { - TyBuilder::new(Tuple(size), iter::repeat(ParamKind::Type).take(size).collect(), None) + TyBuilder::new(Tuple(size), std::iter::repeat_n(ParamKind::Type, size).collect(), None) } pub fn build(self) -> Ty { @@ -356,7 +356,7 @@ impl TyBuilder { let elements = elements.into_iter(); let len = elements.len(); let mut b = - TyBuilder::new(Tuple(len), iter::repeat(ParamKind::Type).take(len).collect(), None); + TyBuilder::new(Tuple(len), std::iter::repeat_n(ParamKind::Type, len).collect(), None); for e in elements { b = b.push(e); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index e55fc0a9b83d9..6d80bfc38e5b7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -1,6 +1,6 @@ //! Unification and canonicalization logic. -use std::{fmt, iter, mem}; +use std::{fmt, mem}; use chalk_ir::{ cast::Cast, fold::TypeFoldable, interner::HasInterner, zip::Zip, CanonicalVarKind, FloatTy, @@ -386,7 +386,7 @@ impl<'a> InferenceTable<'a> { } fn extend_type_variable_table(&mut self, to_index: usize) { let count = to_index - self.type_variable_table.len() + 1; - self.type_variable_table.extend(iter::repeat(TypeVariableFlags::default()).take(count)); + self.type_variable_table.extend(std::iter::repeat_n(TypeVariableFlags::default(), count)); } fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 45b4385568196..be0a79f1dd394 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -1119,7 +1119,7 @@ impl Evaluator<'_> { "Stack overflow. Tried to grow stack to {stack_size} bytes" ))); } - self.stack.extend(iter::repeat(0).take(stack_size)); + self.stack.extend(std::iter::repeat_n(0, stack_size)); Ok((locals, prev_stack_pointer)) } @@ -2122,7 +2122,7 @@ impl Evaluator<'_> { return Err(MirEvalError::Panic(format!("Memory allocation of {size} bytes failed"))); } let pos = self.heap.len(); - self.heap.extend(iter::repeat(0).take(size)); + self.heap.extend(std::iter::repeat_n(0, size)); Ok(Address::Heap(pos)) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs index 829ed9efa2bc1..54754045c98aa 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs @@ -127,7 +127,7 @@ impl Evaluator<'_> { Ordering::Greater => ["ge", "gt", "ne"].contains(&name), }; let result = if result { 255 } else { 0 }; - destination_bytes.extend(std::iter::repeat(result).take(dest_size)); + destination_bytes.extend(std::iter::repeat_n(result, dest_size)); } destination.write_from_bytes(self, &destination_bytes) diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs index 84912f6be65af..ce3c4238b5b18 100644 --- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs +++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs @@ -695,7 +695,7 @@ fn signature_help_for_tuple_pat_ish( } #[cfg(test)] mod tests { - use std::iter; + use expect_test::{expect, Expect}; use ide_db::FilePosition; @@ -742,11 +742,11 @@ mod tests { let gap = start.checked_sub(offset).unwrap_or_else(|| { panic!("parameter ranges out of order: {:?}", sig_help.parameter_ranges()) }); - rendered.extend(iter::repeat(' ').take(gap as usize)); + rendered.extend(std::iter::repeat_n(' ', gap as usize)); let param_text = &sig_help.signature[*range]; let width = param_text.chars().count(); // … let marker = if is_active { '^' } else { '-' }; - rendered.extend(iter::repeat(marker).take(width)); + rendered.extend(std::iter::repeat_n(marker, width)); offset += gap + u32::from(range.len()); } if !sig_help.parameter_ranges().is_empty() { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index 70e567ec76920..d9fab85df1cc8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -1549,7 +1549,7 @@ pub(crate) fn runnable( ); let cwd = match runnable.kind { - ide::RunnableKind::Bin { .. } => workspace_root.clone(), + ide::RunnableKind::Bin => workspace_root.clone(), _ => spec.cargo_toml.parent().to_owned(), }; From edb25788a075011142eec177354e887717c20d79 Mon Sep 17 00:00:00 2001 From: BenjaminBrienen Date: Mon, 10 Mar 2025 12:41:59 +0100 Subject: [PATCH 0137/2248] fix clippy::doc_overindented_list_items --- .../crates/project-model/src/project_json.rs | 3 +-- .../rust-analyzer/crates/toolchain/src/lib.rs | 24 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs index 3c14e6e627771..d78fa12d812e4 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs @@ -85,8 +85,7 @@ impl ProjectJson { /// /// * `manifest` - The path to the `rust-project.json`. /// * `base` - The path to the workspace root (i.e. the folder containing `rust-project.json`) - /// * `data` - The parsed contents of `rust-project.json`, or project json that's passed via - /// configuration. + /// * `data` - The parsed contents of `rust-project.json`, or project json that's passed via configuration. pub fn new( manifest: Option, base: &AbsPath, diff --git a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs index 325b94cc33bae..e3b30ff9cdecd 100644 --- a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs +++ b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs @@ -27,14 +27,14 @@ impl Tool { /// /// The current implementation checks three places for an executable to use: /// 1) `$CARGO_HOME/bin/` - /// where $CARGO_HOME defaults to ~/.cargo (see ) - /// example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. - /// It seems that this is a reasonable place to try for cargo, rustc, and rustup + /// where $CARGO_HOME defaults to ~/.cargo (see ) + /// example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. + /// It seems that this is a reasonable place to try for cargo, rustc, and rustup /// 2) Appropriate environment variable (erroring if this is set but not a usable executable) - /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc + /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc /// 3) $PATH/`` - /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the - /// first that exists + /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the + /// first that exists /// 4) If all else fails, we just try to use the executable name directly pub fn prefer_proxy(self) -> Utf8PathBuf { invoke(&[cargo_proxy, lookup_as_env_var, lookup_in_path], self.name()) @@ -44,14 +44,14 @@ impl Tool { /// /// The current implementation checks three places for an executable to use: /// 1) Appropriate environment variable (erroring if this is set but not a usable executable) - /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc + /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc /// 2) $PATH/`` - /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the - /// first that exists + /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the + /// first that exists /// 3) `$CARGO_HOME/bin/` - /// where $CARGO_HOME defaults to ~/.cargo (see ) - /// example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. - /// It seems that this is a reasonable place to try for cargo, rustc, and rustup + /// where $CARGO_HOME defaults to ~/.cargo (see ) + /// example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. + /// It seems that this is a reasonable place to try for cargo, rustc, and rustup /// 4) If all else fails, we just try to use the executable name directly pub fn path(self) -> Utf8PathBuf { invoke(&[lookup_as_env_var, lookup_in_path, cargo_proxy], self.name()) From 4041c67e90fb6c6f621e3ada853f99874eb637cd Mon Sep 17 00:00:00 2001 From: BenjaminBrienen Date: Mon, 10 Mar 2025 12:42:27 +0100 Subject: [PATCH 0138/2248] cargo fmt --- .../crates/base-db/src/change.rs | 6 +- .../rust-analyzer/crates/base-db/src/input.rs | 84 +++++++++++-------- .../rust-analyzer/crates/base-db/src/lib.rs | 6 +- src/tools/rust-analyzer/crates/cfg/src/lib.rs | 2 +- .../rust-analyzer/crates/cfg/src/tests.rs | 9 +- .../rust-analyzer/crates/hir-def/src/attr.rs | 14 ++-- .../crates/hir-def/src/builtin_type.rs | 2 +- .../rust-analyzer/crates/hir-def/src/data.rs | 14 ++-- .../crates/hir-def/src/data/adt.rs | 2 +- .../rust-analyzer/crates/hir-def/src/db.rs | 26 +++--- .../crates/hir-def/src/dyn_map.rs | 6 +- .../crates/hir-def/src/expander.rs | 16 ++-- .../crates/hir-def/src/expr_store.rs | 6 +- .../crates/hir-def/src/expr_store/body.rs | 4 +- .../crates/hir-def/src/expr_store/lower.rs | 22 ++--- .../hir-def/src/expr_store/lower/asm.rs | 2 +- .../crates/hir-def/src/expr_store/scope.rs | 10 +-- .../crates/hir-def/src/expr_store/tests.rs | 4 +- .../crates/hir-def/src/find_path.rs | 6 +- .../crates/hir-def/src/generics.rs | 12 +-- .../rust-analyzer/crates/hir-def/src/hir.rs | 10 +-- .../crates/hir-def/src/hir/format_args.rs | 2 +- .../crates/hir-def/src/hir/type_ref.rs | 22 ++--- .../crates/hir-def/src/import_map.rs | 16 ++-- .../crates/hir-def/src/item_scope.rs | 8 +- .../crates/hir-def/src/item_tree.rs | 6 +- .../crates/hir-def/src/item_tree/lower.rs | 11 ++- .../crates/hir-def/src/item_tree/tests.rs | 2 +- .../crates/hir-def/src/lang_item.rs | 18 ++-- .../rust-analyzer/crates/hir-def/src/lib.rs | 16 ++-- .../rust-analyzer/crates/hir-def/src/lower.rs | 2 +- .../hir-def/src/macro_expansion_tests/mod.rs | 6 +- .../crates/hir-def/src/nameres.rs | 8 +- .../crates/hir-def/src/nameres/assoc.rs | 10 +-- .../hir-def/src/nameres/attr_resolution.rs | 6 +- .../crates/hir-def/src/nameres/collector.rs | 26 +++--- .../crates/hir-def/src/nameres/diagnostics.rs | 4 +- .../hir-def/src/nameres/mod_resolution.rs | 4 +- .../hir-def/src/nameres/path_resolution.rs | 14 ++-- .../crates/hir-def/src/nameres/tests.rs | 2 +- .../hir-def/src/nameres/tests/incremental.rs | 2 +- .../rust-analyzer/crates/hir-def/src/path.rs | 2 +- .../crates/hir-def/src/path/lower.rs | 2 +- .../crates/hir-def/src/path/tests.rs | 4 +- .../crates/hir-def/src/per_ns.rs | 8 +- .../crates/hir-def/src/resolver.rs | 26 +++--- .../rust-analyzer/crates/hir-def/src/src.rs | 6 +- .../crates/hir-def/src/test_db.rs | 6 +- .../crates/hir-def/src/visibility.rs | 2 +- .../crates/hir-expand/src/attrs.rs | 12 +-- .../crates/hir-expand/src/builtin.rs | 6 +- .../hir-expand/src/builtin/attr_macro.rs | 4 +- .../hir-expand/src/builtin/derive_macro.rs | 21 +++-- .../crates/hir-expand/src/builtin/fn_macro.rs | 33 ++++---- .../crates/hir-expand/src/builtin/quote.rs | 9 +- .../crates/hir-expand/src/cfg_process.rs | 10 +-- .../rust-analyzer/crates/hir-expand/src/db.rs | 23 +++-- .../crates/hir-expand/src/declarative.rs | 7 +- .../crates/hir-expand/src/eager.rs | 6 +- .../crates/hir-expand/src/files.rs | 9 +- .../crates/hir-expand/src/fixup.rs | 9 +- .../crates/hir-expand/src/hygiene.rs | 2 +- .../crates/hir-expand/src/lib.rs | 14 ++-- .../crates/hir-expand/src/mod_path.rs | 4 +- .../crates/hir-expand/src/name.rs | 2 +- .../src/prettify_macro_expansion_.rs | 2 +- .../crates/hir-expand/src/proc_macro.rs | 6 +- .../crates/hir-expand/src/span_map.rs | 2 +- .../crates/hir-ty/src/autoderef.rs | 4 +- .../crates/hir-ty/src/builder.rs | 12 +-- .../crates/hir-ty/src/chalk_db.rs | 19 +++-- .../crates/hir-ty/src/chalk_ext.rs | 12 +-- .../crates/hir-ty/src/consteval.rs | 11 +-- .../crates/hir-ty/src/consteval/tests.rs | 6 +- .../rust-analyzer/crates/hir-ty/src/db.rs | 16 ++-- .../crates/hir-ty/src/diagnostics.rs | 8 +- .../hir-ty/src/diagnostics/decl_check.rs | 10 +-- .../src/diagnostics/decl_check/case_conv.rs | 2 +- .../crates/hir-ty/src/diagnostics/expr.rs | 8 +- .../hir-ty/src/diagnostics/match_check.rs | 6 +- .../diagnostics/match_check/pat_analysis.rs | 10 +-- .../hir-ty/src/diagnostics/unsafe_check.rs | 6 +- .../crates/hir-ty/src/display.rs | 26 +++--- .../rust-analyzer/crates/hir-ty/src/drop.rs | 12 +-- .../crates/hir-ty/src/dyn_compatibility.rs | 17 ++-- .../crates/hir-ty/src/generics.rs | 8 +- .../rust-analyzer/crates/hir-ty/src/infer.rs | 28 +++---- .../crates/hir-ty/src/infer/cast.rs | 6 +- .../crates/hir-ty/src/infer/closure.rs | 12 +-- .../crates/hir-ty/src/infer/coerce.rs | 6 +- .../crates/hir-ty/src/infer/diagnostics.rs | 4 +- .../crates/hir-ty/src/infer/expr.rs | 36 ++++---- .../crates/hir-ty/src/infer/mutability.rs | 6 +- .../crates/hir-ty/src/infer/pat.rs | 11 +-- .../crates/hir-ty/src/infer/path.rs | 11 +-- .../crates/hir-ty/src/infer/unify.rs | 22 ++--- .../crates/hir-ty/src/inhabitedness.rs | 6 +- .../crates/hir-ty/src/interner.rs | 12 +-- .../crates/hir-ty/src/lang_items.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/layout.rs | 8 +- .../crates/hir-ty/src/layout/adt.rs | 6 +- .../crates/hir-ty/src/layout/tests.rs | 4 +- .../rust-analyzer/crates/hir-ty/src/lib.rs | 56 +++++-------- .../rust-analyzer/crates/hir-ty/src/lower.rs | 35 ++++---- .../crates/hir-ty/src/lower/path.rs | 12 +-- .../crates/hir-ty/src/mapping.rs | 6 +- .../crates/hir-ty/src/method_resolution.rs | 30 +++---- .../rust-analyzer/crates/hir-ty/src/mir.rs | 16 ++-- .../crates/hir-ty/src/mir/borrowck.rs | 8 +- .../crates/hir-ty/src/mir/eval.rs | 43 +++++----- .../crates/hir-ty/src/mir/eval/shim.rs | 10 +-- .../crates/hir-ty/src/mir/eval/shim/simd.rs | 6 +- .../crates/hir-ty/src/mir/eval/tests.rs | 4 +- .../crates/hir-ty/src/mir/lower.rs | 36 ++++---- .../hir-ty/src/mir/lower/pattern_matching.rs | 10 +-- .../crates/hir-ty/src/mir/monomorphization.rs | 6 +- .../crates/hir-ty/src/mir/pretty.rs | 4 +- .../crates/hir-ty/src/target_feature.rs | 22 ++--- .../crates/hir-ty/src/test_db.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/tests.rs | 10 +-- .../hir-ty/src/tests/closure_captures.rs | 6 +- .../rust-analyzer/crates/hir-ty/src/tls.rs | 10 +-- .../rust-analyzer/crates/hir-ty/src/traits.rs | 18 ++-- .../rust-analyzer/crates/hir-ty/src/utils.rs | 18 ++-- .../crates/hir-ty/src/variance.rs | 8 +- .../rust-analyzer/crates/hir/src/attrs.rs | 8 +- .../crates/hir/src/diagnostics.rs | 15 ++-- .../rust-analyzer/crates/hir/src/display.rs | 10 +-- .../rust-analyzer/crates/hir/src/from_id.rs | 2 +- .../crates/hir/src/has_source.rs | 5 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 76 +++++++---------- .../rust-analyzer/crates/hir/src/semantics.rs | 26 +++--- .../hir/src/semantics/child_by_source.rs | 12 +-- .../crates/hir/src/semantics/source_to_def.rs | 18 ++-- .../crates/hir/src/source_analyzer.rs | 45 ++++------ .../rust-analyzer/crates/hir/src/symbols.rs | 10 +-- .../crates/hir/src/term_search/tactics.rs | 2 +- .../crates/ide-assists/src/assist_config.rs | 2 +- .../crates/ide-assists/src/assist_context.rs | 8 +- .../ide-assists/src/handlers/add_braces.rs | 2 +- .../add_explicit_enum_discriminant.rs | 4 +- .../src/handlers/add_label_to_loop.rs | 2 +- .../src/handlers/add_lifetime_to_type.rs | 12 +-- .../src/handlers/add_missing_impl_members.rs | 8 +- .../src/handlers/add_missing_match_arms.rs | 8 +- .../src/handlers/add_return_type.rs | 2 +- .../src/handlers/add_turbo_fish.rs | 8 +- .../src/handlers/apply_demorgan.rs | 11 ++- .../ide-assists/src/handlers/auto_import.rs | 12 +-- .../src/handlers/bind_unused_param.rs | 4 +- .../src/handlers/change_visibility.rs | 4 +- .../src/handlers/convert_bool_then.rs | 10 +-- .../src/handlers/convert_bool_to_enum.rs | 10 +-- .../src/handlers/convert_closure_to_fn.rs | 9 +- .../src/handlers/convert_comment_block.rs | 8 +- .../convert_comment_from_or_to_doc.rs | 2 +- .../src/handlers/convert_for_to_while_let.rs | 6 +- .../src/handlers/convert_from_to_tryfrom.rs | 2 +- .../src/handlers/convert_integer_literal.rs | 2 +- .../handlers/convert_iter_for_each_to_for.rs | 4 +- .../src/handlers/convert_let_else_to_match.rs | 10 +-- .../src/handlers/convert_match_to_let_else.rs | 5 +- .../convert_named_struct_to_tuple_struct.rs | 5 +- .../src/handlers/convert_to_guarded_return.rs | 9 +- .../convert_tuple_return_type_to_struct.rs | 9 +- .../convert_tuple_struct_to_named_struct.rs | 5 +- .../src/handlers/convert_while_to_loop.rs | 8 +- .../handlers/destructure_struct_binding.rs | 6 +- .../src/handlers/destructure_tuple_binding.rs | 2 +- .../src/handlers/desugar_doc_comment.rs | 4 +- .../src/handlers/expand_glob_import.rs | 7 +- .../src/handlers/expand_rest_pattern.rs | 3 +- .../extract_expressions_from_format_string.rs | 48 ++++++----- .../src/handlers/extract_function.rs | 23 +++-- .../src/handlers/extract_module.rs | 17 ++-- .../extract_struct_from_enum_variant.rs | 17 ++-- .../src/handlers/extract_type_alias.rs | 2 +- .../src/handlers/extract_variable.rs | 10 +-- .../src/handlers/fix_visibility.rs | 4 +- .../ide-assists/src/handlers/flip_binexpr.rs | 2 +- .../ide-assists/src/handlers/flip_comma.rs | 2 +- .../src/handlers/flip_or_pattern.rs | 2 +- .../src/handlers/flip_trait_bound.rs | 2 +- .../src/handlers/generate_constant.rs | 4 +- .../generate_default_from_enum_variant.rs | 8 +- .../src/handlers/generate_default_from_new.rs | 4 +- .../src/handlers/generate_delegate_methods.rs | 6 +- .../src/handlers/generate_delegate_trait.rs | 14 ++-- .../src/handlers/generate_deref.rs | 6 +- .../src/handlers/generate_derive.rs | 2 +- .../generate_documentation_template.rs | 5 +- .../src/handlers/generate_enum_is_method.rs | 2 +- .../generate_enum_projection_method.rs | 2 +- .../src/handlers/generate_enum_variant.rs | 5 +- .../src/handlers/generate_fn_type_alias.rs | 5 +- .../handlers/generate_from_impl_for_enum.rs | 10 +-- .../src/handlers/generate_function.rs | 16 ++-- .../src/handlers/generate_getter_or_setter.rs | 7 +- .../ide-assists/src/handlers/generate_impl.rs | 4 +- .../handlers/generate_is_empty_from_len.rs | 6 +- .../src/handlers/generate_mut_trait_impl.rs | 3 +- .../ide-assists/src/handlers/generate_new.rs | 4 +- .../src/handlers/generate_trait_from_impl.rs | 6 +- .../ide-assists/src/handlers/inline_call.rs | 14 ++-- .../src/handlers/inline_const_as_literal.rs | 2 +- .../src/handlers/inline_local_variable.rs | 6 +- .../src/handlers/inline_type_alias.rs | 7 +- .../src/handlers/into_to_qualified_from.rs | 2 +- .../src/handlers/introduce_named_lifetime.rs | 6 +- .../introduce_named_type_parameter.rs | 2 +- .../ide-assists/src/handlers/invert_if.rs | 4 +- .../ide-assists/src/handlers/merge_imports.rs | 7 +- .../src/handlers/merge_match_arms.rs | 2 +- .../src/handlers/merge_nested_if.rs | 4 +- .../ide-assists/src/handlers/move_bounds.rs | 4 +- .../src/handlers/move_const_to_impl.rs | 2 +- .../src/handlers/move_from_mod_rs.rs | 2 +- .../ide-assists/src/handlers/move_guard.rs | 2 +- .../src/handlers/move_module_to_file.rs | 4 +- .../src/handlers/move_to_mod_rs.rs | 2 +- .../src/handlers/normalize_import.rs | 4 +- .../src/handlers/number_representation.rs | 2 +- .../src/handlers/promote_local_to_const.rs | 5 +- .../src/handlers/pull_assignment_up.rs | 5 +- .../src/handlers/qualify_method_call.rs | 4 +- .../ide-assists/src/handlers/qualify_path.rs | 9 +- .../ide-assists/src/handlers/raw_string.rs | 4 +- .../ide-assists/src/handlers/remove_dbg.rs | 5 +- .../src/handlers/remove_parentheses.rs | 2 +- .../src/handlers/remove_unused_imports.rs | 4 +- .../src/handlers/remove_unused_param.rs | 8 +- .../src/handlers/reorder_fields.rs | 2 +- .../src/handlers/reorder_impl_items.rs | 2 +- .../src/handlers/replace_arith_op.rs | 2 +- .../replace_derive_with_manual_impl.rs | 10 +-- .../src/handlers/replace_if_let_with_match.rs | 8 +- .../replace_is_method_with_if_let_method.rs | 2 +- .../src/handlers/replace_let_with_if_let.rs | 2 +- .../src/handlers/replace_method_eager_lazy.rs | 14 +--- .../replace_named_generic_with_impl.rs | 9 +- .../replace_qualified_name_with_use.rs | 7 +- .../src/handlers/replace_string_with_char.rs | 5 +- .../handlers/replace_try_expr_with_match.rs | 2 +- .../replace_turbofish_with_explicit_type.rs | 4 +- .../ide-assists/src/handlers/sort_items.rs | 4 +- .../ide-assists/src/handlers/split_import.rs | 2 +- .../ide-assists/src/handlers/term_search.rs | 2 +- .../src/handlers/toggle_async_sugar.rs | 2 +- .../ide-assists/src/handlers/toggle_ignore.rs | 4 +- .../src/handlers/toggle_macro_delimiter.rs | 3 +- .../src/handlers/unmerge_match_arm.rs | 4 +- .../ide-assists/src/handlers/unmerge_use.rs | 6 +- .../src/handlers/unnecessary_async.rs | 4 +- .../src/handlers/unqualify_method_call.rs | 2 +- .../ide-assists/src/handlers/unwrap_block.rs | 2 +- .../src/handlers/unwrap_return_type.rs | 5 +- .../ide-assists/src/handlers/unwrap_tuple.rs | 2 +- .../src/handlers/wrap_return_type.rs | 5 +- .../src/handlers/wrap_unwrap_cfg_attr.rs | 11 +-- .../crates/ide-assists/src/tests.rs | 6 +- .../crates/ide-assists/src/utils.rs | 26 ++---- .../src/utils/gen_trait_fn_body.rs | 2 +- .../ide-assists/src/utils/ref_field_expr.rs | 2 +- .../crates/ide-completion/src/completions.rs | 10 +-- .../src/completions/attribute.rs | 8 +- .../src/completions/attribute/cfg.rs | 4 +- .../src/completions/attribute/derive.rs | 4 +- .../src/completions/attribute/lint.rs | 4 +- .../src/completions/attribute/macro_use.rs | 2 +- .../src/completions/attribute/repr.rs | 2 +- .../ide-completion/src/completions/dot.rs | 2 +- .../src/completions/env_vars.rs | 54 +++++++----- .../ide-completion/src/completions/expr.rs | 10 +-- .../src/completions/extern_abi.rs | 4 +- .../src/completions/extern_crate.rs | 4 +- .../ide-completion/src/completions/field.rs | 2 +- .../src/completions/flyimport.rs | 12 +-- .../src/completions/fn_param.rs | 6 +- .../src/completions/format_string.rs | 6 +- .../src/completions/item_list.rs | 2 +- .../src/completions/item_list/trait_impl.rs | 15 ++-- .../src/completions/lifetime.rs | 2 +- .../ide-completion/src/completions/mod_.rs | 6 +- .../ide-completion/src/completions/pattern.rs | 2 +- .../ide-completion/src/completions/postfix.rs | 28 ++++--- .../src/completions/postfix/format_like.rs | 6 +- .../ide-completion/src/completions/record.rs | 6 +- .../ide-completion/src/completions/snippet.rs | 26 +++--- .../ide-completion/src/completions/type.rs | 4 +- .../ide-completion/src/completions/use_.rs | 4 +- .../ide-completion/src/completions/vis.rs | 2 +- .../crates/ide-completion/src/config.rs | 4 +- .../crates/ide-completion/src/context.rs | 23 +++-- .../ide-completion/src/context/analysis.rs | 17 ++-- .../ide-completion/src/context/tests.rs | 4 +- .../crates/ide-completion/src/item.rs | 8 +- .../crates/ide-completion/src/lib.rs | 2 +- .../crates/ide-completion/src/render.rs | 16 ++-- .../ide-completion/src/render/function.rs | 16 ++-- .../ide-completion/src/render/literal.rs | 19 ++--- .../ide-completion/src/render/macro_.rs | 4 +- .../ide-completion/src/render/pattern.rs | 8 +- .../src/render/union_literal.rs | 4 +- .../ide-completion/src/render/variant.rs | 2 +- .../crates/ide-completion/src/tests.rs | 6 +- .../ide-completion/src/tests/expression.rs | 8 +- .../ide-completion/src/tests/flyimport.rs | 6 +- .../src/tests/raw_identifiers.rs | 4 +- .../ide-completion/src/tests/special.rs | 8 +- .../crates/ide-db/src/active_parameter.rs | 3 +- .../crates/ide-db/src/apply_change.rs | 2 +- .../rust-analyzer/crates/ide-db/src/defs.rs | 5 +- .../crates/ide-db/src/documentation.rs | 11 +-- .../crates/ide-db/src/famous_defs.rs | 6 +- .../crates/ide-db/src/helpers.rs | 5 +- .../ide-db/src/imports/import_assets.rs | 12 +-- .../crates/ide-db/src/imports/insert_use.rs | 14 ++-- .../ide-db/src/imports/insert_use/tests.rs | 2 +- .../ide-db/src/imports/merge_imports.rs | 9 +- .../crates/ide-db/src/items_locator.rs | 4 +- .../rust-analyzer/crates/ide-db/src/lib.rs | 12 +-- .../crates/ide-db/src/path_transform.rs | 5 +- .../crates/ide-db/src/prime_caches.rs | 4 +- .../rust-analyzer/crates/ide-db/src/rename.rs | 6 +- .../rust-analyzer/crates/ide-db/src/search.rs | 14 ++-- .../crates/ide-db/src/source_change.rs | 19 +++-- .../crates/ide-db/src/symbol_index.rs | 4 +- .../src/syntax_helpers/format_string.rs | 2 +- .../src/syntax_helpers/format_string_exprs.rs | 2 +- .../ide-db/src/syntax_helpers/node_ext.rs | 2 +- .../ide-db/src/syntax_helpers/suggest_name.rs | 3 +- .../ide-db/src/syntax_helpers/tree_diff.rs | 4 +- .../rust-analyzer/crates/ide-db/src/traits.rs | 8 +- .../crates/ide-db/src/ty_filter.rs | 2 +- .../ide-db/src/use_trivial_constructor.rs | 2 +- .../src/handlers/await_outside_of_async.rs | 2 +- .../src/handlers/field_shorthand.rs | 6 +- .../src/handlers/generic_args_prohibited.rs | 4 +- .../src/handlers/inactive_code.rs | 2 +- .../src/handlers/incoherent_impl.rs | 2 +- .../src/handlers/incorrect_case.rs | 6 +- .../src/handlers/json_is_not_rust.rs | 10 +-- .../src/handlers/macro_error.rs | 2 +- .../src/handlers/mismatched_arg_count.rs | 4 +- .../src/handlers/missing_fields.rs | 20 ++--- .../src/handlers/missing_match_arms.rs | 2 +- .../src/handlers/missing_unsafe.rs | 6 +- .../src/handlers/mutability_errors.rs | 4 +- .../src/handlers/no_such_field.rs | 8 +- .../src/handlers/remove_trailing_return.rs | 6 +- .../src/handlers/remove_unnecessary_else.rs | 6 +- .../replace_filter_map_next_with_find_map.rs | 8 +- .../handlers/trait_impl_incorrect_safety.rs | 2 +- .../handlers/trait_impl_missing_assoc_item.rs | 4 +- .../trait_impl_redundant_assoc_item.rs | 2 +- .../src/handlers/type_mismatch.rs | 15 ++-- .../src/handlers/typed_hole.rs | 10 +-- .../src/handlers/unlinked_file.rs | 12 +-- .../src/handlers/unresolved_field.rs | 19 ++--- .../src/handlers/unresolved_method.rs | 15 ++-- .../src/handlers/unresolved_module.rs | 4 +- .../src/handlers/unused_variables.rs | 2 +- .../src/handlers/useless_braces.rs | 8 +- .../crates/ide-diagnostics/src/lib.rs | 15 ++-- .../crates/ide-diagnostics/src/tests.rs | 4 +- .../crates/ide-ssr/src/fragments.rs | 2 +- .../crates/ide-ssr/src/from_comment.rs | 4 +- .../rust-analyzer/crates/ide-ssr/src/lib.rs | 4 +- .../crates/ide-ssr/src/matching.rs | 6 +- .../crates/ide-ssr/src/parsing.rs | 2 +- .../crates/ide-ssr/src/replacing.rs | 4 +- .../crates/ide-ssr/src/resolving.rs | 6 +- .../crates/ide-ssr/src/search.rs | 7 +- .../rust-analyzer/crates/ide-ssr/src/tests.rs | 6 +- .../crates/ide/src/annotations.rs | 14 ++-- .../ide/src/annotations/fn_references.rs | 4 +- .../crates/ide/src/call_hierarchy.rs | 8 +- .../rust-analyzer/crates/ide/src/doc_links.rs | 17 ++-- .../ide/src/doc_links/intra_doc_links.rs | 2 +- .../crates/ide/src/doc_links/tests.rs | 13 +-- .../crates/ide/src/expand_macro.rs | 8 +- .../crates/ide/src/extend_selection.rs | 18 ++-- .../crates/ide/src/fetch_crates.rs | 2 +- .../crates/ide/src/file_structure.rs | 6 +- .../rust-analyzer/crates/ide/src/fixture.rs | 2 +- .../crates/ide/src/folding_ranges.rs | 7 +- .../crates/ide/src/goto_declaration.rs | 16 ++-- .../crates/ide/src/goto_definition.rs | 15 ++-- .../crates/ide/src/goto_implementation.rs | 4 +- .../crates/ide/src/goto_type_definition.rs | 4 +- .../crates/ide/src/highlight_related.rs | 21 ++--- .../rust-analyzer/crates/ide/src/hover.rs | 14 ++-- .../crates/ide/src/hover/render.rs | 25 +++--- .../crates/ide/src/hover/tests.rs | 6 +- .../crates/ide/src/inlay_hints.rs | 19 +++-- .../crates/ide/src/inlay_hints/adjustment.rs | 6 +- .../crates/ide/src/inlay_hints/bind_pat.rs | 8 +- .../ide/src/inlay_hints/binding_mode.rs | 2 +- .../crates/ide/src/inlay_hints/bounds.rs | 4 +- .../crates/ide/src/inlay_hints/chaining.rs | 9 +- .../ide/src/inlay_hints/closing_brace.rs | 9 +- .../ide/src/inlay_hints/closure_captures.rs | 4 +- .../crates/ide/src/inlay_hints/closure_ret.rs | 4 +- .../ide/src/inlay_hints/discriminant.rs | 4 +- .../ide/src/inlay_hints/extern_block.rs | 4 +- .../ide/src/inlay_hints/generic_param.rs | 8 +- .../ide/src/inlay_hints/implicit_drop.rs | 9 +- .../ide/src/inlay_hints/implicit_static.rs | 4 +- .../crates/ide/src/inlay_hints/lifetime.rs | 15 ++-- .../crates/ide/src/inlay_hints/param_name.rs | 6 +- .../ide/src/inlay_hints/range_exclusive.rs | 4 +- .../rust-analyzer/crates/ide/src/interpret.rs | 4 +- .../crates/ide/src/join_lines.rs | 4 +- src/tools/rust-analyzer/crates/ide/src/lib.rs | 13 +-- .../crates/ide/src/matching_brace.rs | 2 +- .../rust-analyzer/crates/ide/src/moniker.rs | 12 +-- .../rust-analyzer/crates/ide/src/move_item.rs | 6 +- .../crates/ide/src/navigation_target.rs | 11 +-- .../crates/ide/src/parent_module.rs | 4 +- .../crates/ide/src/references.rs | 15 ++-- .../rust-analyzer/crates/ide/src/rename.rs | 8 +- .../rust-analyzer/crates/ide/src/runnables.rs | 13 +-- .../crates/ide/src/signature_help.rs | 13 ++- src/tools/rust-analyzer/crates/ide/src/ssr.rs | 6 +- .../crates/ide/src/static_index.rs | 16 ++-- .../rust-analyzer/crates/ide/src/status.rs | 2 +- .../crates/ide/src/syntax_highlighting.rs | 8 +- .../ide/src/syntax_highlighting/format.rs | 8 +- .../ide/src/syntax_highlighting/highlight.rs | 28 ++----- .../ide/src/syntax_highlighting/html.rs | 2 +- .../ide/src/syntax_highlighting/inject.rs | 12 +-- .../ide/src/syntax_highlighting/injector.rs | 6 +- .../ide/src/syntax_highlighting/tests.rs | 6 +- .../crates/ide/src/test_explorer.rs | 4 +- .../rust-analyzer/crates/ide/src/typing.rs | 6 +- .../crates/ide/src/typing/on_enter.rs | 6 +- .../crates/ide/src/view_crate_graph.rs | 2 +- .../rust-analyzer/crates/ide/src/view_hir.rs | 2 +- .../crates/ide/src/view_item_tree.rs | 2 +- .../crates/ide/src/view_memory_layout.rs | 2 +- .../rust-analyzer/crates/ide/src/view_mir.rs | 2 +- .../crates/ide/src/view_syntax_tree.rs | 4 +- .../rust-analyzer/crates/intern/src/lib.rs | 4 +- .../rust-analyzer/crates/intern/src/symbol.rs | 6 +- .../crates/intern/src/symbol/symbols.rs | 2 +- .../crates/load-cargo/src/lib.rs | 17 ++-- .../rust-analyzer/crates/mbe/src/benchmark.rs | 11 +-- .../rust-analyzer/crates/mbe/src/expander.rs | 2 +- .../crates/mbe/src/expander/matcher.rs | 8 +- .../crates/mbe/src/expander/transcriber.rs | 11 ++- src/tools/rust-analyzer/crates/mbe/src/lib.rs | 2 +- .../rust-analyzer/crates/mbe/src/parser.rs | 14 ++-- .../rust-analyzer/crates/parser/src/event.rs | 2 +- .../crates/parser/src/grammar.rs | 4 +- .../crates/parser/src/grammar/expressions.rs | 2 +- .../rust-analyzer/crates/parser/src/parser.rs | 6 +- .../rust-analyzer/crates/paths/src/lib.rs | 4 +- .../proc-macro-api/src/legacy_protocol/msg.rs | 4 +- .../crates/proc-macro-api/src/lib.rs | 8 +- .../crates/proc-macro-api/src/process.rs | 8 +- .../crates/proc-macro-srv-cli/src/main.rs | 4 +- .../proc-macro-srv-cli/src/main_loop.rs | 4 +- .../crates/proc-macro-srv/src/dylib.rs | 2 +- .../crates/proc-macro-srv/src/lib.rs | 2 +- .../crates/proc-macro-srv/src/proc_macros.rs | 2 +- .../src/server_impl/rust_analyzer_span.rs | 4 +- .../src/server_impl/token_id.rs | 2 +- .../src/server_impl/token_stream.rs | 2 +- .../crates/proc-macro-srv/src/tests/utils.rs | 2 +- .../project-model/src/build_dependencies.rs | 6 +- .../project-model/src/cargo_workspace.rs | 2 +- .../crates/project-model/src/env.rs | 2 +- .../crates/project-model/src/lib.rs | 8 +- .../crates/project-model/src/manifest_path.rs | 6 +- .../crates/project-model/src/project_json.rs | 2 +- .../crates/project-model/src/sysroot.rs | 20 ++--- .../crates/project-model/src/tests.rs | 8 +- .../src/toolchain_info/target_data_layout.rs | 2 +- .../src/toolchain_info/target_tuple.rs | 2 +- .../crates/project-model/src/workspace.rs | 10 +-- .../crates/query-group-macro/src/lib.rs | 8 +- .../crates/query-group-macro/src/queries.rs | 4 +- .../crates/rust-analyzer/src/bin/main.rs | 10 ++- .../rust-analyzer/src/cli/analysis_stats.rs | 11 +-- .../rust-analyzer/src/cli/diagnostics.rs | 6 +- .../crates/rust-analyzer/src/cli/lsif.rs | 4 +- .../crates/rust-analyzer/src/cli/run_tests.rs | 6 +- .../rust-analyzer/src/cli/rustc_tests.rs | 6 +- .../crates/rust-analyzer/src/cli/scip.rs | 2 +- .../crates/rust-analyzer/src/cli/ssr.rs | 4 +- .../src/cli/unresolved_references.rs | 10 +-- .../crates/rust-analyzer/src/command.rs | 9 +- .../crates/rust-analyzer/src/config.rs | 10 +-- .../src/config/patch_old_style.rs | 2 +- .../rust-analyzer/src/diagnostics/to_proto.rs | 8 +- .../crates/rust-analyzer/src/flycheck.rs | 2 +- .../crates/rust-analyzer/src/global_state.rs | 8 +- .../rust-analyzer/src/handlers/dispatch.rs | 2 +- .../rust-analyzer/src/handlers/request.rs | 23 +++-- .../src/integrated_benchmarks.rs | 4 +- .../rust-analyzer/src/lsp/capabilities.rs | 2 +- .../crates/rust-analyzer/src/lsp/ext.rs | 6 +- .../rust-analyzer/src/lsp/from_proto.rs | 2 +- .../crates/rust-analyzer/src/lsp/to_proto.rs | 23 ++--- .../crates/rust-analyzer/src/lsp/utils.rs | 2 +- .../crates/rust-analyzer/src/main_loop.rs | 20 +++-- .../crates/rust-analyzer/src/reload.rs | 12 +-- .../crates/rust-analyzer/src/target_spec.rs | 7 +- .../rust-analyzer/src/tracing/config.rs | 6 +- .../crates/rust-analyzer/src/tracing/hprof.rs | 5 +- .../crates/rust-analyzer/src/tracing/json.rs | 4 +- .../rust-analyzer/tests/slow-tests/main.rs | 12 +-- .../rust-analyzer/tests/slow-tests/ratoml.rs | 2 +- .../rust-analyzer/tests/slow-tests/support.rs | 22 ++--- .../rust-analyzer/crates/span/src/ast_id.rs | 2 +- .../rust-analyzer/crates/span/src/map.rs | 4 +- .../rust-analyzer/crates/stdx/src/lib.rs | 6 +- .../rust-analyzer/crates/stdx/src/process.rs | 2 +- .../rust-analyzer/crates/stdx/src/thin_vec.rs | 10 +-- .../crates/stdx/src/thread/pool.rs | 2 +- .../crates/syntax-bridge/src/lib.rs | 9 +- .../src/prettify_macro_expansion.rs | 6 +- .../crates/syntax-bridge/src/tests.rs | 9 +- .../rust-analyzer/crates/syntax/src/algo.rs | 4 +- .../rust-analyzer/crates/syntax/src/ast.rs | 2 +- .../crates/syntax/src/ast/edit.rs | 5 +- .../crates/syntax/src/ast/edit_in_place.rs | 6 +- .../crates/syntax/src/ast/expr_ext.rs | 12 +-- .../crates/syntax/src/ast/make.rs | 19 ++--- .../crates/syntax/src/ast/node_ext.rs | 25 ++---- .../crates/syntax/src/ast/prec.rs | 7 +- .../src/ast/syntax_factory/constructors.rs | 6 +- .../crates/syntax/src/ast/token_ext.rs | 18 ++-- .../crates/syntax/src/ast/traits.rs | 10 +-- .../rust-analyzer/crates/syntax/src/fuzz.rs | 2 +- .../rust-analyzer/crates/syntax/src/hacks.rs | 2 +- .../rust-analyzer/crates/syntax/src/lib.rs | 6 +- .../crates/syntax/src/parsing.rs | 2 +- .../crates/syntax/src/parsing/reparsing.rs | 6 +- .../rust-analyzer/crates/syntax/src/ptr.rs | 4 +- .../crates/syntax/src/syntax_editor.rs | 13 +-- .../syntax/src/syntax_editor/edit_algo.rs | 30 ++++--- .../crates/syntax/src/syntax_editor/edits.rs | 6 +- .../rust-analyzer/crates/syntax/src/ted.rs | 2 +- .../rust-analyzer/crates/syntax/src/tests.rs | 2 +- .../crates/syntax/src/validation.rs | 10 +-- .../crates/syntax/src/validation/block.rs | 2 +- .../crates/test-fixture/src/lib.rs | 8 +- .../crates/vfs-notify/src/lib.rs | 2 +- .../rust-analyzer/crates/vfs/src/file_set.rs | 6 +- src/tools/rust-analyzer/crates/vfs/src/lib.rs | 4 +- .../rust-analyzer/crates/vfs/src/vfs_path.rs | 6 +- .../lib/lsp-server/examples/goto_def.rs | 2 +- .../rust-analyzer/lib/lsp-server/src/lib.rs | 6 +- .../lib/lsp-server/src/socket.rs | 4 +- .../rust-analyzer/lib/lsp-server/src/stdio.rs | 2 +- src/tools/rust-analyzer/xtask/src/codegen.rs | 2 +- .../xtask/src/codegen/assists_doc_tests.rs | 2 +- .../xtask/src/codegen/diagnostics_docs.rs | 2 +- .../xtask/src/codegen/feature_docs.rs | 2 +- .../xtask/src/codegen/grammar.rs | 6 +- .../rust-analyzer/xtask/src/codegen/lints.rs | 4 +- .../xtask/src/codegen/parser_inline_tests.rs | 2 +- src/tools/rust-analyzer/xtask/src/dist.rs | 6 +- src/tools/rust-analyzer/xtask/src/install.rs | 14 +++- src/tools/rust-analyzer/xtask/src/main.rs | 2 +- src/tools/rust-analyzer/xtask/src/metrics.rs | 2 +- src/tools/rust-analyzer/xtask/src/publish.rs | 6 +- src/tools/rust-analyzer/xtask/src/release.rs | 11 +-- .../xtask/src/release/changelog.rs | 12 ++- src/tools/rust-analyzer/xtask/src/tidy.rs | 3 +- 571 files changed, 2182 insertions(+), 2430 deletions(-) diff --git a/src/tools/rust-analyzer/crates/base-db/src/change.rs b/src/tools/rust-analyzer/crates/base-db/src/change.rs index 1f19556a766c2..b5964ff5b4abe 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/change.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/change.rs @@ -82,9 +82,5 @@ impl FileChange { } fn durability(source_root: &SourceRoot) -> Durability { - if source_root.is_library { - Durability::HIGH - } else { - Durability::LOW - } + if source_root.is_library { Durability::HIGH } else { Durability::LOW } } diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index 913dfe6efb770..564697facf6e5 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -10,15 +10,15 @@ use std::hash::BuildHasherDefault; use std::{fmt, mem, ops}; use cfg::{CfgOptions, HashableCfgOptions}; -use dashmap::mapref::entry::Entry; use dashmap::DashMap; +use dashmap::mapref::entry::Entry; use intern::Symbol; use la_arena::{Arena, Idx, RawIdx}; use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; use salsa::{Durability, Setter}; use span::{Edition, EditionedFileId}; use triomphe::Arc; -use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath}; +use vfs::{AbsPathBuf, AnchoredPath, FileId, VfsPath, file_set::FileSet}; use crate::{CrateWorkspaceData, RootQueryDb}; @@ -110,11 +110,7 @@ impl CrateName { /// Dashes are not allowed in the crate names, /// hence the input string is returned as `Err` for those cases. pub fn new(name: &str) -> Result { - if name.contains('-') { - Err(name) - } else { - Ok(Self(Symbol::intern(name))) - } + if name.contains('-') { Err(name) } else { Ok(Self(Symbol::intern(name))) } } /// Creates a crate name, unconditionally replacing the dashes with underscores. @@ -922,15 +918,21 @@ mod tests { None, empty_ws_data(), ); - assert!(graph - .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) - .is_ok()); - assert!(graph - .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate3").unwrap(), crate3,)) - .is_ok()); - assert!(graph - .add_dep(crate3, DependencyBuilder::new(CrateName::new("crate1").unwrap(), crate1,)) - .is_err()); + assert!( + graph + .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) + .is_ok() + ); + assert!( + graph + .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate3").unwrap(), crate3,)) + .is_ok() + ); + assert!( + graph + .add_dep(crate3, DependencyBuilder::new(CrateName::new("crate1").unwrap(), crate1,)) + .is_err() + ); } #[test] @@ -962,12 +964,16 @@ mod tests { None, empty_ws_data(), ); - assert!(graph - .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) - .is_ok()); - assert!(graph - .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) - .is_err()); + assert!( + graph + .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) + .is_ok() + ); + assert!( + graph + .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) + .is_err() + ); } #[test] @@ -1012,12 +1018,16 @@ mod tests { None, empty_ws_data(), ); - assert!(graph - .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) - .is_ok()); - assert!(graph - .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate3").unwrap(), crate3,)) - .is_ok()); + assert!( + graph + .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,)) + .is_ok() + ); + assert!( + graph + .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate3").unwrap(), crate3,)) + .is_ok() + ); } #[test] @@ -1049,15 +1059,17 @@ mod tests { None, empty_ws_data(), ); - assert!(graph - .add_dep( - crate1, - DependencyBuilder::new( - CrateName::normalize_dashes("crate-name-with-dashes"), - crate2, + assert!( + graph + .add_dep( + crate1, + DependencyBuilder::new( + CrateName::normalize_dashes("crate-name-with-dashes"), + crate2, + ) ) - ) - .is_ok()); + .is_ok() + ); assert_eq!( graph.arena[crate1].basic.dependencies, vec![ diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index b733c4d24147e..e6059e9e79058 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -14,15 +14,15 @@ pub use crate::{ SourceRoot, SourceRootId, TargetLayoutLoadResult, UniqueCrateData, }, }; -use dashmap::{mapref::entry::Entry, DashMap}; +use dashmap::{DashMap, mapref::entry::Entry}; pub use query_group::{self}; use rustc_hash::{FxHashSet, FxHasher}; pub use salsa::{self}; use salsa::{Durability, Setter}; pub use semver::{BuildMetadata, Prerelease, Version, VersionReq}; -use syntax::{ast, Parse, SyntaxError}; +use syntax::{Parse, SyntaxError, ast}; use triomphe::Arc; -pub use vfs::{file_set::FileSet, AnchoredPath, AnchoredPathBuf, FileId, VfsPath}; +pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet}; #[macro_export] macro_rules! impl_intern_key { diff --git a/src/tools/rust-analyzer/crates/cfg/src/lib.rs b/src/tools/rust-analyzer/crates/cfg/src/lib.rs index 26860fb932077..8218a81556018 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/lib.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/lib.rs @@ -9,7 +9,7 @@ use std::fmt; use rustc_hash::FxHashSet; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; pub use cfg_expr::{CfgAtom, CfgExpr}; pub use dnf::DnfExpr; diff --git a/src/tools/rust-analyzer/crates/cfg/src/tests.rs b/src/tools/rust-analyzer/crates/cfg/src/tests.rs index 6d87d83ad9300..6766748097f00 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/tests.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/tests.rs @@ -1,10 +1,11 @@ use arbitrary::{Arbitrary, Unstructured}; -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use intern::Symbol; -use syntax::{ast, AstNode, Edition}; +use syntax::{AstNode, Edition, ast}; use syntax_bridge::{ - dummy_test_span_utils::{DummyTestSpanMap, DUMMY}, - syntax_node_to_token_tree, DocCommentDesugarMode, + DocCommentDesugarMode, + dummy_test_span_utils::{DUMMY, DummyTestSpanMap}, + syntax_node_to_token_tree, }; use crate::{CfgAtom, CfgExpr, CfgOptions, DnfExpr}; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 2775e1398c28d..78f26d6756907 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -6,28 +6,28 @@ use base_db::Crate; use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_expand::{ - attrs::{collect_attrs, Attr, AttrId, RawAttrs}, HirFileId, InFile, + attrs::{Attr, AttrId, RawAttrs, collect_attrs}, }; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use la_arena::{ArenaMap, Idx, RawIdx}; use mbe::DelimiterKind; use rustc_abi::ReprOptions; use syntax::{ - ast::{self, HasAttrs}, AstPtr, + ast::{self, HasAttrs}, }; use triomphe::Arc; use tt::iter::{TtElement, TtIter}; use crate::{ + AdtId, AttrDefId, GenericParamId, HasModule, ItemTreeLoc, LocalFieldId, Lookup, MacroId, + VariantId, db::DefDatabase, item_tree::{AttrOwner, FieldParent, ItemTreeNode}, lang_item::LangItem, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource}, - AdtId, AttrDefId, GenericParamId, HasModule, ItemTreeLoc, LocalFieldId, Lookup, MacroId, - VariantId, }; /// Desugared attributes of an item post `cfg_attr` expansion. @@ -770,8 +770,8 @@ mod tests { use hir_expand::span_map::{RealSpanMap, SpanMap}; use span::FileId; - use syntax::{ast, AstNode, TextRange}; - use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode}; + use syntax::{AstNode, TextRange, ast}; + use syntax_bridge::{DocCommentDesugarMode, syntax_node_to_token_tree}; use crate::attr::{DocAtom, DocExpr}; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs b/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs index 14b9af84e6ffb..6ea21356aa41e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs @@ -6,7 +6,7 @@ use std::fmt; use hir_expand::name::{AsName, Name}; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; /// Different signed int types. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum BuiltinInt { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index 1a6bed6cabbdd..b251564016c7e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -4,19 +4,19 @@ pub mod adt; use base_db::Crate; use hir_expand::name::Name; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use la_arena::{Idx, RawIdx}; use triomphe::Arc; use crate::{ + ConstId, ExternCrateId, FunctionId, HasModule, ImplId, ItemContainerId, ItemLoc, Lookup, + Macro2Id, MacroRulesId, ProcMacroId, StaticId, TraitAliasId, TraitId, TypeAliasId, db::DefDatabase, item_tree::{self, FnFlags, ModItem}, - nameres::proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind}, + nameres::proc_macro::{ProcMacroKind, parse_macro_name_and_helper_attrs}, path::ImportAlias, type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap}, visibility::RawVisibility, - ConstId, ExternCrateId, FunctionId, HasModule, ImplId, ItemContainerId, ItemLoc, Lookup, - Macro2Id, MacroRulesId, ProcMacroId, StaticId, TraitAliasId, TraitId, TypeAliasId, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -431,11 +431,7 @@ impl ExternCrateDeclData { Some(krate) } else { krate.data(db).dependencies.iter().find_map(|dep| { - if dep.name.symbol() == name.symbol() { - Some(dep.crate_id) - } else { - None - } + if dep.name.symbol() == name.symbol() { Some(dep.crate_id) } else { None } }) }; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index 9db66d6e91c99..8ea79406531de 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -11,6 +11,7 @@ use rustc_abi::{IntegerType, ReprOptions}; use triomphe::Arc; use crate::{ + EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId, db::DefDatabase, hir::Expr, item_tree::{ @@ -20,7 +21,6 @@ use crate::{ nameres::diagnostics::{DefDiagnostic, DefDiagnostics}, type_ref::{TypeRefId, TypesMap}, visibility::RawVisibility, - EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId, }; /// Note that we use `StructData` for unions as well! diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 108968fe52e2a..58688d5f41280 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -1,40 +1,40 @@ //! Defines database & queries for name resolution. use base_db::{Crate, RootQueryDb, SourceDatabase, Upcast}; use either::Either; -use hir_expand::{db::ExpandDatabase, HirFileId, MacroDefId}; +use hir_expand::{HirFileId, MacroDefId, db::ExpandDatabase}; use intern::sym; use la_arena::ArenaMap; use span::{EditionedFileId, MacroCallId}; -use syntax::{ast, AstPtr}; +use syntax::{AstPtr, ast}; use triomphe::Arc; use crate::{ + AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId, + EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, + ExternCrateLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, + InTypeConstLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc, + MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, + TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, + UseId, UseLoc, VariantId, attr::{Attrs, AttrsWithOwner}, data::{ - adt::{EnumData, EnumVariantData, EnumVariants, StructData, VariantData}, ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData, ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData, + adt::{EnumData, EnumVariantData, EnumVariants, StructData, VariantData}, }, - expr_store::{scope::ExprScopes, Body, BodySourceMap}, + expr_store::{Body, BodySourceMap, scope::ExprScopes}, generics::GenericParams, import_map::ImportMap, item_tree::{AttrOwner, ItemTree, ItemTreeSourceMaps}, lang_item::{self, LangItem, LangItemTarget, LangItems}, nameres::{ + DefMap, LocalDefMap, assoc::{ImplItems, TraitItems}, diagnostics::DefDiagnostics, - DefMap, LocalDefMap, }, tt, type_ref::TypesSourceMap, visibility::{self, Visibility}, - AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId, - EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, - ExternCrateLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, - InTypeConstLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc, - MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, - TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, - UseId, UseLoc, VariantId, }; use salsa::plumbing::AsId; @@ -337,7 +337,7 @@ fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool { for output in segments.skip(1) { match output.flat_tokens() { [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::no_std => { - return true + return true; } _ => {} } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs index 8868bc0cd95bd..b17a2b0a2e2df 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs @@ -27,15 +27,15 @@ pub mod keys { use std::marker::PhantomData; - use hir_expand::{attrs::AttrId, MacroCallId}; + use hir_expand::{MacroCallId, attrs::AttrId}; use rustc_hash::FxHashMap; - use syntax::{ast, AstNode, AstPtr}; + use syntax::{AstNode, AstPtr, ast}; use crate::{ - dyn_map::{DynMap, Policy}, BlockId, ConstId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, FieldId, FunctionId, ImplId, LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId, + dyn_map::{DynMap, Policy}, }; pub type Key = crate::dyn_map::Key, V, AstPtrPolicy>; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs index 343d8aa1c9f10..895b82796794f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs @@ -6,17 +6,17 @@ use base_db::Crate; use cfg::CfgOptions; use drop_bomb::DropBomb; use hir_expand::{ - attrs::RawAttrs, mod_path::ModPath, span_map::SpanMap, ExpandError, ExpandErrorKind, - ExpandResult, HirFileId, InFile, Lookup, MacroCallId, + ExpandError, ExpandErrorKind, ExpandResult, HirFileId, InFile, Lookup, MacroCallId, + attrs::RawAttrs, mod_path::ModPath, span_map::SpanMap, }; use span::{Edition, SyntaxContext}; -use syntax::{ast, Parse}; +use syntax::{Parse, ast}; use triomphe::Arc; use crate::type_ref::{TypesMap, TypesSourceMap}; use crate::{ - attr::Attrs, db::DefDatabase, lower::LowerCtx, path::Path, AsMacroCall, MacroId, ModuleId, - UnresolvedMacro, + AsMacroCall, MacroId, ModuleId, UnresolvedMacro, attr::Attrs, db::DefDatabase, lower::LowerCtx, + path::Path, }; #[derive(Debug)] @@ -84,11 +84,7 @@ impl Expander { } }); - if let Some(err) = unresolved_macro_err { - Err(err) - } else { - Ok(result) - } + if let Some(err) = unresolved_macro_err { Err(err) } else { Ok(result) } } pub fn enter_expand_id( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs index 7e7ccbfa91a74..c9a7566c8dab5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs @@ -12,16 +12,17 @@ use std::ops::{Deref, Index}; use cfg::{CfgExpr, CfgOptions}; use either::Either; -use hir_expand::{name::Name, ExpandError, InFile}; +use hir_expand::{ExpandError, InFile, name::Name}; use la_arena::{Arena, ArenaMap}; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::{Edition, MacroFileId, SyntaxContext}; -use syntax::{ast, AstPtr, SyntaxNodePtr}; +use syntax::{AstPtr, SyntaxNodePtr, ast}; use triomphe::Arc; use tt::TextRange; use crate::{ + BlockId, DefWithBodyId, Lookup, SyntheticSyntax, db::DefDatabase, hir::{ Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, Label, LabelId, Pat, @@ -30,7 +31,6 @@ use crate::{ nameres::DefMap, path::{ModPath, Path}, type_ref::{TypeRef, TypeRefId, TypesMap, TypesSourceMap}, - BlockId, DefWithBodyId, Lookup, SyntheticSyntax, }; pub use self::body::{Body, BodySourceMap}; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/body.rs index 8aca4eb9bc1ef..0295874bd7759 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/body.rs @@ -9,13 +9,13 @@ use syntax::ast; use triomphe::Arc; use crate::{ + DefWithBodyId, HasModule, db::DefDatabase, expander::Expander, - expr_store::{lower, pretty, ExpressionStore, ExpressionStoreSourceMap, SelfParamPtr}, + expr_store::{ExpressionStore, ExpressionStoreSourceMap, SelfParamPtr, lower, pretty}, hir::{BindingId, ExprId, PatId}, item_tree::AttrOwner, src::HasSource, - DefWithBodyId, HasModule, }; /// The body of an item (function, const etc.). diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index b9b00108dcd24..fe1a5e8f29d10 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -8,26 +8,27 @@ use std::mem; use base_db::Crate; use either::Either; use hir_expand::{ + InFile, MacroDefId, mod_path::tool_path, name::{AsName, Name}, span_map::{ExpansionSpanMap, SpanMap}, - InFile, MacroDefId, }; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use rustc_hash::FxHashMap; use span::AstIdMap; use stdx::never; use syntax::{ + AstNode, AstPtr, AstToken as _, SyntaxNodePtr, ast::{ self, ArrayExprKind, AstChildren, BlockExpr, HasArgList, HasAttrs, HasGenericArgs, HasLoopBody, HasName, RangeItem, SlicePatComponents, }, - AstNode, AstPtr, AstToken as _, SyntaxNodePtr, }; use text_size::TextSize; use triomphe::Arc; use crate::{ + AdtId, BlockId, BlockLoc, ConstBlockLoc, DefWithBodyId, MacroId, ModuleDefId, UnresolvedMacro, attr::Attrs, builtin_type::BuiltinUint, data::adt::StructKind, @@ -38,14 +39,14 @@ use crate::{ ExpressionStoreDiagnostics, ExpressionStoreSourceMap, HygieneId, LabelPtr, PatPtr, }, hir::{ + Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind, + Expr, ExprId, Item, Label, LabelId, Literal, MatchArm, Movability, OffsetOf, Pat, PatId, + RecordFieldPat, RecordLitField, Statement, format_args::{ self, FormatAlignment, FormatArgs, FormatArgsPiece, FormatArgument, FormatArgumentKind, FormatArgumentsCollector, FormatCount, FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait, }, - Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind, - Expr, ExprId, Item, Label, LabelId, Literal, MatchArm, Movability, OffsetOf, Pat, PatId, - RecordFieldPat, RecordLitField, Statement, }, item_scope::BuiltinShadowMode, lang_item::LangItem, @@ -53,7 +54,6 @@ use crate::{ nameres::{DefMap, LocalDefMap, MacroSubNs}, path::{GenericArgs, Path}, type_ref::{Mutability, Rawness, TypeRef}, - AdtId, BlockId, BlockLoc, ConstBlockLoc, DefWithBodyId, MacroId, ModuleDefId, UnresolvedMacro, }; type FxIndexSet = indexmap::IndexSet>; @@ -641,11 +641,7 @@ impl ExprCollector<'_> { let expr = self.collect_expr_opt(e.expr()); let raw_tok = e.raw_token().is_some(); let mutability = if raw_tok { - if e.mut_token().is_some() { - Mutability::Mut - } else { - Mutability::Shared - } + if e.mut_token().is_some() { Mutability::Mut } else { Mutability::Shared } } else { Mutability::from_mutable(e.mut_token().is_some()) }; @@ -2041,7 +2037,7 @@ impl ExprCollector<'_> { return match l.kind() { ast::LiteralKind::String(s) => Some((s, true)), _ => None, - } + }; } _ => return None, }; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs index 032c18688ea71..633f976a85ddb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs @@ -3,8 +3,8 @@ use hir_expand::name::Name; use intern::Symbol; use rustc_hash::{FxHashMap, FxHashSet}; use syntax::{ - ast::{self, HasName, IsString}, AstNode, AstPtr, AstToken, T, + ast::{self, HasName, IsString}, }; use tt::TextRange; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs index 42a8eae4064dc..43e11508d8c8b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs @@ -1,13 +1,13 @@ //! Name resolution for expressions. -use hir_expand::{name::Name, MacroDefId}; +use hir_expand::{MacroDefId, name::Name}; use la_arena::{Arena, ArenaMap, Idx, IdxRange, RawIdx}; use triomphe::Arc; use crate::{ + BlockId, ConstBlockId, DefWithBodyId, db::DefDatabase, expr_store::{Body, ExpressionStore, HygieneId}, hir::{Binding, BindingId, Expr, ExprId, Item, LabelId, Pat, PatId, Statement}, - BlockId, ConstBlockId, DefWithBodyId, }; pub type ScopeId = Idx; @@ -325,14 +325,14 @@ fn compute_expr_scopes( #[cfg(test)] mod tests { use base_db::RootQueryDb; - use hir_expand::{name::AsName, InFile}; + use hir_expand::{InFile, name::AsName}; use salsa::AsDynDatabase; use span::FileId; - use syntax::{algo::find_node_at_offset, ast, AstNode}; + use syntax::{AstNode, algo::find_node_at_offset, ast}; use test_fixture::WithFixture; use test_utils::{assert_eq_text, extract_offset}; - use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId}; + use crate::{FunctionId, ModuleDefId, db::DefDatabase, test_db::TestDB}; fn find_function(db: &TestDB, file_id: FileId) -> FunctionId { let krate = db.test_crate(); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs index 7bf27747c464a..a6fcfaa445e3e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs @@ -1,7 +1,7 @@ mod block; -use crate::{hir::MatchArm, test_db::TestDB, ModuleDefId}; -use expect_test::{expect, Expect}; +use crate::{ModuleDefId, hir::MatchArm, test_db::TestDB}; +use expect_test::{Expect, expect}; use la_arena::RawIdx; use test_fixture::WithFixture; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs index 48f31698ddf8e..69c7794327540 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs @@ -4,19 +4,19 @@ use std::{cell::Cell, cmp::Ordering, iter}; use base_db::{Crate, CrateOrigin, LangCrateOrigin}; use hir_expand::{ - name::{AsName, Name}, Lookup, + name::{AsName, Name}, }; use intern::sym; use rustc_hash::FxHashSet; use crate::{ + ImportPathConfig, ModuleDefId, ModuleId, db::DefDatabase, item_scope::ItemInNs, nameres::DefMap, path::{ModPath, PathKind}, visibility::{Visibility, VisibilityExplicitness}, - ImportPathConfig, ModuleDefId, ModuleId, }; /// Find a path that can be used to refer to a certain item. This can depend on @@ -651,7 +651,7 @@ fn find_local_import_locations( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use hir_expand::db::ExpandDatabase; use itertools::Itertools; use span::Edition; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs index 6f1650adeb6fe..ad4a8ba2ed16d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs @@ -7,8 +7,8 @@ use std::{ops, sync::LazyLock}; use either::Either; use hir_expand::{ - name::{AsName, Name}, ExpandResult, + name::{AsName, Name}, }; use intern::sym; use la_arena::{Arena, RawIdx}; @@ -20,6 +20,8 @@ use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds}; use triomphe::Arc; use crate::{ + AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId, + LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId, db::DefDatabase, expander::Expander, item_tree::{AttrOwner, FileItemTreeId, GenericModItem, GenericsItemTreeNode, ItemTree}, @@ -30,8 +32,6 @@ use crate::{ ArrayType, ConstRef, FnType, LifetimeRef, PathId, RefType, TypeBound, TypeRef, TypeRefId, TypesMap, TypesSourceMap, }, - AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId, - LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId, }; /// The index of the self param in the generic of the non-parent definition. @@ -292,11 +292,7 @@ impl GenericParams { parent: GenericDefId, ) -> Option { self.lifetimes.iter().find_map(|(id, p)| { - if &p.name == name { - Some(LifetimeParamId { local_id: id, parent }) - } else { - None - } + if &p.name == name { Some(LifetimeParamId { local_id: id, parent }) } else { None } }) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index 494644d8eff9d..cd22ae6638ece 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -17,7 +17,7 @@ pub mod type_ref; use std::fmt; -use hir_expand::{name::Name, MacroDefId}; +use hir_expand::{MacroDefId, name::Name}; use intern::Symbol; use la_arena::Idx; use rustc_apfloat::ieee::{Half as f16, Quad as f128}; @@ -25,10 +25,10 @@ use syntax::ast; use type_ref::TypeRefId; use crate::{ + BlockId, ConstBlockId, builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, path::{GenericArgs, Path}, type_ref::{Mutability, Rawness}, - BlockId, ConstBlockId, }; pub use syntax::ast::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp}; @@ -137,11 +137,7 @@ pub enum LiteralOrConst { impl Literal { pub fn negate(self) -> Option { - if let Literal::Int(i, k) = self { - Some(Literal::Int(-i, k)) - } else { - None - } + if let Literal::Int(i, k) = self { Some(Literal::Int(-i, k)) } else { None } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index 6331861a992e8..821ec565cff7b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs @@ -7,8 +7,8 @@ use rustc_parse_format as parse; use span::SyntaxContext; use stdx::TupleExt; use syntax::{ - ast::{self, IsString}, TextRange, + ast::{self, IsString}, }; use crate::hir::ExprId; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs index 6de4026dff75b..7bb558d34563e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs @@ -5,25 +5,25 @@ use core::fmt; use std::{fmt::Write, ops::Index}; use hir_expand::{ + AstId, InFile, db::ExpandDatabase, name::{AsName, Name}, - AstId, InFile, }; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use la_arena::{Arena, ArenaMap, Idx}; use span::Edition; -use stdx::thin_vec::{thin_vec_with_header_struct, EmptyOptimizedThinVec, ThinVec}; +use stdx::thin_vec::{EmptyOptimizedThinVec, ThinVec, thin_vec_with_header_struct}; use syntax::{ - ast::{self, HasGenericArgs, HasName, IsString}, AstPtr, + ast::{self, HasGenericArgs, HasName, IsString}, }; use crate::{ + SyntheticSyntax, builtin_type::{BuiltinInt, BuiltinType, BuiltinUint}, hir::Literal, lower::LowerCtx, path::{GenericArg, Path}, - SyntheticSyntax, }; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -34,11 +34,7 @@ pub enum Mutability { impl Mutability { pub fn from_mutable(mutable: bool) -> Mutability { - if mutable { - Mutability::Mut - } else { - Mutability::Shared - } + if mutable { Mutability::Mut } else { Mutability::Shared } } pub fn as_keyword_for_ref(self) -> &'static str { @@ -80,11 +76,7 @@ pub enum Rawness { impl Rawness { pub fn from_raw(is_raw: bool) -> Rawness { - if is_raw { - Rawness::RawPtr - } else { - Rawness::Ref - } + if is_raw { Rawness::RawPtr } else { Rawness::Ref } } pub fn is_raw(&self) -> bool { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs index 9e4479f05b427..717566f9d7960 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs @@ -3,21 +3,21 @@ use std::fmt; use base_db::Crate; -use fst::{raw::IndexedValue, Automaton, Streamer}; +use fst::{Automaton, Streamer, raw::IndexedValue}; use hir_expand::name::Name; use itertools::Itertools; use rustc_hash::FxHashSet; use smallvec::SmallVec; use span::Edition; -use stdx::{format_to, TupleExt}; +use stdx::{TupleExt, format_to}; use triomphe::Arc; use crate::{ + AssocItemId, FxIndexMap, ModuleDefId, ModuleId, TraitId, db::DefDatabase, item_scope::{ImportOrExternCrate, ItemInNs}, nameres::DefMap, visibility::Visibility, - AssocItemId, FxIndexMap, ModuleDefId, ModuleId, TraitId, }; /// Item import details stored in the `ImportMap`. @@ -155,11 +155,7 @@ impl ImportMap { let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| { let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public); - if per_ns.is_none() { - None - } else { - Some((name, per_ns)) - } + if per_ns.is_none() { None } else { Some((name, per_ns)) } }); for (name, per_ns) in visible_items { @@ -474,10 +470,10 @@ fn search_maps( #[cfg(test)] mod tests { use base_db::{RootQueryDb, Upcast}; - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use test_fixture::WithFixture; - use crate::{test_db::TestDB, ItemContainerId, Lookup}; + use crate::{ItemContainerId, Lookup, test_db::TestDB}; use super::*; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index 0c683f3531c95..47ad020043ce0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -4,22 +4,22 @@ use std::sync::LazyLock; use base_db::Crate; -use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId}; +use hir_expand::{AstId, MacroCallId, attrs::AttrId, db::ExpandDatabase, name::Name}; use indexmap::map::Entry; use itertools::Itertools; use la_arena::Idx; use rustc_hash::{FxHashMap, FxHashSet}; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use span::Edition; use stdx::format_to; use syntax::ast; use crate::{ + AdtId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap, HasModule, ImplId, + LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, db::DefDatabase, per_ns::{Item, MacrosItem, PerNs, TypesItem, ValuesItem}, visibility::{Visibility, VisibilityExplicitness}, - AdtId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap, HasModule, ImplId, - LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, }; #[derive(Debug, Default)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index b9fc9c9489bad..ea87b0f70006c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -46,24 +46,24 @@ use std::{ use ast::{AstNode, StructKind}; use base_db::Crate; use either::Either; -use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile}; +use hir_expand::{ExpandTo, HirFileId, InFile, attrs::RawAttrs, name::Name}; use intern::{Interned, Symbol}; use la_arena::{Arena, Idx, RawIdx}; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::never; -use syntax::{ast, match_ast, SyntaxKind}; +use syntax::{SyntaxKind, ast, match_ast}; use triomphe::Arc; use crate::{ + BlockId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, attr::Attrs, db::DefDatabase, generics::GenericParams, path::{GenericArgs, ImportAlias, ModPath, Path, PathKind}, type_ref::{Mutability, TraitRef, TypeBound, TypeRefId, TypesMap, TypesSourceMap}, visibility::{RawVisibility, VisibilityExplicitness}, - BlockId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, }; #[derive(Copy, Clone, Eq, PartialEq)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 3c85d5bacb459..776ee98f3bce2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -3,23 +3,24 @@ use std::{cell::OnceCell, collections::hash_map::Entry}; use hir_expand::{ + HirFileId, mod_path::path, name::AsName, span_map::{SpanMap, SpanMapRef}, - HirFileId, }; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use la_arena::Arena; use rustc_hash::FxHashMap; use span::{AstIdMap, SyntaxContext}; use stdx::thin_vec::ThinVec; use syntax::{ - ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString}, AstNode, + ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString}, }; use triomphe::Arc; use crate::{ + LocalLifetimeParamId, LocalTypeOrConstParamId, db::DefDatabase, generics::{GenericParams, GenericParamsCollector}, item_tree::{ @@ -38,7 +39,6 @@ use crate::{ TypesMap, TypesSourceMap, }, visibility::RawVisibility, - LocalLifetimeParamId, LocalTypeOrConstParamId, }; fn id(index: Idx) -> FileItemTreeId { @@ -931,8 +931,7 @@ impl<'a> Ctx<'a> { fn desugar_future_path(ctx: &mut LowerCtx<'_>, orig: TypeRefId) -> PathId { let path = path![core::future::Future]; - let mut generic_args: Vec<_> = - std::iter::repeat_n(None, path.segments().len() - 1).collect(); + let mut generic_args: Vec<_> = std::iter::repeat_n(None, path.segments().len() - 1).collect(); let binding = AssociatedTypeBinding { name: Name::new_symbol_root(sym::Output.clone()), args: None, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs index b442e877343fc..47d374a2beeee 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs @@ -1,4 +1,4 @@ -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use span::Edition; use test_fixture::WithFixture; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 67788576c13bc..342c3fedb9608 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -3,13 +3,13 @@ //! This attribute to tell the compiler about semi built-in std library //! features, such as Fn family of traits. use hir_expand::name::Name; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use rustc_hash::FxHashMap; use triomphe::Arc; use crate::{ - db::DefDatabase, path::Path, AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId, - FunctionId, ImplId, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, UnionId, + AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId, FunctionId, ImplId, ModuleDefId, + StaticId, StructId, TraitId, TypeAliasId, UnionId, db::DefDatabase, path::Path, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -164,11 +164,7 @@ impl LangItems { } } - if lang_items.items.is_empty() { - None - } else { - Some(Arc::new(lang_items)) - } + if lang_items.items.is_empty() { None } else { Some(Arc::new(lang_items)) } } /// Salsa query. Look for a lang item, starting from the specified crate and recursively @@ -230,11 +226,7 @@ pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option } } - if traits.is_empty() { - None - } else { - Some(traits.into_iter().collect()) - } + if traits.is_empty() { None } else { Some(traits.into_iter().collect()) } } pub enum GenericRequirement { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 209ed46b7a85f..615bd33feb6fa 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -71,25 +71,25 @@ mod test_db; use std::hash::{Hash, Hasher}; -use base_db::{impl_intern_key, Crate}; +use base_db::{Crate, impl_intern_key}; use hir_expand::{ + AstId, ExpandError, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, + MacroDefId, MacroDefKind, builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander}, db::ExpandDatabase, eager::expand_eager_macro_input, impl_intern_lookup, name::Name, proc_macro::{CustomProcMacroExpander, ProcMacroKind}, - AstId, ExpandError, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, - MacroDefId, MacroDefKind, }; use item_tree::ExternBlock; use la_arena::Idx; use nameres::DefMap; use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::impl_from; -use syntax::{ast, AstNode}; +use syntax::{AstNode, ast}; -pub use hir_expand::{tt, Intern, Lookup}; +pub use hir_expand::{Intern, Lookup, tt}; use crate::{ builtin_type::BuiltinType, @@ -438,11 +438,7 @@ impl ModuleId { let def_map = self.def_map(db); let parent = def_map[self.local_id].parent?; def_map[parent].children.iter().find_map(|(name, module_id)| { - if *module_id == self.local_id { - Some(name.clone()) - } else { - None - } + if *module_id == self.local_id { Some(name.clone()) } else { None } }) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs index 7cddd48eb174c..c0f6e1a6867ce 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs @@ -1,7 +1,7 @@ //! Context for lowering paths. use std::{cell::OnceCell, mem}; -use hir_expand::{span_map::SpanMap, AstId, HirFileId, InFile}; +use hir_expand::{AstId, HirFileId, InFile, span_map::SpanMap}; use span::{AstIdMap, AstIdNode, Edition, EditionedFileId, FileId, RealSpanMap}; use stdx::thin_vec::ThinVec; use syntax::ast; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs index 70b512c014b94..d9fbf4b17c5d8 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -19,10 +19,10 @@ use std::{iter, ops::Range, sync}; use base_db::RootQueryDb; use expect_test::Expect; use hir_expand::{ + InFile, MacroCallKind, MacroFileId, MacroFileIdExt, MacroKind, db::ExpandDatabase, proc_macro::{ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind}, span_map::SpanMapRef, - InFile, MacroCallKind, MacroFileId, MacroFileIdExt, MacroKind, }; use intern::Symbol; use itertools::Itertools; @@ -30,21 +30,21 @@ use salsa::AsDynDatabase; use span::{Edition, Span}; use stdx::{format_to, format_to_acc}; use syntax::{ - ast::{self, edit::IndentLevel}, AstNode, SyntaxKind::{COMMENT, EOF, IDENT, LIFETIME_IDENT}, SyntaxNode, T, + ast::{self, edit::IndentLevel}, }; use test_fixture::WithFixture; use crate::{ + AdtId, AsMacroCall, Lookup, ModuleDefId, db::DefDatabase, nameres::{DefMap, MacroSubNs, ModuleSource}, resolver::HasResolver, src::HasSource, test_db::TestDB, tt::TopSubtree, - AdtId, AsMacroCall, Lookup, ModuleDefId, }; #[track_caller] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index a34766ebc1dca..12293f3a6171e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -62,7 +62,7 @@ use std::ops::Deref; use base_db::Crate; use hir_expand::{ - name::Name, proc_macro::ProcMacroKind, ErasedAstId, HirFileId, InFile, MacroCallId, MacroDefId, + ErasedAstId, HirFileId, InFile, MacroCallId, MacroDefId, name::Name, proc_macro::ProcMacroKind, }; use intern::Symbol; use itertools::Itertools; @@ -70,11 +70,13 @@ use la_arena::Arena; use rustc_hash::{FxHashMap, FxHashSet}; use span::{Edition, EditionedFileId, FileAstId, FileId, ROOT_ERASED_FILE_AST_ID}; use stdx::format_to; -use syntax::{ast, AstNode, SmolStr, SyntaxNode, ToSmolStr}; +use syntax::{AstNode, SmolStr, SyntaxNode, ToSmolStr, ast}; use triomphe::Arc; use tt::TextRange; use crate::{ + AstId, BlockId, BlockLoc, CrateRootModuleId, EnumId, EnumVariantId, ExternCrateId, FunctionId, + FxIndexMap, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, db::DefDatabase, item_scope::{BuiltinShadowMode, ItemScope}, item_tree::{ItemTreeId, Mod, TreeId}, @@ -82,8 +84,6 @@ use crate::{ path::ModPath, per_ns::PerNs, visibility::{Visibility, VisibilityExplicitness}, - AstId, BlockId, BlockLoc, CrateRootModuleId, EnumId, EnumVariantId, ExternCrateId, FunctionId, - FxIndexMap, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, }; pub use self::path_resolution::ResolvePathResultPrefixInfo; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs index dea6d334f8aa6..1b3d10f098b4a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs @@ -1,25 +1,25 @@ //! Expansion of associated items use hir_expand::{ - name::Name, AstId, ExpandResult, InFile, Intern, Lookup, MacroCallKind, MacroDefKind, + AstId, ExpandResult, InFile, Intern, Lookup, MacroCallKind, MacroDefKind, name::Name, }; use smallvec::SmallVec; use span::{HirFileId, MacroCallId}; -use syntax::{ast, Parse}; +use syntax::{Parse, ast}; use triomphe::Arc; use crate::{ + AssocItemId, AstIdWithPath, ConstLoc, FunctionId, FunctionLoc, ImplId, ItemContainerId, + ItemLoc, ModuleId, TraitId, TypeAliasId, TypeAliasLoc, db::DefDatabase, expander::{Expander, Mark}, item_tree::{self, AssocItem, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId}, macro_call_as_call_id, nameres::{ + DefMap, LocalDefMap, MacroSubNs, attr_resolution::ResolvedAttr, diagnostics::{DefDiagnostic, DefDiagnostics}, - DefMap, LocalDefMap, MacroSubNs, }, - AssocItemId, AstIdWithPath, ConstLoc, FunctionId, FunctionLoc, ImplId, ItemContainerId, - ItemLoc, ModuleId, TraitId, TypeAliasId, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs index c35a7fdc96d2a..7820c6fcbe311 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs @@ -2,20 +2,20 @@ use base_db::Crate; use hir_expand::{ + MacroCallId, MacroCallKind, MacroDefId, attrs::{Attr, AttrId, AttrInput}, inert_attr_macro::find_builtin_attr_idx, - MacroCallId, MacroCallKind, MacroDefId, }; use span::SyntaxContext; use syntax::ast; use triomphe::Arc; use crate::{ + AstIdWithPath, LocalModuleId, MacroId, UnresolvedMacro, db::DefDatabase, item_scope::BuiltinShadowMode, - nameres::{path_resolution::ResolveMode, LocalDefMap}, + nameres::{LocalDefMap, path_resolution::ResolveMode}, path::{self, ModPath, PathKind}, - AstIdWithPath, LocalModuleId, MacroId, UnresolvedMacro, }; use super::{DefMap, MacroSubNs}; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 43b011e57f46a..045a8695407b7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -9,15 +9,15 @@ use base_db::{BuiltDependency, Crate, CrateOrigin, LangCrateOrigin}; use cfg::{CfgAtom, CfgExpr, CfgOptions}; use either::Either; use hir_expand::{ + ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, + MacroFileIdExt, attrs::{Attr, AttrId}, builtin::{find_builtin_attr, find_builtin_derive, find_builtin_macro}, name::{AsName, Name}, proc_macro::CustomProcMacroExpander, - ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, - MacroFileIdExt, }; -use intern::{sym, Interned}; -use itertools::{izip, Itertools}; +use intern::{Interned, sym}; +use itertools::{Itertools, izip}; use la_arena::Idx; use rustc_hash::{FxHashMap, FxHashSet}; use span::{Edition, EditionedFileId, FileAstId, SyntaxContext}; @@ -25,6 +25,12 @@ use syntax::ast; use triomphe::Arc; use crate::{ + AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantLoc, + ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, + ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId, + MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId, + ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, + UnresolvedMacro, UseId, UseLoc, attr::Attrs, db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, @@ -34,24 +40,18 @@ use crate::{ }, macro_call_as_call_id, macro_call_as_call_id_with_eager, nameres::{ + BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode, attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id}, diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, - proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind}, - sub_namespace_match, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, - ModuleOrigin, ResolveMode, + proc_macro::{ProcMacroDef, ProcMacroKind, parse_macro_name_and_helper_attrs}, + sub_namespace_match, }, path::{ImportAlias, ModPath, PathKind}, per_ns::{Item, PerNs}, tt, visibility::{RawVisibility, Visibility}, - AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantLoc, - ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, - ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId, - MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId, - ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, - UnresolvedMacro, UseId, UseLoc, }; const GLOB_RECURSION_LIMIT: usize = 100; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs index bc1617c55b029..1744d3465b272 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs @@ -3,15 +3,15 @@ use std::ops::Not; use cfg::{CfgExpr, CfgOptions}; -use hir_expand::{attrs::AttrId, ExpandErrorKind, MacroCallKind}; +use hir_expand::{ExpandErrorKind, MacroCallKind, attrs::AttrId}; use la_arena::Idx; use syntax::ast; use crate::{ + AstId, item_tree::{self, AttrOwner, ItemTreeId, TreeId}, nameres::LocalModuleId, path::ModPath, - AstId, }; #[derive(Debug, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs index a012eb6ff7eb9..97db89d1e7661 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs @@ -1,10 +1,10 @@ //! This module resolves `mod foo;` declaration to file. use arrayvec::ArrayVec; use base_db::{AnchoredPath, RootQueryDb}; -use hir_expand::{name::Name, HirFileIdExt}; +use hir_expand::{HirFileIdExt, name::Name}; use span::EditionedFileId; -use crate::{db::DefDatabase, HirFileId}; +use crate::{HirFileId, db::DefDatabase}; const MOD_DEPTH_LIMIT: usize = 32; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs index 977bc16adf7ee..e7cb91300b58d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs @@ -11,19 +11,19 @@ //! `ReachedFixedPoint` signals about this. use either::Either; -use hir_expand::{name::Name, Lookup}; +use hir_expand::{Lookup, name::Name}; use span::Edition; use triomphe::Arc; use crate::{ + AdtId, LocalModuleId, ModuleDefId, db::DefDatabase, - item_scope::{ImportOrExternCrate, BUILTIN_SCOPE}, + item_scope::{BUILTIN_SCOPE, ImportOrExternCrate}, item_tree::FieldsShape, - nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs}, + nameres::{BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, sub_namespace_match}, path::{ModPath, PathKind}, per_ns::PerNs, visibility::{RawVisibility, Visibility}, - AdtId, LocalModuleId, ModuleDefId, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -356,7 +356,7 @@ impl DefMap { PathKind::Abs => match self.resolve_path_abs(local_def_map, &mut segments, path) { Either::Left(it) => it, Either::Right(reached_fixed_point) => { - return ResolvePathResult::empty(reached_fixed_point) + return ResolvePathResult::empty(reached_fixed_point); } }, }; @@ -402,11 +402,11 @@ impl DefMap { PathKind::Abs => match self.resolve_path_abs(local_def_map, &mut segments, path) { Either::Left(it) => it, Either::Right(reached_fixed_point) => { - return ResolvePathResult::empty(reached_fixed_point) + return ResolvePathResult::empty(reached_fixed_point); } }, PathKind::DollarCrate(_) | PathKind::Crate | PathKind::Super(_) => { - return ResolvePathResult::empty(ReachedFixedPoint::Yes) + return ResolvePathResult::empty(ReachedFixedPoint::Yes); } }; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs index 7c9fad91865db..3fd095a9a98a8 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs @@ -5,7 +5,7 @@ mod mod_resolution; mod primitives; use base_db::RootQueryDb; -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use test_fixture::WithFixture; use triomphe::Arc; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs index 9a601e0f01384..bd25d0bd58588 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs @@ -7,7 +7,7 @@ use span::Edition; use test_fixture::WithFixture; use triomphe::Arc; -use crate::{db::DefDatabase, nameres::tests::TestDB, AdtId, ModuleDefId}; +use crate::{AdtId, ModuleDefId, db::DefDatabase, nameres::tests::TestDB}; fn check_def_map_is_not_recomputed(ra_fixture_initial: &str, ra_fixture_change: &str) { let (mut db, pos) = TestDB::with_position(ra_fixture_initial); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/path.rs index 713e7389736a0..ec2c8d12aad64 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path.rs @@ -19,7 +19,7 @@ use span::Edition; use stdx::thin_vec::thin_vec_with_header_struct; use syntax::ast; -pub use hir_expand::mod_path::{path, ModPath, PathKind}; +pub use hir_expand::mod_path::{ModPath, PathKind, path}; pub use lower::hir_segment_to_ast_segment; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs index 7a6d6973298b7..ef0ef0e82363b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs @@ -8,7 +8,7 @@ use hir_expand::{ mod_path::resolve_crate_root, name::{AsName, Name}, }; -use intern::{sym, Interned}; +use intern::{Interned, sym}; use stdx::thin_vec::EmptyOptimizedThinVec; use syntax::ast::{self, AstNode, HasGenericArgs, HasTypeBounds}; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/tests.rs index 67a27bf85e89c..c0bfb0c872178 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path/tests.rs @@ -1,4 +1,4 @@ -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use span::Edition; use syntax::ast::{self, make}; use test_fixture::WithFixture; @@ -6,8 +6,8 @@ use test_fixture::WithFixture; use crate::{ lower::LowerCtx, path::{ - lower::{hir_segment_to_ast_segment, SEGMENT_LOWERING_MAP}, Path, + lower::{SEGMENT_LOWERING_MAP, hir_segment_to_ast_segment}, }, pretty, test_db::TestDB, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs b/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs index c2d3f67f17e77..1f7dd6f0c4075 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs @@ -6,9 +6,9 @@ use bitflags::bitflags; use crate::{ + MacroId, ModuleDefId, item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob, ItemInNs}, visibility::Visibility, - MacroId, ModuleDefId, }; #[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] @@ -146,11 +146,7 @@ impl PerNs { } pub fn or_else(self, f: impl FnOnce() -> PerNs) -> PerNs { - if self.is_full() { - self - } else { - self.or(f()) - } + if self.is_full() { self } else { self.or(f()) } } pub fn iter_items(self) -> impl Iterator)> { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 997a12a328e10..28ebaadf4d79e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -2,36 +2,36 @@ use std::{fmt, iter, mem}; use base_db::Crate; -use hir_expand::{name::Name, MacroDefId}; -use intern::{sym, Symbol}; +use hir_expand::{MacroDefId, name::Name}; +use intern::{Symbol, sym}; use itertools::Itertools as _; use rustc_hash::FxHashSet; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use span::SyntaxContext; use triomphe::Arc; use crate::{ + AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, + ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId, GenericParamId, HasModule, + ImplId, ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, + MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, + TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId, builtin_type::BuiltinType, data::ExternCrateDeclData, db::DefDatabase, expr_store::{ - scope::{ExprScopes, ScopeId}, HygieneId, + scope::{ExprScopes, ScopeId}, }, generics::{GenericParams, TypeOrConstParamData}, hir::{BindingId, ExprId, LabelId}, - item_scope::{BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, BUILTIN_SCOPE}, + item_scope::{BUILTIN_SCOPE, BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob}, lang_item::LangItemTarget, nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo}, path::{ModPath, Path, PathKind}, per_ns::PerNs, type_ref::{LifetimeRef, TypesMap}, visibility::{RawVisibility, Visibility}, - AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, - ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId, GenericParamId, HasModule, - ImplId, ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, - MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, - TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId, }; #[derive(Debug, Clone)] @@ -209,11 +209,7 @@ impl Resolver { } let remaining_idx = || { - if path.segments().len() == 1 { - None - } else { - Some(1) - } + if path.segments().len() == 1 { None } else { Some(1) } }; for scope in self.scopes() { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/src.rs b/src/tools/rust-analyzer/crates/hir-def/src/src.rs index 347c4803be1cc..3867f39b8b173 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/src.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/src.rs @@ -3,13 +3,13 @@ use either::Either; use hir_expand::InFile; use la_arena::ArenaMap; -use syntax::{ast, AstNode, AstPtr}; +use syntax::{AstNode, AstPtr, ast}; use crate::{ - db::DefDatabase, - item_tree::{AttrOwner, FieldParent, ItemTreeNode}, GenericDefId, ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, UseId, VariantId, + db::DefDatabase, + item_tree::{AttrOwner, FieldParent, ItemTreeNode}, }; pub trait HasSource { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs index 0b97e6c9ce5b9..91cadb0e81046 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs @@ -6,17 +6,17 @@ use base_db::{ Crate, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, Upcast, }; -use hir_expand::{db::ExpandDatabase, files::FilePosition, InFile}; +use hir_expand::{InFile, db::ExpandDatabase, files::FilePosition}; use salsa::{AsDynDatabase, Durability}; use span::{EditionedFileId, FileId}; -use syntax::{algo, ast, AstNode}; +use syntax::{AstNode, algo, ast}; use triomphe::Arc; use crate::{ + LocalModuleId, Lookup, ModuleDefId, ModuleId, db::DefDatabase, nameres::{DefMap, ModuleSource}, src::HasSource, - LocalModuleId, Lookup, ModuleDefId, ModuleId, }; #[salsa::db] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs index 86a2d02a9f46e..f4729a4f8e0dc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs @@ -9,11 +9,11 @@ use syntax::ast; use triomphe::Arc; use crate::{ + ConstId, FunctionId, HasModule, LocalFieldId, LocalModuleId, ModuleId, VariantId, db::DefDatabase, nameres::DefMap, path::{ModPath, PathKind}, resolver::HasResolver, - ConstId, FunctionId, HasModule, LocalFieldId, LocalModuleId, ModuleId, VariantId, }; /// Visibility of an item, not yet resolved. diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index 6bfef1d28b720..862e3c7305f5d 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -4,23 +4,23 @@ use std::{borrow::Cow, fmt, ops}; use base_db::Crate; use cfg::CfgExpr; use either::Either; -use intern::{sym, Interned, Symbol}; +use intern::{Interned, Symbol, sym}; use mbe::{DelimiterKind, Punct}; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use span::{Span, SyntaxContext}; use syntax::unescape; -use syntax::{ast, match_ast, AstNode, AstToken, SyntaxNode}; -use syntax_bridge::{desugar_doc_comment_text, syntax_node_to_token_tree, DocCommentDesugarMode}; +use syntax::{AstNode, AstToken, SyntaxNode, ast, match_ast}; +use syntax_bridge::{DocCommentDesugarMode, desugar_doc_comment_text, syntax_node_to_token_tree}; use triomphe::ThinArc; use crate::name::Name; use crate::{ + InFile, db::ExpandDatabase, mod_path::ModPath, span_map::SpanMapRef, - tt::{self, token_to_literal, TopSubtree}, - InFile, + tt::{self, TopSubtree, token_to_literal}, }; /// Syntactical attributes, without filtering of `cfg_attr`s. diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs index 7b9b7f36e2cdb..0bf4943b60cec 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs @@ -7,9 +7,9 @@ mod derive_macro; mod fn_macro; pub use self::{ - attr_macro::{find_builtin_attr, pseudo_derive_attr_expansion, BuiltinAttrExpander}, - derive_macro::{find_builtin_derive, BuiltinDeriveExpander}, + attr_macro::{BuiltinAttrExpander, find_builtin_attr, pseudo_derive_attr_expansion}, + derive_macro::{BuiltinDeriveExpander, find_builtin_derive}, fn_macro::{ - find_builtin_macro, include_input_to_file_id, BuiltinFnLikeExpander, EagerExpander, + BuiltinFnLikeExpander, EagerExpander, find_builtin_macro, include_input_to_file_id, }, }; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs index e9dc17a28f688..0463ce11f6791 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs @@ -2,7 +2,7 @@ use intern::sym; use span::{MacroCallId, Span}; -use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallKind}; +use crate::{ExpandResult, MacroCallKind, db::ExpandDatabase, name, tt}; use super::quote; @@ -130,7 +130,7 @@ fn derive_expand( return ExpandResult::ok(tt::TopSubtree::empty(tt::DelimSpan { open: span, close: span, - })) + })); } }; pseudo_derive_attr_expansion(tt, derives, span) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs index 149ab73ec5477..b6181e8ce8c90 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs @@ -1,7 +1,7 @@ //! Builtin derives. use intern::sym; -use itertools::{izip, Itertools}; +use itertools::{Itertools, izip}; use parser::SyntaxKind; use rustc_hash::FxHashSet; use span::{Edition, MacroCallId, Span, SyntaxContext}; @@ -10,17 +10,18 @@ use syntax_bridge::DocCommentDesugarMode; use tracing::debug; use crate::{ + ExpandError, ExpandResult, builtin::quote::{dollar_crate, quote}, db::ExpandDatabase, hygiene::span_with_def_site_ctxt, name::{self, AsName, Name}, span_map::ExpansionSpanMap, - tt, ExpandError, ExpandResult, + tt, }; use syntax::{ ast::{ - self, edit_in_place::GenericParamsOwnerEdit, make, AstNode, FieldList, HasAttrs, - HasGenericArgs, HasGenericParams, HasModuleItem, HasName, HasTypeBounds, + self, AstNode, FieldList, HasAttrs, HasGenericArgs, HasGenericParams, HasModuleItem, + HasName, HasTypeBounds, edit_in_place::GenericParamsOwnerEdit, make, }, ted, }; @@ -464,7 +465,7 @@ fn expand_simple_derive( return ExpandResult::new( tt::TopSubtree::empty(tt::DelimSpan { open: invoc_span, close: invoc_span }), e, - ) + ); } }; ExpandResult::ok(expand_simple_derive_with_parsed( @@ -1072,7 +1073,7 @@ fn coerce_pointee_expand( "exactly one generic type parameter must be marked \ as `#[pointee]` to derive `CoercePointee` traits", ), - ) + ); } (Some(_), Some(_)) => { return ExpandResult::new( @@ -1082,7 +1083,7 @@ fn coerce_pointee_expand( "only one type parameter can be marked as `#[pointee]` \ when deriving `CoercePointee` traits", ), - ) + ); } } }; @@ -1120,7 +1121,9 @@ fn coerce_pointee_expand( tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), ExpandError::other( span, - format!("`derive(CoercePointee)` requires `{pointee_param_name}` to be marked `?Sized`"), + format!( + "`derive(CoercePointee)` requires `{pointee_param_name}` to be marked `?Sized`" + ), ), ); } @@ -1335,7 +1338,7 @@ fn coerce_pointee_expand( let info = match parse_adt_from_syntax(&adt, &span_map, span) { Ok(it) => it, Err(err) => { - return ExpandResult::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), err) + return ExpandResult::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), err); } }; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs index 2fb1f96350cd5..e83d9abf83b79 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs @@ -4,26 +4,26 @@ use base_db::AnchoredPath; use cfg::CfgExpr; use either::Either; use intern::{ - sym::{self}, Symbol, + sym::{self}, }; -use mbe::{expect_fragment, DelimiterKind}; +use mbe::{DelimiterKind, expect_fragment}; use span::{Edition, EditionedFileId, FileId, Span}; use stdx::format_to; use syntax::{ format_smolstr, - unescape::{unescape_byte, unescape_char, unescape_unicode, Mode}, + unescape::{Mode, unescape_byte, unescape_char, unescape_unicode}, }; use syntax_bridge::syntax_node_to_token_tree; use crate::{ - builtin::quote::{dollar_crate, quote, WithDelimiter}, + ExpandError, ExpandResult, HirFileIdExt, Lookup as _, MacroCallId, + builtin::quote::{WithDelimiter, dollar_crate, quote}, db::ExpandDatabase, hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt}, name, span_map::SpanMap, tt::{self, DelimSpan, TtElement, TtIter}, - ExpandError, ExpandResult, HirFileIdExt, Lookup as _, MacroCallId, }; macro_rules! register_builtin { @@ -427,12 +427,15 @@ fn compile_error_expand( span: Span, ) -> ExpandResult { let err = match &*tt.0 { - [_, tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { - symbol: text, - span: _, - kind: tt::LitKind::Str | tt::LitKind::StrRaw(_), - suffix: _, - }))] => ExpandError::other(span, Box::from(unescape_str(text).as_str())), + [ + _, + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + symbol: text, + span: _, + kind: tt::LitKind::Str | tt::LitKind::StrRaw(_), + suffix: _, + })), + ] => ExpandError::other(span, Box::from(unescape_str(text).as_str())), _ => ExpandError::other(span, "`compile_error!` argument must be a string"), }; @@ -736,7 +739,7 @@ fn include_expand( return ExpandResult::new( tt::TopSubtree::empty(DelimSpan { open: span, close: span }), e, - ) + ); } }; let span_map = db.real_span_map(editioned_file_id); @@ -789,7 +792,7 @@ fn include_str_expand( return ExpandResult::new( tt::TopSubtree::empty(DelimSpan { open: span, close: span }), e, - ) + ); } }; @@ -827,7 +830,7 @@ fn env_expand( return ExpandResult::new( tt::TopSubtree::empty(DelimSpan { open: span, close: span }), e, - ) + ); } }; @@ -865,7 +868,7 @@ fn option_env_expand( return ExpandResult::new( tt::TopSubtree::empty(DelimSpan { open: call_site, close: call_site }), e, - ) + ); } }; let dollar_crate = dollar_crate(call_site); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs index 9dd2b77b525c4..859f6f7b1449d 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs @@ -1,7 +1,7 @@ //! A simplified version of quote-crate like quasi quote macro #![allow(clippy::crate_in_macro_def)] -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use span::Span; use syntax::ToSmolStr; use tt::IdentIsRaw; @@ -226,7 +226,7 @@ mod tests { use ::tt::IdentIsRaw; use expect_test::expect; use intern::Symbol; - use span::{Edition, SpanAnchor, SyntaxContext, ROOT_ERASED_FILE_AST_ID}; + use span::{Edition, ROOT_ERASED_FILE_AST_ID, SpanAnchor, SyntaxContext}; use syntax::{TextRange, TextSize}; use super::quote; @@ -324,6 +324,9 @@ mod tests { } }; - assert_eq!(quoted.to_string(), "impl Clone for Foo {fn clone (& self) -> Self {Self {name : self . name . clone () , id : self . id . clone () ,}}}"); + assert_eq!( + quoted.to_string(), + "impl Clone for Foo {fn clone (& self) -> Self {Self {name : self . name . clone () , id : self . id . clone () ,}}}" + ); } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs index 0ceab3c890217..c6ea4a3a33db8 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs @@ -3,15 +3,15 @@ use std::iter::Peekable; use base_db::Crate; use cfg::{CfgAtom, CfgExpr}; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use rustc_hash::FxHashSet; use syntax::{ - ast::{self, Attr, HasAttrs, Meta, TokenTree, VariantList}, AstNode, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, T, + ast::{self, Attr, HasAttrs, Meta, TokenTree, VariantList}, }; use tracing::{debug, warn}; -use crate::{db::ExpandDatabase, proc_macro::ProcMacroKind, MacroCallLoc, MacroDefKind}; +use crate::{MacroCallLoc, MacroDefKind, db::ExpandDatabase, proc_macro::ProcMacroKind}; fn check_cfg(db: &dyn ExpandDatabase, attr: &Attr, krate: Crate) -> Option { if !attr.simple_name().as_deref().map(|v| v == "cfg")? { @@ -344,8 +344,8 @@ where #[cfg(test)] mod tests { use cfg::DnfExpr; - use expect_test::{expect, Expect}; - use syntax::{ast::Attr, AstNode, SourceFile}; + use expect_test::{Expect, expect}; + use syntax::{AstNode, SourceFile, ast::Attr}; use crate::cfg_process::parse_from_attr_token_tree; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 85c242a790fc9..2fe251d298907 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -9,25 +9,26 @@ use span::{ AstIdMap, Edition, EditionedFileId, HirFileId, HirFileIdRepr, MacroCallId, MacroFileId, Span, SyntaxContext, }; -use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T}; -use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode}; +use syntax::{AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T, ast}; +use syntax_bridge::{DocCommentDesugarMode, syntax_node_to_token_tree}; use triomphe::Arc; use crate::{ - attrs::{collect_attrs, AttrId}, + AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, + EagerExpander, ExpandError, ExpandResult, ExpandTo, MacroCallKind, MacroCallLoc, MacroDefId, + MacroDefKind, + attrs::{AttrId, collect_attrs}, builtin::pseudo_derive_attr_expansion, cfg_process, declarative::DeclarativeMacroExpander, fixup::{self, SyntaxFixupUndoInfo}, hygiene::{ - span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt, - SyntaxContextExt as _, + SyntaxContextExt as _, span_with_call_site_ctxt, span_with_def_site_ctxt, + span_with_mixed_site_ctxt, }, proc_macro::{CrateProcMacros, CustomProcMacroExpander, ProcMacros}, span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef}, - tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, - EagerExpander, ExpandError, ExpandResult, ExpandTo, MacroCallKind, MacroCallLoc, MacroDefId, - MacroDefKind, + tt, }; /// This is just to ensure the types of smart_macro_arg and macro_arg are the same type MacroArgResult = (Arc, SyntaxFixupUndoInfo, Span); @@ -397,11 +398,7 @@ fn parse_macro_expansion_error( ) -> Option>>> { let e: ExpandResult> = db.parse_macro_expansion(MacroFileId { macro_call_id }).map(|it| Arc::from(it.0.errors())); - if e.value.is_empty() && e.err.is_none() { - None - } else { - Some(Arc::new(e)) - } + if e.value.is_empty() && e.err.is_none() { None } else { Some(Arc::new(e)) } } pub(crate) fn parse_with_map( diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs index a0b614add4974..063410230d438 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs @@ -4,15 +4,16 @@ use base_db::Crate; use intern::sym; use span::{Edition, HirFileIdRepr, MacroCallId, Span, SyntaxContext}; use stdx::TupleExt; -use syntax::{ast, AstNode}; +use syntax::{AstNode, ast}; use syntax_bridge::DocCommentDesugarMode; use triomphe::Arc; use crate::{ + AstId, ExpandError, ExpandErrorKind, ExpandResult, Lookup, attrs::RawAttrs, db::ExpandDatabase, - hygiene::{apply_mark, Transparency}, - tt, AstId, ExpandError, ExpandErrorKind, ExpandResult, Lookup, + hygiene::{Transparency, apply_mark}, + tt, }; /// Old-style `macro_rules` or the new macros 2.0 diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs index fcf3929eaab06..dd824e6fd0408 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs @@ -20,16 +20,16 @@ //! See the full discussion : use base_db::Crate; use span::SyntaxContext; -use syntax::{ted, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent}; +use syntax::{Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent, ted}; use syntax_bridge::DocCommentDesugarMode; use triomphe::Arc; use crate::{ + AstId, EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, + MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, ast::{self, AstNode}, db::ExpandDatabase, mod_path::ModPath, - AstId, EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, - MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, }; pub fn expand_eager_macro_input( diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs index 3a26c62e1f200..c34570fcb5cf9 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs @@ -9,8 +9,9 @@ use span::{ use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextSize}; use crate::{ + MacroFileIdExt, MacroKind, db::{self, ExpandDatabase}, - map_node_range_up, map_node_range_up_rooted, span_for_offset, MacroFileIdExt, MacroKind, + map_node_range_up, map_node_range_up_rooted, span_for_offset, }; /// `InFile` stores a value of `T` inside a particular file/syntax tree. @@ -365,11 +366,7 @@ impl InFile { // FIXME: Figure out an API that makes proper use of ctx, this only exists to // keep pre-token map rewrite behaviour. - if ctxt.is_root() { - Some(range) - } else { - None - } + if ctxt.is_root() { Some(range) } else { None } } } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs index 076dd75cde35f..740152892b8b4 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs @@ -4,13 +4,14 @@ use intern::sym; use rustc_hash::{FxHashMap, FxHashSet}; use span::{ - ErasedFileAstId, Span, SpanAnchor, SyntaxContext, FIXUP_ERASED_FILE_AST_ID_MARKER, - ROOT_ERASED_FILE_AST_ID, + ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, ROOT_ERASED_FILE_AST_ID, Span, SpanAnchor, + SyntaxContext, }; use stdx::never; use syntax::{ + SyntaxElement, SyntaxKind, SyntaxNode, TextRange, TextSize, ast::{self, AstNode, HasLoopBody}, - match_ast, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, TextSize, + match_ast, }; use syntax_bridge::DocCommentDesugarMode; use triomphe::Arc; @@ -465,7 +466,7 @@ fn reverse_fixups_(tt: &mut TopSubtree, undo_info: &[TopSubtree]) { #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use span::{Edition, EditionedFileId, FileId}; use syntax::TextRange; use syntax_bridge::DocCommentDesugarMode; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs index 20694e7d6b80b..d684a2f9ce7ab 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs @@ -147,7 +147,7 @@ pub trait SyntaxContextExt { fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> span::SyntaxContext; fn parent_ctxt(self, db: &dyn ExpandDatabase) -> span::SyntaxContext; fn remove_mark(&mut self, db: &dyn ExpandDatabase) - -> (Option, Transparency); + -> (Option, Transparency); fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option, Transparency); fn marks(self, db: &dyn ExpandDatabase) -> Vec<(span::MacroCallId, Transparency)>; fn is_opaque(self, db: &dyn ExpandDatabase) -> bool; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index ca5c40c9fac34..d089d4c49eb9c 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -40,15 +40,15 @@ use span::{ SyntaxContext, }; use syntax::{ - ast::{self, AstNode}, SyntaxNode, SyntaxToken, TextRange, TextSize, + ast::{self, AstNode}, }; use crate::{ attrs::AttrId, builtin::{ - include_input_to_file_id, BuiltinAttrExpander, BuiltinDeriveExpander, - BuiltinFnLikeExpander, EagerExpander, + BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander, + include_input_to_file_id, }, db::ExpandDatabase, mod_path::ModPath, @@ -67,7 +67,7 @@ pub use span::{HirFileId, MacroCallId, MacroFileId}; pub mod tt { pub use span::Span; - pub use tt::{token_to_literal, DelimiterKind, IdentIsRaw, LitKind, Spacing}; + pub use tt::{DelimiterKind, IdentIsRaw, LitKind, Spacing, token_to_literal}; pub type Delimiter = ::tt::Delimiter; pub type DelimSpan = ::tt::DelimSpan; @@ -207,7 +207,9 @@ impl ExpandErrorKind { kind: RenderedExpandError::GENERAL_KIND, }, None => RenderedExpandError { - message: format!("internal error: proc-macro map is missing error entry for crate {def_crate:?}"), + message: format!( + "internal error: proc-macro map is missing error entry for crate {def_crate:?}" + ), error: true, kind: RenderedExpandError::GENERAL_KIND, }, @@ -389,7 +391,7 @@ impl HirFileIdExt for HirFileId { loop { match call.file_id.repr() { HirFileIdRepr::FileId(file_id) => { - break Some(InRealFile { file_id, value: call.value }) + break Some(InRealFile { file_id, value: call.value }); } HirFileIdRepr::MacroFile(MacroFileId { macro_call_id }) => { call = db.lookup_intern_macro_call(macro_call_id).to_node(db); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs index 5c160240a2ba2..7f8dc0dba6ff6 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs @@ -7,7 +7,7 @@ use std::{ use crate::{ db::ExpandDatabase, - hygiene::{marks_rev, SyntaxContextExt, Transparency}, + hygiene::{SyntaxContextExt, Transparency, marks_rev}, name::{AsName, Name}, tt, }; @@ -15,7 +15,7 @@ use base_db::Crate; use intern::sym; use smallvec::SmallVec; use span::{Edition, SyntaxContext}; -use syntax::{ast, AstNode}; +use syntax::{AstNode, ast}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ModPath { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index 79860a002afe7..23ca77f5a0d84 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -2,7 +2,7 @@ use std::fmt; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use span::{Edition, SyntaxContext}; use syntax::utils::is_raw_identifier; use syntax::{ast, format_smolstr}; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs index f398b070f791b..953aea65b2cd9 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs @@ -3,7 +3,7 @@ use base_db::Crate; use rustc_hash::FxHashMap; use syntax::NodeOrToken; -use syntax::{ast::make, SyntaxNode}; +use syntax::{SyntaxNode, ast::make}; use crate::{db::ExpandDatabase, span_map::ExpansionSpanMap}; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs index 1330f6af9fd37..9dcd5ef1ef03e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs @@ -10,7 +10,7 @@ use rustc_hash::FxHashMap; use span::Span; use triomphe::Arc; -use crate::{db::ExpandDatabase, tt, ExpandError, ExpandErrorKind, ExpandResult}; +use crate::{ExpandError, ExpandErrorKind, ExpandResult, db::ExpandDatabase, tt}; #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug, Hash)] pub enum ProcMacroKind { @@ -298,7 +298,7 @@ impl CustomProcMacroExpander { call_site, "internal error: no proc macros for crate", ), - ) + ); } }; let proc_macro = match proc_macros.get(id, call_site) { @@ -310,7 +310,7 @@ impl CustomProcMacroExpander { close: call_site, }), e, - ) + ); } }; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs b/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs index 55fe42e271f4d..1965e767074a2 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs @@ -2,7 +2,7 @@ use span::{EditionedFileId, HirFileId, HirFileIdRepr, MacroFileId, Span, SyntaxContext}; use stdx::TupleExt; -use syntax::{ast, AstNode, TextRange}; +use syntax::{AstNode, TextRange, ast}; use triomphe::Arc; pub use span::RealSpanMap; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs index 2c27f5e3bbf18..8f3526f1d4905 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs @@ -12,8 +12,8 @@ use intern::sym; use triomphe::Arc; use crate::{ - db::HirDatabase, infer::unify::InferenceTable, Canonical, Goal, Interner, ProjectionTyExt, - TraitEnvironment, Ty, TyBuilder, TyKind, + Canonical, Goal, Interner, ProjectionTyExt, TraitEnvironment, Ty, TyBuilder, TyKind, + db::HirDatabase, infer::unify::InferenceTable, }; const AUTODEREF_RECURSION_LIMIT: usize = 20; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs index 4c35db0c9b98c..2898ab7b49f52 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs @@ -3,21 +3,21 @@ use std::iter; use chalk_ir::{ + AdtId, DebruijnIndex, Scalar, cast::{Cast, CastTo, Caster}, fold::TypeFoldable, interner::HasInterner, - AdtId, DebruijnIndex, Scalar, }; use hir_def::{ - builtin_type::BuiltinType, DefWithBodyId, GenericDefId, GenericParamId, TraitId, TypeAliasId, + DefWithBodyId, GenericDefId, GenericParamId, TraitId, TypeAliasId, builtin_type::BuiltinType, }; use smallvec::SmallVec; use crate::{ - consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime, generics::generics, - infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, Binders, - BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy, Substitution, - TraitRef, Ty, TyDefId, TyExt, TyKind, + Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy, + Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind, consteval::unknown_const_as_generic, + db::HirDatabase, error_lifetime, generics::generics, infer::unify::InferenceTable, primitive, + to_assoc_type_id, to_chalk_trait_id, }; #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index acaca24f54f9b..e0975b5aeb40b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -8,31 +8,32 @@ use intern::sym; use span::Edition; use tracing::debug; -use chalk_ir::{cast::Caster, fold::shift::Shift, CanonicalVarKinds}; +use chalk_ir::{CanonicalVarKinds, cast::Caster, fold::shift::Shift}; use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; use base_db::Crate; use hir_def::{ - data::{adt::StructFlags, TraitFlags}, - hir::Movability, - lang_item::{LangItem, LangItemTarget}, AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup, TypeAliasId, VariantId, + data::{TraitFlags, adt::StructFlags}, + hir::Movability, + lang_item::{LangItem, LangItemTarget}, }; use crate::{ + AliasEq, AliasTy, BoundVar, DebruijnIndex, FnDefId, Interner, ProjectionTy, ProjectionTyExt, + QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, + WhereClause, db::{HirDatabase, InternedCoroutine}, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, generics::generics, make_binders, make_single_type_binders, - mapping::{from_chalk, ToChalk, TypeAliasAsValue}, - method_resolution::{TraitImpls, TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, + mapping::{ToChalk, TypeAliasAsValue, from_chalk}, + method_resolution::{ALL_FLOAT_FPS, ALL_INT_FPS, TraitImpls, TyFingerprint}, to_assoc_type_id, to_chalk_trait_id, traits::ChalkContext, utils::ClosureSubst, - wrap_empty_binders, AliasEq, AliasTy, BoundVar, DebruijnIndex, FnDefId, Interner, ProjectionTy, - ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, - TyExt, TyKind, WhereClause, + wrap_empty_binders, }; pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs index 51c178b90d72b..49dde303099b6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs @@ -1,22 +1,22 @@ //! Various extensions traits for Chalk types. use chalk_ir::{ - cast::Cast, FloatTy, IntTy, Mutability, Scalar, TyVariableKind, TypeOutlives, UintTy, + FloatTy, IntTy, Mutability, Scalar, TyVariableKind, TypeOutlives, UintTy, cast::Cast, }; use hir_def::{ + DefWithBodyId, FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId, builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType, BuiltinUint}, generics::TypeOrConstParamData, lang_item::LangItem, type_ref::Rawness, - DefWithBodyId, FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId, }; use crate::{ - db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, - from_placeholder_idx, generics::generics, to_chalk_trait_id, utils::ClosureSubst, AdtId, - AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, ClosureId, - DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy, + AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, + ClosureId, DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy, QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyKind, TypeFlags, WhereClause, + db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, + from_placeholder_idx, generics::generics, to_chalk_trait_id, utils::ClosureSubst, }; pub trait TyExt { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index ec8f9b7c31186..48c23aff78880 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -1,14 +1,14 @@ //! Constant evaluation details use base_db::Crate; -use chalk_ir::{cast::Cast, BoundVar, DebruijnIndex}; +use chalk_ir::{BoundVar, DebruijnIndex, cast::Cast}; use hir_def::{ + ConstBlockLoc, EnumVariantId, GeneralConstId, HasModule as _, StaticId, expr_store::{Body, HygieneId}, hir::{Expr, ExprId}, path::Path, resolver::{Resolver, ValueNs}, type_ref::LiteralConstRef, - ConstBlockLoc, EnumVariantId, GeneralConstId, HasModule as _, StaticId, }; use hir_expand::Lookup; use salsa::Cycle; @@ -16,17 +16,18 @@ use stdx::never; use triomphe::Arc; use crate::{ + Const, ConstData, ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, + TraitEnvironment, Ty, TyBuilder, db::{HirDatabase, HirDatabaseData}, display::DisplayTarget, generics::Generics, infer::InferenceContext, lower::ParamLoweringMode, mir::monomorphize_mir_body_bad, - to_placeholder_idx, Const, ConstData, ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, - Substitution, TraitEnvironment, Ty, TyBuilder, + to_placeholder_idx, }; -use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError}; +use super::mir::{MirEvalError, MirLowerError, interpret_mir, lower_to_mir, pad16}; /// Extension trait for [`Const`] pub trait ConstExt { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index d679f9dd7ca42..8049897f31f08 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -2,16 +2,16 @@ use base_db::RootQueryDb; use chalk_ir::Substitution; use hir_def::db::DefDatabase; use rustc_apfloat::{ - ieee::{Half as f16, Quad as f128}, Float, + ieee::{Half as f16, Quad as f128}, }; use span::EditionedFileId; use test_fixture::WithFixture; use test_utils::skip_slow_tests; use crate::{ - consteval::try_const_usize, db::HirDatabase, display::DisplayTarget, mir::pad16, - test_db::TestDB, Const, ConstScalar, Interner, MemoryMap, + Const, ConstScalar, Interner, MemoryMap, consteval::try_const_usize, db::HirDatabase, + display::DisplayTarget, mir::pad16, test_db::TestDB, }; use super::{ diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index 8f48cfc4327ff..6c619794753b0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -3,11 +3,12 @@ use std::sync; -use base_db::{impl_intern_key, Crate, Upcast}; +use base_db::{Crate, Upcast, impl_intern_key}; use hir_def::{ - db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, CallableDefId, - ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId, - LifetimeParamId, LocalFieldId, StaticId, TraitId, TypeAliasId, TypeOrConstParamId, VariantId, + AdtId, BlockId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, + GeneralConstId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, StaticId, TraitId, + TypeAliasId, TypeOrConstParamId, VariantId, db::DefDatabase, hir::ExprId, + layout::TargetDataLayout, }; use hir_expand::name::Name; use la_arena::ArenaMap; @@ -16,7 +17,8 @@ use smallvec::SmallVec; use triomphe::Arc; use crate::{ - chalk_db, + Binders, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, Interner, + PolyFnSig, Substitution, TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId, chalk_db, consteval::ConstEvalError, drop::DropGlue, dyn_compatibility::DynCompatibilityViolation, @@ -24,8 +26,6 @@ use crate::{ lower::{Diagnostics, GenericDefaults, GenericPredicates}, method_resolution::{InherentImpls, TraitImpls, TyFingerprint}, mir::{BorrowckResult, MirBody, MirLowerError}, - Binders, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, Interner, - PolyFnSig, Substitution, TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId, }; #[query_group::query_group] @@ -262,7 +262,7 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { #[salsa::invoke(chalk_db::impl_datum_query)] fn impl_datum(&self, krate: Crate, impl_id: chalk_db::ImplId) - -> sync::Arc; + -> sync::Arc; #[salsa::invoke(chalk_db::fn_def_datum_query)] fn fn_def_datum(&self, fn_def_id: FnDefId) -> sync::Arc; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs index 845d333335365..047a348fb09a7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs @@ -5,12 +5,12 @@ mod match_check; mod unsafe_check; pub use crate::diagnostics::{ - decl_check::{incorrect_case, CaseType, IncorrectCase}, + decl_check::{CaseType, IncorrectCase, incorrect_case}, expr::{ - record_literal_missing_fields, record_pattern_missing_fields, BodyValidationDiagnostic, + BodyValidationDiagnostic, record_literal_missing_fields, record_pattern_missing_fields, }, unsafe_check::{ - missing_unsafe, unsafe_operations, unsafe_operations_for_body, InsideUnsafeBlock, - UnsafetyReason, + InsideUnsafeBlock, UnsafetyReason, missing_unsafe, unsafe_operations, + unsafe_operations_for_body, }, }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index 5106056d40971..ce0ffb1792641 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -16,20 +16,20 @@ mod case_conv; use std::fmt; use hir_def::{ - data::adt::VariantData, db::DefDatabase, hir::Pat, src::HasSource, AdtId, ConstId, EnumId, - EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, ModuleDefId, ModuleId, StaticId, - StructId, TraitId, TypeAliasId, + AdtId, ConstId, EnumId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, + ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, data::adt::VariantData, + db::DefDatabase, hir::Pat, src::HasSource, }; use hir_expand::{ - name::{AsName, Name}, HirFileId, HirFileIdExt, + name::{AsName, Name}, }; use intern::sym; use stdx::{always, never}; use syntax::{ + AstNode, AstPtr, ToSmolStr, ast::{self, HasName}, utils::is_raw_identifier, - AstNode, AstPtr, ToSmolStr, }; use crate::db::HirDatabase; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs index 348f8a0f4a856..234c7e4b03c3c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs @@ -97,7 +97,7 @@ fn is_snake_case bool>(ident: &str, wrong_case: F) -> bool { #[cfg(test)] mod tests { use super::*; - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; fn check Option>(fun: F, input: &str, expect: Expect) { // `None` is translated to empty string, meaning that there is nothing to fix. diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 6096439565cba..51b404be8130e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -8,36 +8,36 @@ use base_db::Crate; use chalk_solve::rust_ir::AdtKind; use either::Either; use hir_def::{ + AdtId, AssocItemId, DefWithBodyId, HasModule, ItemContainerId, Lookup, lang_item::LangItem, resolver::{HasResolver, ValueNs}, - AdtId, AssocItemId, DefWithBodyId, HasModule, ItemContainerId, Lookup, }; use intern::sym; use itertools::Itertools; use rustc_hash::FxHashSet; use rustc_pattern_analysis::constructor::Constructor; use syntax::{ - ast::{self, UnaryOp}, AstNode, + ast::{self, UnaryOp}, }; use tracing::debug; use triomphe::Arc; use typed_arena::Arena; use crate::{ + Adjust, InferenceResult, Interner, Ty, TyExt, TyKind, db::HirDatabase, diagnostics::match_check::{ self, pat_analysis::{self, DeconstructedPat, MatchCheckCtx, WitnessPat}, }, display::{DisplayTarget, HirDisplay}, - Adjust, InferenceResult, Interner, Ty, TyExt, TyKind, }; pub(crate) use hir_def::{ + LocalFieldId, VariantId, expr_store::Body, hir::{Expr, ExprId, MatchArm, Pat, PatId, Statement}, - LocalFieldId, VariantId, }; pub enum BodyValidationDiagnostic { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs index b0f9fc53e29ee..1c58485eb97fc 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs @@ -11,19 +11,19 @@ pub(crate) mod pat_analysis; use chalk_ir::Mutability; use hir_def::{ - data::adt::VariantData, expr_store::Body, hir::PatId, AdtId, EnumVariantId, LocalFieldId, - VariantId, + AdtId, EnumVariantId, LocalFieldId, VariantId, data::adt::VariantData, expr_store::Body, + hir::PatId, }; use hir_expand::name::Name; use span::Edition; use stdx::{always, never}; use crate::{ + InferenceResult, Interner, Substitution, Ty, TyExt, TyKind, db::HirDatabase, display::{HirDisplay, HirDisplayError, HirFormatter}, infer::BindingMode, lang_items::is_box, - InferenceResult, Interner, Substitution, Ty, TyExt, TyKind, }; use self::pat_util::EnumerateAndAdjustIterator; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index b7f8a0c610c54..683a48bfc9e5b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -6,21 +6,21 @@ use std::fmt; use hir_def::{DefWithBodyId, EnumId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId}; use intern::sym; use rustc_pattern_analysis::{ - constructor::{Constructor, ConstructorSet, VariantVisibility}, - usefulness::{compute_match_usefulness, PlaceValidity, UsefulnessReport}, Captures, IndexVec, PatCx, PrivateUninhabitedField, + constructor::{Constructor, ConstructorSet, VariantVisibility}, + usefulness::{PlaceValidity, UsefulnessReport, compute_match_usefulness}, }; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use stdx::never; use crate::{ + AdtId, Interner, Scalar, Ty, TyExt, TyKind, db::HirDatabase, infer::normalize, inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from}, - AdtId, Interner, Scalar, Ty, TyExt, TyKind, }; -use super::{is_box, FieldPat, Pat, PatKind}; +use super::{FieldPat, Pat, PatKind, is_box}; use Constructor::*; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs index 84dd4be67fe8d..562a9aa085a1f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -5,18 +5,18 @@ use std::mem; use either::Either; use hir_def::{ + AdtId, DefWithBodyId, FieldId, FunctionId, VariantId, expr_store::Body, hir::{Expr, ExprId, ExprOrPatId, Pat, PatId, Statement, UnaryOp}, path::Path, resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs}, type_ref::Rawness, - AdtId, DefWithBodyId, FieldId, FunctionId, VariantId, }; use span::Edition; use crate::{ - db::HirDatabase, utils::is_fn_unsafe_to_call, InferenceResult, Interner, TargetFeatures, TyExt, - TyKind, + InferenceResult, Interner, TargetFeatures, TyExt, TyKind, db::HirDatabase, + utils::is_fn_unsafe_to_call, }; #[derive(Debug, Default)] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 7bce23f398a60..b2e13ba69201e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -11,6 +11,8 @@ use base_db::Crate; use chalk_ir::{BoundVar, Safety, TyKind}; use either::Either; use hir_def::{ + GenericDefId, HasModule, ImportPathConfig, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, + ModuleId, TraitId, data::adt::VariantData, db::DefDatabase, find_path::{self, PrefixKind}, @@ -23,16 +25,14 @@ use hir_def::{ TraitBoundModifier, TypeBound, TypeRef, TypeRefId, TypesMap, TypesSourceMap, UseArgRef, }, visibility::Visibility, - GenericDefId, HasModule, ImportPathConfig, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, - ModuleId, TraitId, }; use hir_expand::name::Name; -use intern::{sym, Internable, Interned}; +use intern::{Internable, Interned, sym}; use itertools::Itertools; use la_arena::ArenaMap; use rustc_apfloat::{ - ieee::{Half as f16, Quad as f128}, Float, + ieee::{Half as f16, Quad as f128}, }; use rustc_hash::FxHashSet; use smallvec::SmallVec; @@ -41,6 +41,11 @@ use stdx::never; use triomphe::Arc; use crate::{ + AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const, + ConstScalar, ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime, + LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, + QuantifiedWhereClause, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, + TyExt, WhereClause, consteval::try_const_usize, db::{HirDatabase, InternedClosure}, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, @@ -51,12 +56,7 @@ use crate::{ mapping::from_chalk, mir::pad16, primitive, to_assoc_type_id, - utils::{self, detect_variant_from_bytes, ClosureSubst}, - AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const, - ConstScalar, ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime, - LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, - QuantifiedWhereClause, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, - TyExt, WhereClause, + utils::{self, ClosureSubst, detect_variant_from_bytes}, }; pub trait HirWrite: fmt::Write { @@ -529,7 +529,9 @@ where Err(HirDisplayError::FmtError) => Err(fmt::Error), Err(HirDisplayError::DisplaySourceCodeError(_)) => { // This should never happen - panic!("HirDisplay::hir_fmt failed with DisplaySourceCodeError when calling Display::fmt!") + panic!( + "HirDisplay::hir_fmt failed with DisplaySourceCodeError when calling Display::fmt!" + ) } } } @@ -1381,7 +1383,7 @@ impl HirDisplay for Ty { match f.closure_style { ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"), ClosureStyle::ClosureWithId => { - return write!(f, "{{closure#{:?}}}", id.0.as_u32()) + return write!(f, "{{closure#{:?}}}", id.0.as_u32()); } ClosureStyle::ClosureWithSubst => { write!(f, "{{closure#{:?}}}", id.0.as_u32())?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs index ab17f86b5b2cb..5484a39324f93 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs @@ -1,16 +1,16 @@ //! Utilities for computing drop info about types. use chalk_ir::cast::Cast; +use hir_def::AdtId; use hir_def::data::adt::StructFlags; use hir_def::lang_item::LangItem; -use hir_def::AdtId; use stdx::never; use triomphe::Arc; use crate::db::HirDatabaseData; use crate::{ - db::HirDatabase, method_resolution::TyFingerprint, AliasTy, Canonical, CanonicalVarKinds, - InEnvironment, Interner, ProjectionTy, TraitEnvironment, Ty, TyBuilder, TyKind, + AliasTy, Canonical, CanonicalVarKinds, InEnvironment, Interner, ProjectionTy, TraitEnvironment, + Ty, TyBuilder, TyKind, db::HirDatabase, method_resolution::TyFingerprint, }; use crate::{ConcreteConst, ConstScalar, ConstValue}; @@ -176,11 +176,7 @@ fn projection_has_drop_glue( let normalized = db.normalize_projection(projection, env.clone()); match normalized.kind(Interner) { TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(..) => { - if is_copy(db, ty, env) { - DropGlue::None - } else { - DropGlue::DependOnParams - } + if is_copy(db, ty, env) { DropGlue::None } else { DropGlue::DependOnParams } } _ => db.has_drop_glue(normalized, env), } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs index af16a2499ba08..cb186c45ad00e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs @@ -3,28 +3,27 @@ use std::ops::ControlFlow; use chalk_ir::{ + DebruijnIndex, cast::Cast, visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, - DebruijnIndex, }; use chalk_solve::rust_ir::InlineBound; use hir_def::{ - data::TraitFlags, lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId, - HasModule, TraitId, TypeAliasId, + AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, TypeAliasId, + data::TraitFlags, lang_item::LangItem, }; use rustc_hash::FxHashSet; use smallvec::SmallVec; use crate::{ - all_super_traits, + AliasEq, AliasTy, Binders, BoundVar, CallableSig, GoalData, ImplTraitId, Interner, OpaqueTyId, + ProjectionTyExt, Solution, Substitution, TraitRef, Ty, TyKind, WhereClause, all_super_traits, db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, generics::{generics, trait_self_param_idx}, lower::callable_item_sig, to_assoc_type_id, to_chalk_trait_id, utils::elaborate_clause_supertraits, - AliasEq, AliasTy, Binders, BoundVar, CallableSig, GoalData, ImplTraitId, Interner, OpaqueTyId, - ProjectionTyExt, Solution, Substitution, TraitRef, Ty, TyKind, WhereClause, }; #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -558,11 +557,7 @@ fn receiver_for_self_ty(db: &dyn HirDatabase, func: FunctionId, ty: Ty) -> Optio let subst = Substitution::from_iter( Interner, subst.iter(Interner).enumerate().map(|(idx, arg)| { - if idx == trait_self_idx { - ty.clone().cast(Interner) - } else { - arg.clone() - } + if idx == trait_self_idx { ty.clone().cast(Interner) } else { arg.clone() } }), ); let sig = callable_item_sig(db, func.into()); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs index 18cf6e5ce36ef..9ed9817dfa077 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs @@ -9,22 +9,22 @@ //! where parent follows the same scheme. use std::ops; -use chalk_ir::{cast::Cast as _, BoundVar, DebruijnIndex}; +use chalk_ir::{BoundVar, DebruijnIndex, cast::Cast as _}; use hir_def::{ + ConstParamId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId, + LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId, db::DefDatabase, generics::{ GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance, }, type_ref::TypesMap, - ConstParamId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId, - LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId, }; use itertools::chain; use stdx::TupleExt; use triomphe::Arc; -use crate::{db::HirDatabase, lt_to_placeholder_idx, to_placeholder_idx, Interner, Substitution}; +use crate::{Interner, Substitution, db::HirDatabase, lt_to_placeholder_idx, to_placeholder_idx}; pub fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def))); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index ecadfccf00299..7388d2ab43cc7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -26,14 +26,16 @@ pub(crate) mod unify; use std::{cell::OnceCell, convert::identity, iter, ops::Index}; use chalk_ir::{ + DebruijnIndex, Mutability, Safety, Scalar, TyKind, TypeFlags, Variance, cast::Cast, fold::TypeFoldable, interner::HasInterner, visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, - DebruijnIndex, Mutability, Safety, Scalar, TyKind, TypeFlags, Variance, }; use either::Either; use hir_def::{ + AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ImplId, ItemContainerId, Lookup, + TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId, builtin_type::{BuiltinInt, BuiltinType, BuiltinUint}, data::{ConstData, StaticData}, expr_store::{Body, HygieneId}, @@ -43,8 +45,6 @@ use hir_def::{ path::{ModPath, Path}, resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs}, type_ref::{LifetimeRef, TypeRefId, TypesMap}, - AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ImplId, ItemContainerId, Lookup, - TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId, }; use hir_expand::name::Name; use indexmap::IndexSet; @@ -55,6 +55,9 @@ use stdx::{always, never}; use triomphe::Arc; use crate::{ + AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId, + ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ParamLoweringMode, + PathLoweringDiagnostic, ProjectionTy, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, db::HirDatabase, fold_tys, generics::Generics, @@ -64,14 +67,11 @@ use crate::{ expr::ExprIsRead, unify::InferenceTable, }, - lower::{diagnostics::TyLoweringDiagnostic, ImplTraitLoweringMode}, + lower::{ImplTraitLoweringMode, diagnostics::TyLoweringDiagnostic}, mir::MirSpan, to_assoc_type_id, traits::FnTrait, utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder}, - AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId, - ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ParamLoweringMode, - PathLoweringDiagnostic, ProjectionTy, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, }; // This lint has a false positive here. See the link below for details. @@ -1190,11 +1190,7 @@ impl<'a> InferenceContext<'a> { if let Some(impl_id) = impl_id { taits.extend(collector.assocs.into_iter().filter_map(|(id, (impl_, ty))| { - if impl_ == impl_id { - Some((id, ty)) - } else { - None - } + if impl_ == impl_id { Some((id, ty)) } else { None } })); } @@ -1914,11 +1910,7 @@ impl Expectation { match self { Expectation::HasType(ety) => { let ety = table.resolve_ty_shallow(ety); - if ety.is_ty_var() { - Expectation::None - } else { - Expectation::HasType(ety) - } + if ety.is_ty_var() { Expectation::None } else { Expectation::HasType(ety) } } Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()), _ => Expectation::None, @@ -2044,7 +2036,7 @@ impl chalk_ir::zip::Zipper for UnknownMismatch<'_> { | (_, TyKind::Error) | (TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _), _) | (_, TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _)) => { - return Err(chalk_ir::NoSolution) + return Err(chalk_ir::NoSolution); } _ => (), } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs index 8b43d0188a9de..d3de86f038721 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs @@ -1,13 +1,13 @@ //! Type cast logic. Basically coercion + additional casts. use chalk_ir::{Mutability, Scalar, TyVariableKind, UintTy}; -use hir_def::{hir::ExprId, AdtId}; +use hir_def::{AdtId, hir::ExprId}; use stdx::never; use crate::{ - infer::{coerce::CoerceNever, unify::InferenceTable}, Adjustment, Binders, DynTy, InferenceDiagnostic, Interner, PlaceholderIndex, QuantifiedWhereClauses, Ty, TyExt, TyKind, TypeFlags, WhereClause, + infer::{coerce::CoerceNever, unify::InferenceTable}, }; #[derive(Debug)] @@ -431,8 +431,8 @@ fn contains_dyn_trait(ty: &Ty) -> bool { use std::ops::ControlFlow; use chalk_ir::{ - visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, DebruijnIndex, + visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, }; struct DynTraitVisitor; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index 9ae6e0a174443..69de555214d2b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -3,12 +3,13 @@ use std::{cmp, convert::Infallible, mem}; use chalk_ir::{ + BoundVar, DebruijnIndex, FnSubst, Mutability, TyKind, cast::Cast, fold::{FallibleTypeFolder, TypeFoldable}, - BoundVar, DebruijnIndex, FnSubst, Mutability, TyKind, }; use either::Either; use hir_def::{ + DefWithBodyId, FieldId, HasModule, TupleFieldId, TupleId, VariantId, data::adt::VariantData, hir::{ Array, AsmOperand, BinaryOp, BindingId, CaptureBy, Expr, ExprId, ExprOrPatId, Pat, PatId, @@ -17,16 +18,18 @@ use hir_def::{ lang_item::LangItem, path::Path, resolver::ValueNs, - DefWithBodyId, FieldId, HasModule, TupleFieldId, TupleId, VariantId, }; use hir_expand::name::Name; use intern::sym; use rustc_hash::FxHashMap; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use stdx::{format_to, never}; use syntax::utils::is_raw_identifier; use crate::{ + Adjust, Adjustment, AliasEq, AliasTy, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, + DynTyExt, FnAbi, FnPointer, FnSig, Interner, OpaqueTy, ProjectionTyExt, Substitution, Ty, + TyExt, WhereClause, db::{HirDatabase, InternedClosure}, error_lifetime, from_chalk_trait_id, from_placeholder_idx, generics::Generics, @@ -36,9 +39,6 @@ use crate::{ to_chalk_trait_id, traits::FnTrait, utils::{self, elaborate_clause_supertraits}, - Adjust, Adjustment, AliasEq, AliasTy, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, - DynTyExt, FnAbi, FnPointer, FnSig, Interner, OpaqueTy, ProjectionTyExt, Substitution, Ty, - TyExt, WhereClause, }; use super::{Expectation, InferenceContext}; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs index acd86b1f3ed8a..b0fb01a84d18d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs @@ -7,7 +7,7 @@ use std::iter; -use chalk_ir::{cast::Cast, BoundVar, Goal, Mutability, TyKind, TyVariableKind}; +use chalk_ir::{BoundVar, Goal, Mutability, TyKind, TyVariableKind, cast::Cast}; use hir_def::{ hir::ExprId, lang_item::{LangItem, LangItemTarget}, @@ -16,6 +16,8 @@ use stdx::always; use triomphe::Arc; use crate::{ + Canonical, DomainGoal, FnAbi, FnPointer, FnSig, Guidance, InEnvironment, Interner, Lifetime, + Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, autoderef::{Autoderef, AutoderefKind}, db::HirDatabase, infer::{ @@ -23,8 +25,6 @@ use crate::{ TypeError, TypeMismatch, }, utils::ClosureSubst, - Canonical, DomainGoal, FnAbi, FnPointer, FnSig, Guidance, InEnvironment, Interner, Lifetime, - Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, }; use super::unify::InferenceTable; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs index e4f5b5ed378dc..563c5699cff63 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs @@ -6,13 +6,13 @@ use std::cell::RefCell; use std::ops::{Deref, DerefMut}; use either::Either; -use hir_def::{hir::ExprOrPatId, path::Path, resolver::Resolver, type_ref::TypesMap, TypeOwnerId}; +use hir_def::{TypeOwnerId, hir::ExprOrPatId, path::Path, resolver::Resolver, type_ref::TypesMap}; use la_arena::{Idx, RawIdx}; use crate::{ + InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringContext, TyLoweringDiagnostic, db::HirDatabase, lower::path::{PathDiagnosticCallback, PathLoweringContext}, - InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringContext, TyLoweringDiagnostic, }; // Unfortunately, this struct needs to use interior mutability (but we encapsulate it) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index d0cbce70a2f14..c5a6c21d29b29 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -5,9 +5,10 @@ use std::{ mem, }; -use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind}; +use chalk_ir::{DebruijnIndex, Mutability, TyVariableKind, cast::Cast, fold::Shift}; use either::Either; use hir_def::{ + BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId, hir::{ ArithOp, Array, AsmOperand, AsmOptions, BinaryOp, ClosureKind, Expr, ExprId, ExprOrPatId, LabelId, Literal, Pat, PatId, Statement, UnaryOp, @@ -15,7 +16,6 @@ use hir_def::{ lang_item::{LangItem, LangItemTarget}, path::{GenericArg, GenericArgs, Path}, resolver::ValueNs, - BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId, }; use hir_expand::name::Name; use intern::sym; @@ -23,34 +23,34 @@ use stdx::always; use syntax::ast::RangeOp; use crate::{ - autoderef::{builtin_deref, deref_by_trait, Autoderef}, + Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, DeclContext, + DeclOrigin, FnAbi, FnPointer, FnSig, FnSubst, Interner, Rawness, Scalar, Substitution, + TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, + autoderef::{Autoderef, builtin_deref, deref_by_trait}, consteval, db::{InternedClosure, InternedCoroutine}, error_lifetime, - generics::{generics, Generics}, + generics::{Generics, generics}, infer::{ + BreakableKind, coerce::{CoerceMany, CoerceNever, CoercionCause}, find_continuable, pat::contains_explicit_ref_binding, - BreakableKind, }, lang_items::lang_items_for_bin_op, lower::{ - const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode, + ParamLoweringMode, const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, }, - mapping::{from_chalk, ToChalk}, + mapping::{ToChalk, from_chalk}, method_resolution::{self, VisibleFromModule}, primitive::{self, UintTy}, static_lifetime, to_chalk_trait_id, traits::FnTrait, - Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, DeclContext, - DeclOrigin, FnAbi, FnPointer, FnSig, FnSubst, Interner, Rawness, Scalar, Substitution, - TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, }; use super::{ - cast::CastCheck, coerce::auto_deref_adjust_steps, find_breakable, BreakableContext, Diverges, - Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch, + BreakableContext, Diverges, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch, + cast::CastCheck, coerce::auto_deref_adjust_steps, find_breakable, }; #[derive(Clone, Copy, PartialEq, Eq)] @@ -1556,11 +1556,7 @@ impl InferenceContext<'_> { target_is_read, ) }; - if type_ref.is_some() { - decl_ty - } else { - ty - } + if type_ref.is_some() { decl_ty } else { ty } } else { decl_ty }; @@ -2402,11 +2398,7 @@ impl InferenceContext<'_> { BinaryOp::Assignment { .. } => unreachable!("handled above"), }; - if is_assign { - self.result.standard_types.unit.clone() - } else { - output_ty - } + if is_assign { self.result.standard_types.unit.clone() } else { output_ty } } fn is_builtin_binop(&mut self, lhs: &Ty, rhs: &Ty, op: BinaryOp) -> bool { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index 96d84cad9394c..aeaecc2831c25 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -1,7 +1,7 @@ //! Finds if an expression is an immutable context or a mutable context, which is used in selecting //! between `Deref` and `DerefMut` or `Index` and `IndexMut` or similar. -use chalk_ir::{cast::Cast, Mutability}; +use chalk_ir::{Mutability, cast::Cast}; use hir_def::{ hir::{ Array, AsmOperand, BinaryOp, BindingAnnotation, Expr, ExprId, Pat, PatId, Statement, @@ -13,9 +13,9 @@ use hir_expand::name::Name; use intern::sym; use crate::{ - infer::{expr::ExprIsRead, Expectation, InferenceContext}, - lower::lower_to_chalk_mutability, Adjust, Adjustment, AutoBorrow, Interner, OverloadedDeref, TyBuilder, TyKind, + infer::{Expectation, InferenceContext, expr::ExprIsRead}, + lower::lower_to_chalk_mutability, }; impl InferenceContext<'_> { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs index db93116f1071a..6d2811635eea6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs @@ -3,24 +3,25 @@ use std::iter::repeat_with; use hir_def::{ + HasModule, expr_store::Body, hir::{Binding, BindingAnnotation, BindingId, Expr, ExprId, Literal, Pat, PatId}, path::Path, - HasModule, }; use hir_expand::name::Name; use stdx::TupleExt; use crate::{ + DeclContext, DeclOrigin, InferenceDiagnostic, Interner, Mutability, Scalar, Substitution, Ty, + TyBuilder, TyExt, TyKind, consteval::{self, try_const_usize, usize_const}, infer::{ - coerce::CoerceNever, expr::ExprIsRead, BindingMode, Expectation, InferenceContext, - TypeMismatch, + BindingMode, Expectation, InferenceContext, TypeMismatch, coerce::CoerceNever, + expr::ExprIsRead, }, lower::lower_to_chalk_mutability, primitive::UintTy, - static_lifetime, DeclContext, DeclOrigin, InferenceDiagnostic, Interner, Mutability, Scalar, - Substitution, Ty, TyBuilder, TyExt, TyKind, + static_lifetime, }; impl InferenceContext<'_> { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs index 8ff0cf308224c..04d1ea97f938a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs @@ -2,21 +2,22 @@ use chalk_ir::cast::Cast; use hir_def::{ + AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup, path::{Path, PathSegment}, resolver::{ResolveValueResult, TypeNs, ValueNs}, - AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup, }; use hir_expand::name::Name; use stdx::never; use crate::{ + InferenceDiagnostic, Interner, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, + TyKind, ValueTyDefId, builder::ParamKind, consteval, error_lifetime, generics::generics, infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext, method_resolution::{self, VisibleFromModule}, - to_chalk_trait_id, InferenceDiagnostic, Interner, Substitution, TraitRef, TraitRefExt, Ty, - TyBuilder, TyExt, TyKind, ValueTyDefId, + to_chalk_trait_id, }; use super::{ExprOrPatId, InferenceContext, InferenceTyDiagnosticSource}; @@ -63,7 +64,7 @@ impl InferenceContext<'_> { never!("uninferred pattern?"); None } - } + }; } ValueNs::ImplSelf(impl_id) => { let generics = crate::generics::generics(self.db.upcast(), impl_id.into()); @@ -81,7 +82,7 @@ impl InferenceContext<'_> { }; } ValueNs::GenericParam(it) => { - return Some(ValuePathResolution::NonGeneric(self.db.const_param_ty(it))) + return Some(ValuePathResolution::NonGeneric(self.db.const_param_ty(it))); } }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 6d80bfc38e5b7..903097ee2f8f7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -3,13 +3,13 @@ use std::{fmt, mem}; use chalk_ir::{ - cast::Cast, fold::TypeFoldable, interner::HasInterner, zip::Zip, CanonicalVarKind, FloatTy, - IntTy, TyVariableKind, UniverseIndex, + CanonicalVarKind, FloatTy, IntTy, TyVariableKind, UniverseIndex, cast::Cast, + fold::TypeFoldable, interner::HasInterner, zip::Zip, }; use chalk_solve::infer::ParameterEnaVariableExt; use either::Either; use ena::unify::UnifyKey; -use hir_def::{lang_item::LangItem, AdtId}; +use hir_def::{AdtId, lang_item::LangItem}; use hir_expand::name::Name; use intern::sym; use rustc_hash::FxHashMap; @@ -18,12 +18,12 @@ use triomphe::Arc; use super::{InferOk, InferResult, InferenceContext, TypeError}; use crate::{ + AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, DomainGoal, + GenericArg, GenericArgData, Goal, GoalData, Guidance, InEnvironment, InferenceVar, Interner, + Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Solution, Substitution, + TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause, consteval::unknown_const, db::HirDatabase, fold_generic_args, fold_tys_and_consts, - to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, - DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, Guidance, InEnvironment, - InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, - Solution, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, VariableKind, - WhereClause, + to_chalk_trait_id, traits::FnTrait, }; impl InferenceContext<'_> { @@ -890,11 +890,7 @@ impl<'a> InferenceTable<'a> { TyKind::Error => self.new_type_var(), TyKind::InferenceVar(..) => { let ty_resolved = self.resolve_ty_shallow(&ty); - if ty_resolved.is_unknown() { - self.new_type_var() - } else { - ty - } + if ty_resolved.is_unknown() { self.new_type_var() } else { ty } } _ => ty, } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs index 800ba0d454490..c153bf3e34f1b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs @@ -2,14 +2,14 @@ use std::ops::ControlFlow::{self, Break, Continue}; use chalk_ir::{ - visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, DebruijnIndex, + visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, }; -use hir_def::{visibility::Visibility, AdtId, EnumVariantId, ModuleId, VariantId}; +use hir_def::{AdtId, EnumVariantId, ModuleId, VariantId, visibility::Visibility}; use rustc_hash::FxHashSet; use crate::{ - consteval::try_const_usize, db::HirDatabase, Binders, Interner, Substitution, Ty, TyKind, + Binders, Interner, Substitution, Ty, TyKind, consteval::try_const_usize, db::HirDatabase, }; // FIXME: Turn this into a query, it can be quite slow diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs index 832a00e1e5e7b..bd4a53603d1ae 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs @@ -2,15 +2,15 @@ //! representation of the various objects Chalk deals with (types, goals etc.). use crate::{ - chalk_db, tls, AliasTy, CanonicalVarKind, CanonicalVarKinds, ClosureId, Const, ConstData, - ConstScalar, Constraint, Constraints, FnAbi, FnDefId, GenericArg, GenericArgData, Goal, - GoalData, Goals, InEnvironment, Lifetime, LifetimeData, OpaqueTy, OpaqueTyId, ProgramClause, - ProgramClauseData, ProgramClauses, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, - Substitution, Ty, TyData, TyKind, VariableKind, VariableKinds, + AliasTy, CanonicalVarKind, CanonicalVarKinds, ClosureId, Const, ConstData, ConstScalar, + Constraint, Constraints, FnAbi, FnDefId, GenericArg, GenericArgData, Goal, GoalData, Goals, + InEnvironment, Lifetime, LifetimeData, OpaqueTy, OpaqueTyId, ProgramClause, ProgramClauseData, + ProgramClauses, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution, Ty, + TyData, TyKind, VariableKind, VariableKinds, chalk_db, tls, }; use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variance}; use hir_def::TypeAliasId; -use intern::{impl_internable, Interned}; +use intern::{Interned, impl_internable}; use smallvec::SmallVec; use std::fmt; use triomphe::Arc; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs index ff9c52fbb6c17..d638d50f8e344 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs @@ -1,6 +1,6 @@ //! Functions to detect special lang items -use hir_def::{data::adt::StructFlags, lang_item::LangItem, AdtId}; +use hir_def::{AdtId, data::adt::StructFlags, lang_item::LangItem}; use hir_expand::name::Name; use intern::sym; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index 2f7ad2b99d25b..0cb868d273f04 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -4,11 +4,11 @@ use std::fmt; use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy}; use hir_def::{ + LocalFieldId, StructId, layout::{ Float, Integer, LayoutCalculator, LayoutCalculatorError, LayoutData, Primitive, ReprOptions, Scalar, StructKind, TargetDataLayout, WrappingRange, }, - LocalFieldId, StructId, }; use la_arena::{Idx, RawIdx}; use rustc_abi::AddressSpace; @@ -18,11 +18,11 @@ use salsa::Cycle; use triomphe::Arc; use crate::{ + Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, consteval::try_const_usize, db::{HirDatabase, HirDatabaseData, InternedClosure}, infer::normalize, utils::ClosureSubst, - Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, }; pub(crate) use self::adt::layout_of_adt_recover; @@ -320,7 +320,7 @@ pub fn layout_of_ty_query( return Err(LayoutError::NotImplemented); } crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => { - return Err(LayoutError::NotImplemented) + return Err(LayoutError::NotImplemented); } } } @@ -342,7 +342,7 @@ pub fn layout_of_ty_query( cx.calc.univariant(&fields, &ReprOptions::default(), StructKind::AlwaysSized)? } TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) => { - return Err(LayoutError::NotImplemented) + return Err(LayoutError::NotImplemented); } TyKind::Error => return Err(LayoutError::HasErrorType), TyKind::AssociatedType(id, subst) => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs index 9f453162e30c5..efff875dec68b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs @@ -3,9 +3,9 @@ use std::{cmp, ops::Bound}; use hir_def::{ + AdtId, VariantId, data::adt::VariantData, layout::{Integer, ReprOptions, TargetDataLayout}, - AdtId, VariantId, }; use intern::sym; use rustc_index::IndexVec; @@ -14,10 +14,10 @@ use smallvec::SmallVec; use triomphe::Arc; use crate::{ + Substitution, TraitEnvironment, db::HirDatabase, lang_items::is_unsafe_cell, - layout::{field_ty, Layout, LayoutError}, - Substitution, TraitEnvironment, + layout::{Layout, LayoutError, field_ty}, }; use super::{HirDatabaseData, LayoutCx}; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index 8b74b7328bd83..f671b30380724 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs @@ -1,17 +1,17 @@ use chalk_ir::{AdtId, TyKind}; use either::Either; use hir_def::db::DefDatabase; -use project_model::{toolchain_info::QueryConfig, Sysroot}; +use project_model::{Sysroot, toolchain_info::QueryConfig}; use rustc_hash::FxHashMap; use syntax::ToSmolStr; use test_fixture::WithFixture; use triomphe::Arc; use crate::{ + Interner, Substitution, db::HirDatabase, layout::{Layout, LayoutError}, test_db::TestDB, - Interner, Substitution, }; mod closure; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 836319431dfb4..8292e80c1e197 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -57,19 +57,19 @@ mod variance; use std::hash::Hash; use chalk_ir::{ + NoSolution, fold::{Shift, TypeFoldable}, interner::HasInterner, - NoSolution, }; use either::Either; -use hir_def::{hir::ExprId, type_ref::Rawness, CallableDefId, GeneralConstId, TypeOrConstParamId}; +use hir_def::{CallableDefId, GeneralConstId, TypeOrConstParamId, hir::ExprId, type_ref::Rawness}; use hir_expand::name::Name; -use indexmap::{map::Entry, IndexMap}; -use intern::{sym, Symbol}; +use indexmap::{IndexMap, map::Entry}; +use intern::{Symbol, sym}; use la_arena::{Arena, Idx}; use mir::{MirEvalError, VTableMap}; use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; -use syntax::ast::{make, ConstArg}; +use syntax::ast::{ConstArg, make}; use traits::FnTrait; use triomphe::Arc; @@ -86,16 +86,16 @@ pub use builder::{ParamKind, TyBuilder}; pub use chalk_ext::*; pub use drop::DropGlue; pub use infer::{ + Adjust, Adjustment, AutoBorrow, BindingMode, InferenceDiagnostic, InferenceResult, + InferenceTyDiagnosticSource, OverloadedDeref, PointerCast, cast::CastError, closure::{CaptureKind, CapturedItem}, - could_coerce, could_unify, could_unify_deeply, Adjust, Adjustment, AutoBorrow, BindingMode, - InferenceDiagnostic, InferenceResult, InferenceTyDiagnosticSource, OverloadedDeref, - PointerCast, + could_coerce, could_unify, could_unify_deeply, }; pub use interner::Interner; pub use lower::{ - associated_type_shorthand_candidates, diagnostics::*, ImplTraitLoweringMode, ParamLoweringMode, - TyDefId, TyLoweringContext, ValueTyDefId, + ImplTraitLoweringMode, ParamLoweringMode, TyDefId, TyLoweringContext, ValueTyDefId, + associated_type_shorthand_candidates, diagnostics::*, }; pub use mapping::{ from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, @@ -105,13 +105,13 @@ pub use mapping::{ pub use method_resolution::check_orphan_rules; pub use target_feature::TargetFeatures; pub use traits::TraitEnvironment; -pub use utils::{all_super_traits, direct_super_traits, is_fn_unsafe_to_call, Unsafety}; +pub use utils::{Unsafety, all_super_traits, direct_super_traits, is_fn_unsafe_to_call}; pub use variance::Variance; pub use chalk_ir::{ + AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, cast::Cast, visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, - AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, }; pub type ForeignDefId = chalk_ir::ForeignDefId; @@ -645,10 +645,8 @@ pub(crate) fn fold_free_vars + TypeFoldable< F1: FnMut(BoundVar, DebruijnIndex) -> Ty, F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const, >(F1, F2); - impl< - F1: FnMut(BoundVar, DebruijnIndex) -> Ty, - F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const, - > TypeFolder for FreeVarFolder + impl Ty, F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const> + TypeFolder for FreeVarFolder { fn as_dyn(&mut self) -> &mut dyn TypeFolder { self @@ -778,8 +776,8 @@ where T: HasInterner + TypeFoldable + Clone, { use chalk_ir::{ - fold::{FallibleTypeFolder, TypeSuperFoldable}, Fallible, + fold::{FallibleTypeFolder, TypeSuperFoldable}, }; struct ErrorReplacer { vars: usize, @@ -840,11 +838,7 @@ where _var: InferenceVar, _outer_binder: DebruijnIndex, ) -> Fallible { - if cfg!(debug_assertions) { - Err(NoSolution) - } else { - Ok(unknown_const(ty)) - } + if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(unknown_const(ty)) } } fn try_fold_free_var_const( @@ -853,11 +847,7 @@ where _bound_var: BoundVar, _outer_binder: DebruijnIndex, ) -> Fallible { - if cfg!(debug_assertions) { - Err(NoSolution) - } else { - Ok(unknown_const(ty)) - } + if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(unknown_const(ty)) } } fn try_fold_inference_lifetime( @@ -865,11 +855,7 @@ where _var: InferenceVar, _outer_binder: DebruijnIndex, ) -> Fallible { - if cfg!(debug_assertions) { - Err(NoSolution) - } else { - Ok(error_lifetime()) - } + if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(error_lifetime()) } } fn try_fold_free_var_lifetime( @@ -877,11 +863,7 @@ where _bound_var: BoundVar, _outer_binder: DebruijnIndex, ) -> Fallible { - if cfg!(debug_assertions) { - Err(NoSolution) - } else { - Ok(error_lifetime()) - } + if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(error_lifetime()) } } } let mut error_replacer = ErrorReplacer { vars: 0 }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 12f3a1138fcc0..e5f3c4cfc8fc9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -16,16 +16,19 @@ use std::{ use base_db::Crate; use chalk_ir::{ + Mutability, Safety, TypeOutlives, cast::Cast, fold::{Shift, TypeFoldable}, interner::HasInterner, - Mutability, Safety, TypeOutlives, }; use either::Either; use hir_def::{ + AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, + FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, LocalFieldId, + Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, UnionId, VariantId, builtin_type::BuiltinType, - data::{adt::StructKind, TraitFlags}, + data::{TraitFlags, adt::StructKind}, expander::Expander, generics::{ GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate, @@ -39,11 +42,8 @@ use hir_def::{ ConstRef, LifetimeRef, PathId, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId, TypesMap, TypesSourceMap, }, - AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, - FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, LocalFieldId, - Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, UnionId, VariantId, }; -use hir_expand::{name::Name, ExpandResult}; +use hir_expand::{ExpandResult, name::Name}; use la_arena::{Arena, ArenaMap}; use rustc_hash::FxHashSet; use rustc_pattern_analysis::Captures; @@ -53,27 +53,26 @@ use syntax::ast; use triomphe::{Arc, ThinArc}; use crate::{ - all_super_traits, + AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, FnAbi, + FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, + LifetimeData, LifetimeOutlives, ParamKind, PolyFnSig, ProgramClause, QuantifiedWhereClause, + QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, + TyKind, WhereClause, all_super_traits, consteval::{ intern_const_ref, intern_const_scalar, path_to_const, unknown_const, unknown_const_as_generic, }, db::{HirDatabase, HirDatabaseData}, error_lifetime, - generics::{generics, trait_self_param_idx, Generics}, + generics::{Generics, generics, trait_self_param_idx}, lower::{ diagnostics::*, path::{PathDiagnosticCallback, PathLoweringContext}, }, make_binders, - mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk}, + mapping::{ToChalk, from_chalk_trait_id, lt_to_placeholder_idx}, static_lifetime, to_chalk_trait_id, to_placeholder_idx, - utils::{all_super_trait_refs, InTypeConstIdMetadata}, - AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, FnAbi, - FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, - LifetimeData, LifetimeOutlives, ParamKind, PolyFnSig, ProgramClause, QuantifiedWhereClause, - QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, - TyKind, WhereClause, + utils::{InTypeConstIdMetadata, all_super_trait_refs}, }; #[derive(Debug, Default)] @@ -1301,11 +1300,7 @@ fn implicitly_sized_clauses<'a, 'subst: 'a>( .enumerate() .filter_map( move |(idx, generic_arg)| { - if Some(idx) == trait_self_idx { - None - } else { - Some(generic_arg) - } + if Some(idx) == trait_self_idx { None } else { Some(generic_arg) } }, ) .filter_map(|generic_arg| generic_arg.ty(Interner)) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs index a9e9e83e871ff..960cb533713ee 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs @@ -2,32 +2,32 @@ use std::iter; -use chalk_ir::{cast::Cast, fold::Shift, BoundVar}; +use chalk_ir::{BoundVar, cast::Cast, fold::Shift}; use either::Either; use hir_def::{ + GenericDefId, GenericParamId, ItemContainerId, Lookup, TraitId, data::TraitFlags, expr_store::HygieneId, generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, path::{GenericArg, GenericArgs, Path, PathSegment, PathSegments}, resolver::{ResolveValueResult, TypeNs, ValueNs}, type_ref::{TypeBound, TypeRef, TypesMap}, - GenericDefId, GenericParamId, ItemContainerId, Lookup, TraitId, }; use smallvec::SmallVec; use stdx::never; use crate::{ + AliasEq, AliasTy, GenericArgsProhibitedReason, ImplTraitLoweringMode, Interner, + ParamLoweringMode, PathLoweringDiagnostic, ProjectionTy, QuantifiedWhereClause, Substitution, + TraitRef, Ty, TyBuilder, TyDefId, TyKind, TyLoweringContext, ValueTyDefId, WhereClause, consteval::unknown_const_as_generic, error_lifetime, generics::generics, lower::{ - generic_arg_to_chalk, named_associated_type_shorthand_candidates, ImplTraitLoweringState, + ImplTraitLoweringState, generic_arg_to_chalk, named_associated_type_shorthand_candidates, }, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, utils::associated_type_by_name_including_super_traits, - AliasEq, AliasTy, GenericArgsProhibitedReason, ImplTraitLoweringMode, Interner, - ParamLoweringMode, PathLoweringDiagnostic, ProjectionTy, QuantifiedWhereClause, Substitution, - TraitRef, Ty, TyBuilder, TyDefId, TyKind, TyLoweringContext, ValueTyDefId, WhereClause, }; type CallbackData<'a> = Either< diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs index cfa2a49b79c53..f7511e5f63a3f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs @@ -7,13 +7,13 @@ use chalk_solve::rust_ir; use hir_def::{LifetimeParamId, TraitId, TypeAliasId, TypeOrConstParamId}; use salsa::{ - plumbing::{AsId, FromId}, Id, + plumbing::{AsId, FromId}, }; use crate::{ - chalk_db, db::HirDatabase, AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, - Interner, OpaqueTyId, PlaceholderIndex, + AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, Interner, OpaqueTyId, + PlaceholderIndex, chalk_db, db::HirDatabase, }; pub(crate) trait ToChalk { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index bb3aaef20b76c..d887013b6ff30 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -6,33 +6,33 @@ use std::ops::ControlFlow; use arrayvec::ArrayVec; use base_db::Crate; -use chalk_ir::{cast::Cast, UniverseIndex, WithKind}; +use chalk_ir::{UniverseIndex, WithKind, cast::Cast}; use hir_def::{ - data::{adt::StructFlags, TraitFlags}, - nameres::{assoc::ImplItems, DefMap}, AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleId, TraitId, + data::{TraitFlags, adt::StructFlags}, + nameres::{DefMap, assoc::ImplItems}, }; use hir_expand::name::Name; use intern::sym; use rustc_hash::{FxHashMap, FxHashSet}; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use stdx::never; use triomphe::Arc; use crate::{ + AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData, + Goal, Guidance, InEnvironment, Interner, Mutability, Scalar, Solution, Substitution, + TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind, + VariableKind, WhereClause, autoderef::{self, AutoderefKind}, db::HirDatabase, error_lifetime, from_chalk_trait_id, from_foreign_def_id, - infer::{unify::InferenceTable, Adjust, Adjustment, OverloadedDeref, PointerCast}, + infer::{Adjust, Adjustment, OverloadedDeref, PointerCast, unify::InferenceTable}, lang_items::is_box, primitive::{FloatTy, IntTy, UintTy}, to_chalk_trait_id, utils::all_super_traits, - AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData, - Goal, Guidance, InEnvironment, Interner, Mutability, Scalar, Solution, Substitution, - TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind, - VariableKind, WhereClause, }; /// This is used as a key for indexing impls. @@ -166,11 +166,7 @@ impl TraitImpls { Self::collect_def_map(db, &mut impls, &db.block_def_map(block)); - if impls.is_empty() { - None - } else { - Some(Arc::new(Self::finish(impls))) - } + if impls.is_empty() { None } else { Some(Arc::new(Self::finish(impls))) } } pub(crate) fn trait_impls_in_deps_query( @@ -698,11 +694,7 @@ pub(crate) fn lookup_impl_method_query( let name = &db.function_data(func).name; let Some((impl_fn, impl_subst)) = lookup_impl_assoc_item_for_trait_ref(trait_ref, db, env, name).and_then(|assoc| { - if let (AssocItemId::FunctionId(id), subst) = assoc { - Some((id, subst)) - } else { - None - } + if let (AssocItemId::FunctionId(id), subst) = assoc { Some((id, subst)) } else { None } }) else { return (func, fn_subst); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index 7faa23f818b8f..247f0ec429fc8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -3,22 +3,22 @@ use std::{collections::hash_map::Entry, fmt::Display, iter}; use crate::{ + CallableDefId, ClosureId, Const, ConstScalar, InferenceResult, Interner, MemoryMap, + Substitution, TraitEnvironment, Ty, TyExt, TyKind, consteval::usize_const, db::HirDatabase, display::{DisplayTarget, HirDisplay}, - infer::{normalize, PointerCast}, + infer::{PointerCast, normalize}, lang_items::is_box, mapping::ToChalk, - CallableDefId, ClosureId, Const, ConstScalar, InferenceResult, Interner, MemoryMap, - Substitution, TraitEnvironment, Ty, TyExt, TyKind, }; use base_db::Crate; use chalk_ir::Mutability; use either::Either; use hir_def::{ + DefWithBodyId, FieldId, StaticId, TupleFieldId, UnionId, VariantId, expr_store::Body, hir::{BindingAnnotation, BindingId, Expr, ExprId, Ordering, PatId}, - DefWithBodyId, FieldId, StaticId, TupleFieldId, UnionId, VariantId, }; use la_arena::{Arena, ArenaMap, Idx, RawIdx}; @@ -28,17 +28,17 @@ mod lower; mod monomorphization; mod pretty; -pub use borrowck::{borrowck_query, BorrowckResult, MutabilityReason}; +pub use borrowck::{BorrowckResult, MutabilityReason, borrowck_query}; pub use eval::{ - interpret_mir, pad16, render_const_using_debug_impl, Evaluator, MirEvalError, VTableMap, + Evaluator, MirEvalError, VTableMap, interpret_mir, pad16, render_const_using_debug_impl, }; -pub use lower::{lower_to_mir, mir_body_for_closure_query, mir_body_query, MirLowerError}; +pub use lower::{MirLowerError, lower_to_mir, mir_body_for_closure_query, mir_body_query}; pub use monomorphization::{ monomorphize_mir_body_bad, monomorphized_mir_body_for_closure_query, monomorphized_mir_body_query, }; use rustc_hash::FxHashMap; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use stdx::{impl_from, never}; pub(crate) use lower::mir_body_recover; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs index fd1e724ee88ec..d9938fc60cd76 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs @@ -12,11 +12,11 @@ use stdx::never; use triomphe::Arc; use crate::{ + ClosureId, Interner, Substitution, Ty, TyExt, TypeFlags, db::{HirDatabase, InternedClosure}, display::DisplayTarget, mir::Operand, utils::ClosureSubst, - ClosureId, Interner, Substitution, Ty, TyExt, TypeFlags, }; use super::{ @@ -376,11 +376,7 @@ fn place_case(db: &dyn HirDatabase, body: &MirBody, lvalue: &Place) -> Projectio body.owner.module(db.upcast()).krate(), ); } - if is_part_of { - ProjectionCase::DirectPart - } else { - ProjectionCase::Direct - } + if is_part_of { ProjectionCase::DirectPart } else { ProjectionCase::Direct } } /// Returns a map from basic blocks to the set of locals that might be ever initialized before diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index be0a79f1dd394..ee412dd00b3a9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -3,25 +3,25 @@ use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range}; use base_db::Crate; -use chalk_ir::{cast::Cast, Mutability}; +use chalk_ir::{Mutability, cast::Cast}; use either::Either; use hir_def::{ + AdtId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, StaticId, + VariantId, builtin_type::BuiltinType, data::adt::{StructFlags, VariantData}, expr_store::HygieneId, lang_item::LangItem, layout::{TagEncoding, Variants}, resolver::{HasResolver, TypeNs, ValueNs}, - AdtId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, StaticId, - VariantId, }; -use hir_expand::{mod_path::path, name::Name, HirFileIdExt, InFile}; +use hir_expand::{HirFileIdExt, InFile, mod_path::path, name::Name}; use intern::sym; use la_arena::ArenaMap; use rustc_abi::TargetDataLayout; use rustc_apfloat::{ - ieee::{Half as f16, Quad as f128}, Float, + ieee::{Half as f16, Quad as f128}, }; use rustc_hash::{FxHashMap, FxHashSet}; use span::FileId; @@ -30,7 +30,9 @@ use syntax::{SyntaxNodePtr, TextRange}; use triomphe::Arc; use crate::{ - consteval::{intern_const_scalar, try_const_usize, ConstEvalError}, + CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstData, ConstScalar, FnDefId, Interner, + MemoryMap, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, + consteval::{ConstEvalError, intern_const_scalar, try_const_usize}, db::{HirDatabase, InternedClosure}, display::{ClosureStyle, DisplayTarget, HirDisplay}, infer::PointerCast, @@ -39,15 +41,13 @@ use crate::{ method_resolution::{is_dyn_method, lookup_impl_const}, static_lifetime, traits::FnTrait, - utils::{detect_variant_from_bytes, ClosureSubst}, - CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstData, ConstScalar, FnDefId, Interner, - MemoryMap, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, + utils::{ClosureSubst, detect_variant_from_bytes}, }; use super::{ - return_slot, AggregateKind, BasicBlockId, BinOp, CastKind, LocalId, MirBody, MirLowerError, - MirSpan, Operand, Place, PlaceElem, ProjectionElem, ProjectionStore, Rvalue, StatementKind, - TerminatorKind, UnOp, + AggregateKind, BasicBlockId, BinOp, CastKind, LocalId, MirBody, MirLowerError, MirSpan, + Operand, Place, PlaceElem, ProjectionElem, ProjectionStore, Rvalue, StatementKind, + TerminatorKind, UnOp, return_slot, }; mod shim; @@ -825,7 +825,7 @@ impl Evaluator<'_> { _ => { return Err(MirEvalError::InternalError( "mismatched layout".into(), - )) + )); } }] } @@ -1864,7 +1864,7 @@ impl Evaluator<'_> { "encoded tag ({offset}, {size}, {value}) is out of bounds 0..{size}" ) .into(), - )) + )); } } } @@ -1876,7 +1876,7 @@ impl Evaluator<'_> { None => { return Err(MirEvalError::InternalError( format!("field offset ({offset}) is out of bounds 0..{size}").into(), - )) + )); } } } @@ -2054,7 +2054,7 @@ impl Evaluator<'_> { _ => { return Err(MirEvalError::UndefinedBehavior(format!( "invalid memory write at address {addr:?}" - ))) + ))); } } @@ -2618,13 +2618,10 @@ impl Evaluator<'_> { let ty = ty.clone().cast(Interner); let generics_for_target = Substitution::from_iter( Interner, - generic_args.iter(Interner).enumerate().map(|(i, it)| { - if i == self_ty_idx { - &ty - } else { - it - } - }), + generic_args + .iter(Interner) + .enumerate() + .map(|(i, it)| if i == self_ty_idx { &ty } else { it }), ); self.exec_fn_with_args( def, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index edd028cdeb26c..a1cff20f9296d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -10,19 +10,19 @@ use hir_def::{ resolver::HasResolver, }; use hir_expand::name::Name; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use stdx::never; use crate::{ + DropGlue, display::DisplayTarget, error_lifetime, mir::eval::{ - pad16, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay, + Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay, InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId, LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, Result, Substitution, - Ty, TyBuilder, TyExt, + Ty, TyBuilder, TyExt, pad16, }, - DropGlue, }; mod simd; @@ -1357,7 +1357,7 @@ impl Evaluator<'_> { _ => { return Err(MirEvalError::InternalError( "three_way_compare expects an integral type".into(), - )) + )); } }; let rhs = rhs.get(self)?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs index 54754045c98aa..2387c19cdb517 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs @@ -2,8 +2,8 @@ use std::cmp::Ordering; -use crate::consteval::try_const_usize; use crate::TyKind; +use crate::consteval::try_const_usize; use super::*; @@ -164,7 +164,7 @@ impl Evaluator<'_> { None => { return Err(MirEvalError::InternalError( "simd type with unevaluatable len param".into(), - )) + )); } }; let (left_len, _) = self.detect_simd_ty(&left.ty)?; @@ -179,7 +179,7 @@ impl Evaluator<'_> { None => { return Err(MirEvalError::InternalError( "out of bound access in simd shuffle".into(), - )) + )); } }; result.extend(val); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs index 084c391d26cbb..cd490c3b48e5a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs @@ -4,9 +4,9 @@ use syntax::{TextRange, TextSize}; use test_fixture::WithFixture; use crate::display::DisplayTarget; -use crate::{db::HirDatabase, mir::MirLowerError, test_db::TestDB, Interner, Substitution}; +use crate::{Interner, Substitution, db::HirDatabase, mir::MirLowerError, test_db::TestDB}; -use super::{interpret_mir, MirEvalError}; +use super::{MirEvalError, interpret_mir}; fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), MirEvalError> { let module_id = db.module_for_file(file_id); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 38924d7c95495..95c93b5f3edd8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -2,9 +2,11 @@ use std::{fmt::Write, iter, mem}; -use base_db::{salsa::Cycle, Crate}; +use base_db::{Crate, salsa::Cycle}; use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind}; use hir_def::{ + AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, HasModule, ItemContainerId, LocalFieldId, + Lookup, TraitId, TupleId, TypeOrConstParamId, data::adt::{StructKind, VariantData}, expr_store::{Body, HygieneId}, hir::{ @@ -15,8 +17,6 @@ use hir_def::{ path::Path, resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs}, type_ref::TypesMap, - AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, HasModule, ItemContainerId, LocalFieldId, - Lookup, TraitId, TupleId, TypeOrConstParamId, }; use hir_expand::name::Name; use la_arena::ArenaMap; @@ -27,27 +27,27 @@ use syntax::TextRange; use triomphe::Arc; use crate::{ + Adjust, Adjustment, AutoBorrow, CallableDefId, TyBuilder, TyExt, consteval::ConstEvalError, db::{HirDatabase, InternedClosure}, - display::{hir_display_with_types_map, DisplayTarget, HirDisplay}, + display::{DisplayTarget, HirDisplay, hir_display_with_types_map}, error_lifetime, generics::generics, - infer::{cast::CastTy, unify::InferenceTable, CaptureKind, CapturedItem, TypeMismatch}, + infer::{CaptureKind, CapturedItem, TypeMismatch, cast::CastTy, unify::InferenceTable}, inhabitedness::is_ty_uninhabited_from, layout::LayoutError, mapping::ToChalk, mir::{ - intern_const_scalar, return_slot, AggregateKind, Arena, BasicBlock, BasicBlockId, BinOp, - BorrowKind, CastKind, ClosureId, ConstScalar, Either, Expr, FieldId, Idx, InferenceResult, - Interner, Local, LocalId, MemoryMap, MirBody, MirSpan, Mutability, Operand, Place, - PlaceElem, PointerCast, ProjectionElem, ProjectionStore, RawIdx, Rvalue, Statement, - StatementKind, Substitution, SwitchTargets, Terminator, TerminatorKind, TupleFieldId, Ty, - UnOp, VariantId, + AggregateKind, Arena, BasicBlock, BasicBlockId, BinOp, BorrowKind, CastKind, ClosureId, + ConstScalar, Either, Expr, FieldId, Idx, InferenceResult, Interner, Local, LocalId, + MemoryMap, MirBody, MirSpan, Mutability, Operand, Place, PlaceElem, PointerCast, + ProjectionElem, ProjectionStore, RawIdx, Rvalue, Statement, StatementKind, Substitution, + SwitchTargets, Terminator, TerminatorKind, TupleFieldId, Ty, UnOp, VariantId, + intern_const_scalar, return_slot, }, static_lifetime, traits::FnTrait, utils::ClosureSubst, - Adjust, Adjustment, AutoBorrow, CallableDefId, TyBuilder, TyExt, }; mod as_place; @@ -1278,7 +1278,7 @@ impl<'ctx> MirLowerCtx<'ctx> { _ => { return Err(MirLowerError::TypeError( "Array expression with non array type", - )) + )); } }; let Some(values) = elements @@ -1310,7 +1310,7 @@ impl<'ctx> MirLowerCtx<'ctx> { _ => { return Err(MirLowerError::TypeError( "Array repeat expression with non array type", - )) + )); } }; let r = Rvalue::Repeat(init, len); @@ -1441,7 +1441,7 @@ impl<'ctx> MirLowerCtx<'ctx> { _ => { return Err(MirLowerError::TypeError( "float with size other than 2, 4, 8 or 16 bytes", - )) + )); } }, }; @@ -2173,11 +2173,7 @@ pub fn lower_to_mir( ctx.result.locals.alloc(Local { ty: ctx.expr_ty_after_adjustments(root_expr) }); let binding_picker = |b: BindingId| { let owner = ctx.body.binding_owners.get(&b).copied(); - if root_expr == body.body_expr { - owner.is_none() - } else { - owner == Some(root_expr) - } + if root_expr == body.body_expr { owner.is_none() } else { owner == Some(root_expr) } }; // 1 to param_len is for params // FIXME: replace with let chain once it becomes stable diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs index 1c6dc4fecd81e..d6b2100253f6b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -1,9 +1,11 @@ //! MIR lowering for patterns -use hir_def::{hir::ExprId, AssocItemId}; +use hir_def::{AssocItemId, hir::ExprId}; use crate::{ + BindingMode, mir::{ + LocalId, MutBorrowKind, lower::{ BasicBlockId, BinOp, BindingId, BorrowKind, Either, Expr, FieldId, Idx, Interner, MemoryMap, MirLowerCtx, MirLowerError, MirSpan, Mutability, Operand, Pat, PatId, Place, @@ -11,9 +13,7 @@ use crate::{ Substitution, SwitchTargets, TerminatorKind, TupleFieldId, TupleId, TyBuilder, TyKind, ValueNs, VariantData, VariantId, }, - LocalId, MutBorrowKind, }, - BindingMode, }; macro_rules! not_supported { @@ -139,7 +139,7 @@ impl MirLowerCtx<'_> { _ => { return Err(MirLowerError::TypeError( "non tuple type matched with tuple pattern", - )) + )); } }; self.pattern_match_tuple_like( @@ -615,7 +615,7 @@ impl MirLowerCtx<'_> { mode, )?, VariantId::UnionId(_) => { - return Err(MirLowerError::TypeError("pattern matching on union")) + return Err(MirLowerError::TypeError("pattern matching on union")); } }) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs index 6d1e9a1ea1972..c733c7ed845a4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs @@ -10,19 +10,19 @@ use std::mem; use chalk_ir::{ - fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}, ConstData, DebruijnIndex, + fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}, }; use hir_def::DefWithBodyId; use triomphe::Arc; use crate::{ + ClosureId, Const, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, TyKind, consteval::{intern_const_scalar, unknown_const}, db::{HirDatabase, HirDatabaseData, InternedClosure}, from_placeholder_idx, - generics::{generics, Generics}, + generics::{Generics, generics}, infer::normalize, - ClosureId, Const, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, TyKind, }; use super::{MirBody, MirLowerError, Operand, Rvalue, StatementKind, TerminatorKind}; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs index 7d7d4106cb955..d9c0000fffd01 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs @@ -7,14 +7,14 @@ use std::{ use either::Either; use hir_def::{expr_store::Body, hir::BindingId}; -use hir_expand::{name::Name, Lookup}; +use hir_expand::{Lookup, name::Name}; use la_arena::ArenaMap; use crate::{ + ClosureId, db::HirDatabase, display::{ClosureStyle, DisplayTarget, HirDisplay}, mir::{PlaceElem, ProjectionElem, StatementKind, TerminatorKind}, - ClosureId, }; use super::{ diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs index fe9416c6cfc69..01e4160edb8dd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs @@ -4,7 +4,7 @@ use std::sync::LazyLock; use hir_def::attr::Attrs; use hir_def::tt; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use rustc_hash::{FxHashMap, FxHashSet}; #[derive(Debug, Default)] @@ -38,15 +38,17 @@ impl TargetFeatures { let enabled = attrs .by_key(&sym::target_feature) .tt_values() - .filter_map(|tt| { - match tt.token_trees().flat_tokens() { - [ - tt::TokenTree::Leaf(tt::Leaf::Ident(enable_ident)), - tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. })), - tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { kind: tt::LitKind::Str, symbol: features, .. })), - ] if enable_ident.sym == sym::enable => Some(features), - _ => None, - } + .filter_map(|tt| match tt.token_trees().flat_tokens() { + [ + tt::TokenTree::Leaf(tt::Leaf::Ident(enable_ident)), + tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. })), + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + kind: tt::LitKind::Str, + symbol: features, + .. + })), + ] if enable_ident.sym == sym::enable => Some(features), + _ => None, }) .flat_map(|features| features.as_str().split(',').map(Symbol::intern)) .collect(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs index 68d0c8cd5a312..5f1bd57af80ac 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs @@ -7,7 +7,7 @@ use base_db::{ SourceRoot, SourceRootId, SourceRootInput, Upcast, }; -use hir_def::{db::DefDatabase, ModuleId}; +use hir_def::{ModuleId, db::DefDatabase}; use hir_expand::db::ExpandDatabase; use rustc_hash::FxHashMap; use salsa::{AsDynDatabase, Durability}; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index 13d74264c560d..8790a31562e23 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -18,33 +18,33 @@ use std::sync::LazyLock; use base_db::{Crate, SourceDatabase}; use expect_test::Expect; use hir_def::{ + AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId, SyntheticSyntax, db::DefDatabase, expr_store::{Body, BodySourceMap}, hir::{ExprId, Pat, PatId}, item_scope::ItemScope, nameres::DefMap, src::HasSource, - AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId, SyntheticSyntax, }; -use hir_expand::{db::ExpandDatabase, FileRange, InFile}; +use hir_expand::{FileRange, InFile, db::ExpandDatabase}; use itertools::Itertools; use rustc_hash::FxHashMap; use stdx::format_to; use syntax::{ - ast::{self, AstNode, HasName}, SyntaxNode, + ast::{self, AstNode, HasName}, }; use test_fixture::WithFixture; -use tracing_subscriber::{layer::SubscriberExt, Registry}; +use tracing_subscriber::{Registry, layer::SubscriberExt}; use tracing_tree::HierarchicalLayer; use triomphe::Arc; use crate::{ + InferenceResult, Ty, db::HirDatabase, display::{DisplayTarget, HirDisplay}, infer::{Adjustment, TypeMismatch}, test_db::TestDB, - InferenceResult, Ty, }; // These tests compare the inference results for all expressions in a file diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs index efb1728d0561d..7d4218939ed36 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs @@ -1,4 +1,4 @@ -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use hir_def::db::DefDatabase; use hir_expand::files::InFileWrapper; use itertools::Itertools; @@ -384,7 +384,9 @@ fn main() { }; } "#, - expect!["57..149;20..25;78..80,98..100,118..124,134..135 ByRef(Mut { kind: Default }) a &'? mut bool"], + expect![ + "57..149;20..25;78..80,98..100,118..124,134..135 ByRef(Mut { kind: Default }) a &'? mut bool" + ], ); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs index 6cb59491fac82..b718556c8ae03 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs @@ -5,8 +5,8 @@ use itertools::Itertools; use span::Edition; use crate::{ - chalk_db, db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, mapping::from_chalk, - CallableDefId, Interner, ProjectionTyExt, + CallableDefId, Interner, ProjectionTyExt, chalk_db, db::HirDatabase, from_assoc_type_id, + from_chalk_trait_id, mapping::from_chalk, }; use hir_def::{AdtId, ItemContainerId, Lookup, TypeAliasId}; @@ -131,11 +131,7 @@ mod unsafe_tls { pub(crate) fn with_current_program( op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R, ) -> R { - if PROGRAM.is_set() { - PROGRAM.with(|prog| op(Some(prog))) - } else { - op(None) - } + if PROGRAM.is_set() { PROGRAM.with(|prog| op(Some(prog))) } else { op(None) } } pub(crate) fn set_current_program(p: &dyn HirDatabase, op: OP) -> R diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index f8db6a8298f6b..92dea02c7bf72 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -3,14 +3,14 @@ use core::fmt; use std::env::var; -use chalk_ir::{fold::TypeFoldable, DebruijnIndex, GoalData}; +use chalk_ir::{DebruijnIndex, GoalData, fold::TypeFoldable}; use chalk_recursive::Cache; -use chalk_solve::{logging_db::LoggingRustIrDatabase, rust_ir, Solver}; +use chalk_solve::{Solver, logging_db::LoggingRustIrDatabase, rust_ir}; use base_db::Crate; use hir_def::{ - lang_item::{LangItem, LangItemTarget}, BlockId, TraitId, + lang_item::{LangItem, LangItemTarget}, }; use hir_expand::name::Name; use intern::sym; @@ -19,9 +19,9 @@ use stdx::{never, panic_context}; use triomphe::Arc; use crate::{ - db::HirDatabase, infer::unify::InferenceTable, utils::UnevaluatedConstEvaluatorFolder, AliasEq, - AliasTy, Canonical, DomainGoal, Goal, Guidance, InEnvironment, Interner, ProjectionTy, - ProjectionTyExt, Solution, TraitRefExt, Ty, TyKind, TypeFlags, WhereClause, + AliasEq, AliasTy, Canonical, DomainGoal, Goal, Guidance, InEnvironment, Interner, ProjectionTy, + ProjectionTyExt, Solution, TraitRefExt, Ty, TyKind, TypeFlags, WhereClause, db::HirDatabase, + infer::unify::InferenceTable, utils::UnevaluatedConstEvaluatorFolder, }; /// This controls how much 'time' we give the Chalk solver before giving up. @@ -190,11 +190,7 @@ fn solve( // don't set the TLS for Chalk unless Chalk debugging is active, to make // extra sure we only use it for debugging - if is_chalk_debug() { - crate::tls::set_current_program(db, solve) - } else { - solve() - } + if is_chalk_debug() { crate::tls::set_current_program(db, solve) } else { solve() } } struct LoggingRustIrDatabaseLoggingOnDrop<'a>(LoggingRustIrDatabase>); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 3bd04b21b285d..695527444db05 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -5,33 +5,33 @@ use std::{hash::Hash, iter}; use base_db::Crate; use chalk_ir::{ - fold::{FallibleTypeFolder, Shift}, DebruijnIndex, + fold::{FallibleTypeFolder, Shift}, }; use hir_def::{ + EnumId, EnumVariantId, FunctionId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, + TypeOrConstParamId, db::DefDatabase, generics::{WherePredicate, WherePredicateTypeTarget}, lang_item::LangItem, resolver::{HasResolver, TypeNs}, type_ref::{TraitBoundModifier, TypeRef}, - EnumId, EnumVariantId, FunctionId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, - TypeOrConstParamId, }; use hir_expand::name::Name; use intern::sym; use rustc_abi::TargetDataLayout; use rustc_hash::FxHashSet; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use span::Edition; use stdx::never; use crate::{ + ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TargetFeatures, TraitRef, + TraitRefExt, Ty, WhereClause, consteval::unknown_const, db::HirDatabase, layout::{Layout, TagEncoding}, mir::pad16, - ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TargetFeatures, TraitRef, - TraitRefExt, Ty, WhereClause, }; pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator + '_ { @@ -315,11 +315,7 @@ pub fn is_fn_unsafe_to_call( } else { // Function in an `extern` block are always unsafe to call, except when // it is marked as `safe`. - if data.is_safe() { - Unsafety::Safe - } else { - Unsafety::Unsafe - } + if data.is_safe() { Unsafety::Safe } else { Unsafety::Unsafe } } } _ => Unsafety::Safe, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index ab3d098908893..e8744e4629e80 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -14,7 +14,7 @@ //! while installing firewall per item queries to prevent invalidation issues. use crate::db::HirDatabase; -use crate::generics::{generics, Generics}; +use crate::generics::{Generics, generics}; use crate::{ AliasTy, Const, ConstScalar, DynTyExt, GenericArg, GenericArgData, Interner, Lifetime, LifetimeData, Ty, TyKind, @@ -487,13 +487,13 @@ impl Context<'_> { #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use hir_def::{ - generics::GenericParamDataRef, src::HasSource, AdtId, GenericDefId, ModuleDefId, + AdtId, GenericDefId, ModuleDefId, generics::GenericParamDataRef, src::HasSource, }; use itertools::Itertools; use stdx::format_to; - use syntax::{ast::HasName, AstNode}; + use syntax::{AstNode, ast::HasName}; use test_fixture::WithFixture; use hir_def::Lookup; diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index 1c88e79933fba..70637028eff98 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -3,12 +3,12 @@ use std::ops::ControlFlow; use hir_def::{ + AssocItemId, AttrDefId, ModuleDefId, attr::AttrsWithOwner, item_scope::ItemInNs, path::{ModPath, Path}, per_ns::Namespace, resolver::{HasResolver, Resolver, TypeNs}, - AssocItemId, AttrDefId, ModuleDefId, }; use hir_expand::{mod_path::PathKind, name::Name}; use hir_ty::{db::HirDatabase, method_resolution}; @@ -273,11 +273,7 @@ fn resolve_impl_trait_item( // disambiguation) so we just pick the first one we find as well. result = as_module_def_if_namespace_matches(assoc_item_id.into(), ns); - if result.is_some() { - ControlFlow::Break(()) - } else { - ControlFlow::Continue(()) - } + if result.is_some() { ControlFlow::Break(()) } else { ControlFlow::Continue(()) } }, ); diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index 1ed0daa375630..a9893e741d54d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -6,22 +6,23 @@ use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_def::{ + DefWithBodyId, SyntheticSyntax, expr_store::ExprOrPatPtr, hir::ExprOrPatId, - path::{hir_segment_to_ast_segment, ModPath}, + path::{ModPath, hir_segment_to_ast_segment}, type_ref::TypesSourceMap, - DefWithBodyId, SyntheticSyntax, }; -use hir_expand::{name::Name, HirFileId, InFile}; +use hir_expand::{HirFileId, InFile, name::Name}; use hir_ty::{ - db::HirDatabase, - diagnostics::{BodyValidationDiagnostic, UnsafetyReason}, CastError, InferenceDiagnostic, InferenceTyDiagnosticSource, PathLoweringDiagnostic, TyLoweringDiagnostic, TyLoweringDiagnosticKind, + db::HirDatabase, + diagnostics::{BodyValidationDiagnostic, UnsafetyReason}, }; use syntax::{ + AstNode, AstPtr, SyntaxError, SyntaxNodePtr, TextRange, ast::{self, HasGenericArgs}, - match_ast, AstNode, AstPtr, SyntaxError, SyntaxNodePtr, TextRange, + match_ast, }; use triomphe::Arc; @@ -29,8 +30,8 @@ use crate::{AssocItem, Field, Function, Local, Trait, Type}; pub use hir_def::VariantId; pub use hir_ty::{ - diagnostics::{CaseType, IncorrectCase}, GenericArgsProhibitedReason, + diagnostics::{CaseType, IncorrectCase}, }; macro_rules! diagnostics { diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs index 6f4168ab0867d..ec34fd80ad689 100644 --- a/src/tools/rust-analyzer/crates/hir/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir/src/display.rs @@ -1,9 +1,10 @@ //! HirDisplay implementations for various hir types. use either::Either; use hir_def::{ + AdtId, GenericDefId, data::{ - adt::{StructKind, VariantData}, TraitFlags, + adt::{StructKind, VariantData}, }, generics::{ GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate, @@ -11,14 +12,13 @@ use hir_def::{ }, lang_item::LangItem, type_ref::{TypeBound, TypeRef}, - AdtId, GenericDefId, }; use hir_ty::{ + AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause, display::{ - hir_display_with_types_map, write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError, HirDisplayWithTypesMap, HirFormatter, SizedByDefault, + hir_display_with_types_map, write_bounds_like_dyn_trait_with_prefix, write_visibility, }, - AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause, }; use itertools::Itertools; @@ -854,7 +854,7 @@ impl HirDisplay for Module { return match self.krate(f.db).display_name(f.db) { Some(name) => write!(f, "extern crate {name}"), None => f.write_str("extern crate {unknown}"), - } + }; } } match self.name(f.db) { diff --git a/src/tools/rust-analyzer/crates/hir/src/from_id.rs b/src/tools/rust-analyzer/crates/hir/src/from_id.rs index 891d2fd2ba5dc..ab4b4a8dae541 100644 --- a/src/tools/rust-analyzer/crates/hir/src/from_id.rs +++ b/src/tools/rust-analyzer/crates/hir/src/from_id.rs @@ -4,9 +4,9 @@ //! are splitting the hir. use hir_def::{ - hir::{BindingId, LabelId}, AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, GenericDefId, GenericParamId, ModuleDefId, VariantId, + hir::{BindingId, LabelId}, }; use crate::{ diff --git a/src/tools/rust-analyzer/crates/hir/src/has_source.rs b/src/tools/rust-analyzer/crates/hir/src/has_source.rs index b4468178fbede..3d9c04d387483 100644 --- a/src/tools/rust-analyzer/crates/hir/src/has_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/has_source.rs @@ -2,9 +2,9 @@ use either::Either; use hir_def::{ + CallableDefId, Lookup, MacroId, VariantId, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource as _}, - CallableDefId, Lookup, MacroId, VariantId, }; use hir_expand::{HirFileId, InFile}; use hir_ty::db::InternedClosure; @@ -13,9 +13,10 @@ use syntax::ast; use tt::TextRange; use crate::{ - db::HirDatabase, Adt, Callee, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl, + Adt, Callee, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl, InlineAsmOperand, Label, LifetimeParam, LocalSource, Macro, Module, Param, SelfParam, Static, Struct, Trait, TraitAlias, TypeAlias, TypeOrConstParam, Union, Variant, VariantDef, + db::HirDatabase, }; pub trait HasSource { diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index caf00665a1e6b..b3bb4a0a33a2b 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -42,7 +42,12 @@ use arrayvec::ArrayVec; use base_db::{CrateDisplayName, CrateOrigin, LangCrateOrigin}; use either::Either; use hir_def::{ - data::{adt::VariantData, TraitFlags}, + AdtId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, + CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, + FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId, + LifetimeParamId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, + SyntheticSyntax, TraitAliasId, TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, + data::{TraitFlags, adt::VariantData}, expr_store::ExpressionStoreDiagnostics, generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, hir::{BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat}, @@ -54,30 +59,24 @@ use hir_def::{ per_ns::PerNs, resolver::{HasResolver, Resolver}, type_ref::TypesSourceMap, - AdtId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, - CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, - FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId, - LifetimeParamId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, - SyntheticSyntax, TraitAliasId, TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, }; use hir_expand::{ - attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, RenderedExpandError, - ValueResult, + AstId, MacroCallKind, RenderedExpandError, ValueResult, attrs::collect_attrs, + proc_macro::ProcMacroKind, }; use hir_ty::{ - all_super_traits, autoderef, check_orphan_rules, - consteval::{try_const_usize, unknown_const_as_generic, ConstExt}, + AliasTy, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, + GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution, + TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyLoweringDiagnostic, + ValueTyDefId, WhereClause, all_super_traits, autoderef, check_orphan_rules, + consteval::{ConstExt, try_const_usize, unknown_const_as_generic}, diagnostics::BodyValidationDiagnostic, direct_super_traits, error_lifetime, known_const_to_ast, layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, method_resolution, - mir::{interpret_mir, MutBorrowKind}, + mir::{MutBorrowKind, interpret_mir}, primitive::UintTy, traits::FnTrait, - AliasTy, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, - GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution, - TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyLoweringDiagnostic, - ValueTyDefId, WhereClause, }; use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; @@ -86,15 +85,16 @@ use smallvec::SmallVec; use span::{Edition, EditionedFileId, FileId, MacroCallId}; use stdx::{format_to, impl_from, never}; use syntax::{ + AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, T, TextRange, ToSmolStr, ast::{self, HasAttrs as _, HasGenericParams, HasName}, - format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T, + format_smolstr, }; use triomphe::{Arc, ThinArc}; use crate::db::{DefDatabase, HirDatabase}; pub use crate::{ - attrs::{resolve_doc_path_on, HasAttrs}, + attrs::{HasAttrs, resolve_doc_path_on}, diagnostics::*, has_source::HasSource, semantics::{ @@ -114,6 +114,7 @@ pub use crate::{ pub use { cfg::{CfgAtom, CfgExpr, CfgOptions}, hir_def::{ + ImportPathConfig, attr::{AttrSourceMap, Attrs, AttrsWithOwner}, data::adt::StructKind, find_path::PrefixKind, @@ -124,12 +125,12 @@ pub use { per_ns::Namespace, type_ref::{Mutability, TypeRef}, visibility::Visibility, - ImportPathConfig, // FIXME: This is here since some queries take it as input that are used // outside of hir. {ModuleDefId, TraitId}, }, hir_expand::{ + ExpandResult, HirFileId, HirFileIdExt, MacroFileId, MacroFileIdExt, MacroKind, attrs::{Attr, AttrId}, change::ChangeWithProcMacros, files::{ @@ -137,15 +138,16 @@ pub use { HirFileRange, InFile, InFileWrapper, InMacroFile, InRealFile, MacroFilePosition, MacroFileRange, }, - hygiene::{marks_rev, SyntaxContextExt}, + hygiene::{SyntaxContextExt, marks_rev}, inert_attr_macro::AttributeTemplate, mod_path::tool_path, name::Name, prettify_macro_expansion, proc_macro::{ProcMacros, ProcMacrosBuilder}, - tt, ExpandResult, HirFileId, HirFileIdExt, MacroFileId, MacroFileIdExt, MacroKind, + tt, }, hir_ty::{ + CastError, DropGlue, FnAbi, PointerCast, Safety, Variance, consteval::ConstEvalError, diagnostics::UnsafetyReason, display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite}, @@ -153,11 +155,10 @@ pub use { layout::LayoutError, method_resolution::TyFingerprint, mir::{MirEvalError, MirLowerError}, - CastError, DropGlue, FnAbi, PointerCast, Safety, Variance, }, // FIXME: Properly encapsulate mir - hir_ty::{mir, Interner as ChalkTyInterner}, - intern::{sym, Symbol}, + hir_ty::{Interner as ChalkTyInterner, mir}, + intern::{Symbol, sym}, }; // These are negative re-exports: pub using these names is forbidden, they @@ -587,11 +588,7 @@ impl Module { if let Some(m) = visible_from { let filtered = def.filter_visibility(|vis| vis.is_visible_from(db.upcast(), m.id)); - if filtered.is_none() && !def.is_none() { - None - } else { - Some((name, filtered)) - } + if filtered.is_none() && !def.is_none() { None } else { Some((name, filtered)) } } else { Some((name, def)) } @@ -1759,19 +1756,11 @@ impl Adt { } pub fn as_struct(&self) -> Option { - if let Self::Struct(v) = self { - Some(*v) - } else { - None - } + if let Self::Struct(v) = self { Some(*v) } else { None } } pub fn as_enum(&self) -> Option { - if let Self::Enum(v) = self { - Some(*v) - } else { - None - } + if let Self::Enum(v) = self { Some(*v) } else { None } } } @@ -5080,11 +5069,7 @@ impl Type { let projection = TyBuilder::assoc_type_projection(db, alias.id, Some(parent_subst)).build(); let ty = db.normalize_projection(projection, self.env.clone()); - if ty.is_unknown() { - None - } else { - Some(self.derived(ty)) - } + if ty.is_unknown() { None } else { Some(self.derived(ty)) } } pub fn is_copy(&self, db: &dyn HirDatabase) -> bool { @@ -5261,7 +5246,10 @@ impl Type { /// Returns types that this type dereferences to (including this type itself). The returned /// iterator won't yield the same type more than once even if the deref chain contains a cycle. - pub fn autoderef<'db>(&self, db: &'db dyn HirDatabase) -> impl Iterator + use<'_, 'db> { + pub fn autoderef<'db>( + &self, + db: &'db dyn HirDatabase, + ) -> impl Iterator + use<'_, 'db> { self.autoderef_(db).map(move |ty| self.derived(ty)) } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index a1c0521a5eb57..604099aaa5566 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -12,6 +12,7 @@ use std::{ use either::Either; use hir_def::{ + AsMacroCall, DefWithBodyId, FunctionId, MacroId, StructId, TraitId, VariantId, expr_store::{Body, ExprOrPatSource}, hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, lower::LowerCtx, @@ -19,9 +20,9 @@ use hir_def::{ path::ModPath, resolver::{self, HasResolver, Resolver, TypeNs}, type_ref::{Mutability, TypesMap, TypesSourceMap}, - AsMacroCall, DefWithBodyId, FunctionId, MacroId, StructId, TraitId, VariantId, }; use hir_expand::{ + ExpandResult, FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, attrs::collect_attrs, builtin::{BuiltinFnLikeExpander, EagerExpander}, db::ExpandDatabase, @@ -29,32 +30,31 @@ use hir_expand::{ hygiene::SyntaxContextExt as _, inert_attr_macro::find_builtin_attr_idx, name::AsName, - ExpandResult, FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, }; use hir_ty::diagnostics::unsafe_operations_for_body; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use span::{AstIdMap, EditionedFileId, FileId, HirFileIdRepr, SyntaxContext}; use stdx::TupleExt; use syntax::{ - algo::skip_trivia_token, - ast::{self, HasAttrs as _, HasGenericParams}, AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextSize, + algo::skip_trivia_token, + ast::{self, HasAttrs as _, HasGenericParams}, }; use triomphe::Arc; use crate::{ - db::HirDatabase, - semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, - source_analyzer::{name_hygiene, resolve_hir_path, SourceAnalyzer}, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, ConstParam, Crate, DefWithBody, DeriveHelper, Enum, Field, Function, GenericSubstitution, HasSource, HirFileId, Impl, InFile, InlineAsmOperand, ItemInNs, Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, + db::HirDatabase, + semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, + source_analyzer::{SourceAnalyzer, name_hygiene, resolve_hir_path}, }; const CONTINUE_NO_BREAKS: ControlFlow = ControlFlow::Continue(()); @@ -963,11 +963,7 @@ impl<'db> SemanticsImpl<'db> { || kind.is_any_identifier() && value.kind().is_any_identifier(); let matches = (kind == mapped_kind || any_ident_match()) && text == value.text(); - if matches { - ControlFlow::Break(value) - } else { - ControlFlow::Continue(()) - } + if matches { ControlFlow::Break(value) } else { ControlFlow::Continue(()) } }, ) } else { @@ -1780,7 +1776,7 @@ impl<'db> SemanticsImpl<'db> { SourceAnalyzer::new_for_body(self.db, def, node, offset) } else { SourceAnalyzer::new_for_body_no_infer(self.db, def, node, offset) - }) + }); } ChildContainer::TraitId(it) => it.resolver(self.db.upcast()), ChildContainer::TraitAliasId(it) => it.resolver(self.db.upcast()), diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index b89d332238b65..f172eec32a4ca 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -5,22 +5,22 @@ //! node for a *child*, and get its hir. use either::Either; -use hir_expand::{attrs::collect_attrs, HirFileId}; -use syntax::{ast, AstPtr}; +use hir_expand::{HirFileId, attrs::collect_attrs}; +use syntax::{AstPtr, ast}; use hir_def::{ + AdtId, AssocItemId, DefWithBodyId, EnumId, FieldId, GenericDefId, ImplId, ItemTreeLoc, + LifetimeParamId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, TypeOrConstParamId, + VariantId, db::DefDatabase, dyn_map::{ - keys::{self, Key}, DynMap, + keys::{self, Key}, }, item_scope::ItemScope, item_tree::ItemTreeNode, nameres::DefMap, src::{HasChildSource, HasSource}, - AdtId, AssocItemId, DefWithBodyId, EnumId, FieldId, GenericDefId, ImplId, ItemTreeLoc, - LifetimeParamId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, TypeOrConstParamId, - VariantId, }; pub(crate) trait ChildBySource { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 4ec0739656076..d5695f1c21a6d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -88,30 +88,30 @@ use base_db::{RootQueryDb, Upcast}; use either::Either; use hir_def::{ - dyn_map::{ - keys::{self, Key}, - DynMap, - }, - hir::{BindingId, Expr, LabelId}, AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, Lookup, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId, VariantId, + dyn_map::{ + DynMap, + keys::{self, Key}, + }, + hir::{BindingId, Expr, LabelId}, }; use hir_expand::{ - attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, InMacroFile, MacroCallId, - MacroFileId, MacroFileIdExt, + ExpansionInfo, HirFileId, HirFileIdExt, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, + attrs::AttrId, name::AsName, }; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::{EditionedFileId, FileId}; use stdx::impl_from; use syntax::{ - ast::{self, HasName}, AstNode, AstPtr, SyntaxNode, + ast::{self, HasName}, }; -use crate::{db::HirDatabase, semantics::child_by_source::ChildBySource, InFile, InlineAsmOperand}; +use crate::{InFile, InlineAsmOperand, db::HirDatabase, semantics::child_by_source::ChildBySource}; #[derive(Default)] pub(super) struct SourceToDefCache { diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index e390fb0b935ff..ce9f56993e3cf 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -8,48 +8,49 @@ use std::iter::{self, once}; use crate::{ - db::HirDatabase, semantics::PathResolution, Adt, AssocItem, BindingMode, BuiltinAttr, - BuiltinType, Callable, Const, DeriveHelper, Field, Function, GenericSubstitution, Local, Macro, - ModuleDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, Variant, + Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field, + Function, GenericSubstitution, Local, Macro, ModuleDef, Static, Struct, ToolModule, Trait, + TraitAlias, TupleField, Type, TypeAlias, Variant, db::HirDatabase, semantics::PathResolution, }; use either::Either; use hir_def::{ + AsMacroCall, AssocItemId, CallableDefId, ConstId, DefWithBodyId, FieldId, FunctionId, + ItemContainerId, LocalFieldId, Lookup, ModuleDefId, StructId, TraitId, VariantId, expr_store::{ - scope::{ExprScopes, ScopeId}, Body, BodySourceMap, HygieneId, + scope::{ExprScopes, ScopeId}, }, hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, lang_item::LangItem, lower::LowerCtx, nameres::MacroSubNs, path::{ModPath, Path, PathKind}, - resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs}, + resolver::{Resolver, TypeNs, ValueNs, resolver_for_scope}, type_ref::{Mutability, TypesMap, TypesSourceMap}, - AsMacroCall, AssocItemId, CallableDefId, ConstId, DefWithBodyId, FieldId, FunctionId, - ItemContainerId, LocalFieldId, Lookup, ModuleDefId, StructId, TraitId, VariantId, }; use hir_expand::{ + HirFileId, InFile, InMacroFile, MacroFileId, MacroFileIdExt, mod_path::path, name::{AsName, Name}, - HirFileId, InFile, InMacroFile, MacroFileId, MacroFileIdExt, }; use hir_ty::{ + Adjustment, InferenceResult, Interner, Substitution, TraitEnvironment, Ty, TyExt, TyKind, + TyLoweringContext, diagnostics::{ - record_literal_missing_fields, record_pattern_missing_fields, unsafe_operations, - InsideUnsafeBlock, + InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields, + unsafe_operations, }, from_assoc_type_id, lang_items::lang_items_for_bin_op, - method_resolution, Adjustment, InferenceResult, Interner, Substitution, TraitEnvironment, Ty, - TyExt, TyKind, TyLoweringContext, + method_resolution, }; use intern::sym; use itertools::Itertools; use smallvec::SmallVec; use syntax::ast::{RangeItem, RangeOp}; use syntax::{ - ast::{self, AstNode}, SyntaxKind, SyntaxNode, TextRange, TextSize, + ast::{self, AstNode}, }; use triomphe::Arc; @@ -147,11 +148,7 @@ impl SourceAnalyzer { fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option { let pat_id = self.pat_id(&pat.clone().into())?; - if let Pat::Bind { id, .. } = self.body()?.pats[pat_id.as_pat()?] { - Some(id) - } else { - None - } + if let Pat::Bind { id, .. } = self.body()?.pats[pat_id.as_pat()?] { Some(id) } else { None } } fn expand_expr( @@ -504,11 +501,7 @@ impl SourceAnalyzer { LangItem::DerefMut, &Name::new_symbol_root(sym::deref_mut.clone()), )?; - if func == deref_mut { - Some((deref_mut_trait, deref_mut)) - } else { - None - } + if func == deref_mut { Some((deref_mut_trait, deref_mut)) } else { None } }) .unwrap_or((deref_trait, deref)) } @@ -550,11 +543,7 @@ impl SourceAnalyzer { LangItem::IndexMut, &Name::new_symbol_root(sym::index_mut.clone()), )?; - if func == index_mut_fn { - Some((index_mut_trait, index_mut_fn)) - } else { - None - } + if func == index_mut_fn { Some((index_mut_trait, index_mut_fn)) } else { None } }) .unwrap_or((index_trait, index_fn)); // HACK: subst for all methods coincides with that for their trait because the methods diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index 853df7ee2d88a..ae70f6f0ecc05 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -2,22 +2,22 @@ use either::Either; use hir_def::{ + AdtId, AssocItemId, DefWithBodyId, ExternCrateId, HasModule, ImplId, Lookup, MacroId, + ModuleDefId, ModuleId, TraitId, db::DefDatabase, item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob}, per_ns::Item, src::{HasChildSource, HasSource}, visibility::{Visibility, VisibilityExplicitness}, - AdtId, AssocItemId, DefWithBodyId, ExternCrateId, HasModule, ImplId, Lookup, MacroId, - ModuleDefId, ModuleId, TraitId, }; -use hir_expand::{name::Name, HirFileId}; +use hir_expand::{HirFileId, name::Name}; use hir_ty::{ db::HirDatabase, - display::{hir_display_with_types_map, DisplayTarget, HirDisplay}, + display::{DisplayTarget, HirDisplay, hir_display_with_types_map}, }; use intern::Symbol; use rustc_hash::FxHashMap; -use syntax::{ast::HasName, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr}; +use syntax::{AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr, ast::HasName}; use crate::{Module, ModuleDef, Semantics}; diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs index 847304d503a84..bcff44fcd016e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs @@ -10,9 +10,9 @@ use std::iter; +use hir_ty::TyBuilder; use hir_ty::db::HirDatabase; use hir_ty::mir::BorrowKind; -use hir_ty::TyBuilder; use itertools::Itertools; use rustc_hash::FxHashSet; use span::Edition; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs index 05105c8c92c5e..2de0013bb126d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs @@ -5,7 +5,7 @@ //! assists if we are allowed to. use hir::ImportPathConfig; -use ide_db::{imports::insert_use::InsertUseConfig, SnippetCap}; +use ide_db::{SnippetCap, imports::insert_use::InsertUseConfig}; use crate::AssistKind; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs index c4e98c0742358..afb2229d3e2f6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs @@ -1,18 +1,18 @@ //! See [`AssistContext`]. use hir::{FileRange, Semantics}; -use ide_db::base_db::salsa::AsDynDatabase; use ide_db::EditionedFileId; -use ide_db::{label::Label, FileId, RootDatabase}; +use ide_db::base_db::salsa::AsDynDatabase; +use ide_db::{FileId, RootDatabase, label::Label}; use syntax::Edition; use syntax::{ - algo::{self, find_node_at_offset, find_node_at_range}, AstNode, AstToken, Direction, SourceFile, SyntaxElement, SyntaxKind, SyntaxToken, TextRange, TextSize, TokenAtOffset, + algo::{self, find_node_at_offset, find_node_at_range}, }; use crate::{ - assist_config::AssistConfig, Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel, + Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel, assist_config::AssistConfig, }; pub(crate) use ide_db::source_change::{SourceChangeBuilder, TreeMutator}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs index 42f615e71daf6..f9124d2d46551 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs @@ -1,6 +1,6 @@ use syntax::{ - ast::{self, edit_in_place::Indent, syntax_factory::SyntaxFactory}, AstNode, + ast::{self, edit_in_place::Indent, syntax_factory::SyntaxFactory}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs index 1a5de9cb071bb..c8a6f9e65caf5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs @@ -1,10 +1,10 @@ use hir::Semantics; use ide_db::{ + RootDatabase, assists::{AssistId, AssistKind}, source_change::SourceChangeBuilder, - RootDatabase, }; -use syntax::{ast, AstNode}; +use syntax::{AstNode, ast}; use crate::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs index 001f1e8bb1585..fc10501543b47 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs @@ -1,7 +1,7 @@ use ide_db::syntax_helpers::node_ext::for_each_break_and_continue_expr; use syntax::{ - ast::{self, AstNode, HasLoopBody}, T, + ast::{self, AstNode, HasLoopBody}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs index 43c0a72fa4774..c3e05b8fb0839 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs @@ -99,11 +99,7 @@ fn fetch_borrowed_types(node: &ast::Adt) -> Option> { } }; - if ref_types.is_empty() { - None - } else { - Some(ref_types) - } + if ref_types.is_empty() { None } else { Some(ref_types) } } fn find_ref_types_from_field_list(field_list: &ast::FieldList) -> Option> { @@ -134,11 +130,7 @@ fn find_ref_types_from_field_list(field_list: &ast::FieldList) -> Option) -> Opti let def = match NameRefClass::classify(&ctx.sema, &name_ref)? { NameRefClass::Definition(def, _) => def, NameRefClass::FieldShorthand { .. } | NameRefClass::ExternCrateShorthand { .. } => { - return None + return None; } }; let fun = match def { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs index 67bf8eed23df1..e584c709a94a4 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs @@ -6,19 +6,18 @@ use ide_db::{ syntax_helpers::node_ext::{for_each_tail_expr, walk_expr}, }; use syntax::{ + SyntaxKind, T, ast::{ - self, - prec::{precedence, ExprPrecedence}, - syntax_factory::SyntaxFactory, - AstNode, + self, AstNode, Expr::BinExpr, HasArgList, + prec::{ExprPrecedence, precedence}, + syntax_factory::SyntaxFactory, }, syntax_editor::{Position, SyntaxEditor}, - SyntaxKind, T, }; -use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists, utils::invert_boolean_expression}; // Assist: apply_demorgan // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs index a92a000c3fbd3..f491b9375c33b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs @@ -1,14 +1,14 @@ use std::cmp::Reverse; -use hir::{db::HirDatabase, Module}; +use hir::{Module, db::HirDatabase}; use ide_db::{ helpers::mod_path_to_ast, imports::{ import_assets::{ImportAssets, ImportCandidate, LocatedImport}, - insert_use::{insert_use, insert_use_as_alias, ImportScope}, + insert_use::{ImportScope, insert_use, insert_use_as_alias}, }, }; -use syntax::{ast, AstNode, Edition, NodeOrToken, SyntaxElement}; +use syntax::{AstNode, Edition, NodeOrToken, SyntaxElement, ast}; use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; @@ -279,12 +279,12 @@ mod tests { use super::*; use hir::{FileRange, Semantics}; - use ide_db::{assists::AssistResolveStrategy, RootDatabase}; + use ide_db::{RootDatabase, assists::AssistResolveStrategy}; use test_fixture::WithFixture; use crate::tests::{ - check_assist, check_assist_by_label, check_assist_not_applicable, check_assist_target, - TEST_CONFIG, + TEST_CONFIG, check_assist, check_assist_by_label, check_assist_not_applicable, + check_assist_target, }; fn check_auto_import_order(before: &str, order: &[&str]) { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bind_unused_param.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bind_unused_param.rs index 8f053f4df949f..5048ff5163abf 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bind_unused_param.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bind_unused_param.rs @@ -1,12 +1,12 @@ use crate::assist_context::{AssistContext, Assists}; use ide_db::{ + LineIndexDatabase, assists::{AssistId, AssistKind}, defs::Definition, - LineIndexDatabase, }; use syntax::{ - ast::{self, edit_in_place::Indent}, AstNode, + ast::{self, edit_in_place::Indent}, }; // Assist: bind_unused_param diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs index 07fd5e34181ef..8af9121fc8d13 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs @@ -1,14 +1,14 @@ use syntax::{ - ast::{self, HasName, HasVisibility}, AstNode, SyntaxKind::{ self, ASSOC_ITEM_LIST, CONST, ENUM, FN, MACRO_DEF, MODULE, SOURCE_FILE, STATIC, STRUCT, TRAIT, TYPE_ALIAS, USE, VISIBILITY, }, SyntaxNode, T, + ast::{self, HasName, HasVisibility}, }; -use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists, utils::vis_offset}; // Assist: change_visibility // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs index 151c71c0a767e..c4a2189f696ea 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs @@ -1,21 +1,21 @@ -use hir::{sym, AsAssocItem, Semantics}; +use hir::{AsAssocItem, Semantics, sym}; use ide_db::{ + RootDatabase, famous_defs::FamousDefs, syntax_helpers::node_ext::{ block_as_lone_tail, for_each_tail_expr, is_pattern_cond, preorder_expr, }, - RootDatabase, }; use itertools::Itertools; use syntax::{ - ast::{self, edit::AstNodeEdit, syntax_factory::SyntaxFactory, HasArgList}, - syntax_editor::SyntaxEditor, AstNode, SyntaxNode, + ast::{self, HasArgList, edit::AstNodeEdit, syntax_factory::SyntaxFactory}, + syntax_editor::SyntaxEditor, }; use crate::{ - utils::{invert_boolean_expression, unwrap_trivial_block}, AssistContext, AssistId, AssistKind, Assists, + utils::{invert_boolean_expression, unwrap_trivial_block}, }; // Assist: convert_if_to_bool_then diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs index 9cb14e8d9a007..8200ad75df5ff 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs @@ -2,23 +2,23 @@ use either::Either; use hir::ModuleDef; use ide_db::text_edit::TextRange; use ide_db::{ + FxHashSet, assists::{AssistId, AssistKind}, defs::Definition, helpers::mod_path_to_ast, - imports::insert_use::{insert_use, ImportScope}, + imports::insert_use::{ImportScope, insert_use}, search::{FileReference, UsageSearchResult}, source_change::SourceChangeBuilder, - FxHashSet, }; use itertools::Itertools; use syntax::{ + AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T, ast::{ - self, + self, HasName, edit::IndentLevel, edit_in_place::{AttrsOwnerEdit, Indent}, - make, HasName, + make, }, - AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T, }; use crate::{ diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs index 54826f03884f3..c11a411fb9c2c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs @@ -1,23 +1,24 @@ use either::Either; use hir::{CaptureKind, ClosureCapture, FileRangeWrapper, HirDisplay}; use ide_db::{ + FxHashSet, assists::{AssistId, AssistKind}, base_db::SourceDatabase, defs::Definition, search::FileReferenceNode, source_change::SourceChangeBuilder, - FxHashSet, }; use stdx::format_to; use syntax::{ + AstNode, Direction, SyntaxKind, SyntaxNode, T, TextSize, ToSmolStr, algo::{skip_trivia_token, skip_whitespace_token}, ast::{ - self, + self, HasArgList, HasGenericParams, HasName, edit::{AstNodeEdit, IndentLevel}, - make, HasArgList, HasGenericParams, HasName, + make, }, hacks::parse_expr_from_str, - ted, AstNode, Direction, SyntaxKind, SyntaxNode, TextSize, ToSmolStr, T, + ted, }; use crate::assist_context::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs index fbc0b9f6739ff..92b86cee356e8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs @@ -1,7 +1,7 @@ use itertools::Itertools; use syntax::{ - ast::{self, edit::IndentLevel, Comment, CommentKind, CommentShape, Whitespace}, AstToken, Direction, SyntaxElement, TextRange, + ast::{self, Comment, CommentKind, CommentShape, Whitespace, edit::IndentLevel}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -167,11 +167,7 @@ pub(crate) fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> let contents = contents_without_prefix.strip_prefix(' ').unwrap_or(contents_without_prefix); // Don't add the indentation if the line is empty - if contents.is_empty() { - contents.to_owned() - } else { - indentation.to_string() + contents - } + if contents.is_empty() { contents.to_owned() } else { indentation.to_string() + contents } } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs index 5a9db67a5fb68..7b4d27100f15d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs @@ -1,7 +1,7 @@ use itertools::Itertools; use syntax::{ - ast::{self, edit::IndentLevel, Comment, CommentPlacement, Whitespace}, AstToken, Direction, SyntaxElement, TextRange, + ast::{self, Comment, CommentPlacement, Whitespace, edit::IndentLevel}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs index 2d2751de99d87..03041f3551d39 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs @@ -1,12 +1,12 @@ use hir::{ - sym::{self}, Name, + sym::{self}, }; use ide_db::{famous_defs::FamousDefs, syntax_helpers::suggest_name}; use syntax::{ - ast::{self, edit::IndentLevel, make, syntax_factory::SyntaxFactory, HasLoopBody}, - syntax_editor::Position, AstNode, + ast::{self, HasLoopBody, edit::IndentLevel, make, syntax_factory::SyntaxFactory}, + syntax_editor::Position, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs index dd2e9cbcb5f2d..07ad5a695b3c3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs @@ -1,7 +1,7 @@ use ide_db::{famous_defs::FamousDefs, traits::resolve_target_trait}; use itertools::Itertools; use syntax::{ - ast::{self, make, AstNode, HasGenericArgs, HasName}, + ast::{self, AstNode, HasGenericArgs, HasName, make}, ted, }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs index fd3378e8c2636..270eecd83b06e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs @@ -1,4 +1,4 @@ -use syntax::{ast, ast::Radix, AstToken}; +use syntax::{AstToken, ast, ast::Radix}; use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs index 3c9a91741047e..713d215f1209e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs @@ -1,9 +1,9 @@ -use hir::{sym, Name}; +use hir::{Name, sym}; use ide_db::famous_defs::FamousDefs; use stdx::format_to; use syntax::{ - ast::{self, edit_in_place::Indent, make, HasArgList, HasLoopBody}, AstNode, + ast::{self, HasArgList, HasLoopBody, edit_in_place::Indent, make}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs index 79c34c14da720..9f71031a1e68a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs @@ -1,8 +1,8 @@ use hir::Semantics; use ide_db::RootDatabase; -use syntax::ast::RangeItem; -use syntax::ast::{edit::AstNodeEdit, AstNode, HasName, LetStmt, Name, Pat}; use syntax::T; +use syntax::ast::RangeItem; +use syntax::ast::{AstNode, HasName, LetStmt, Name, Pat, edit::AstNodeEdit}; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -162,11 +162,7 @@ fn binders_to_str(binders: &[(Name, bool)], addmut: bool) -> String { .iter() .map( |(ident, ismut)| { - if *ismut && addmut { - format!("mut {ident}") - } else { - ident.to_string() - } + if *ismut && addmut { format!("mut {ident}") } else { ident.to_string() } }, ) .collect::>() diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs index fd159eb824d6d..2db78f412d740 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs @@ -1,12 +1,13 @@ use ide_db::defs::{Definition, NameRefClass}; use syntax::{ + AstNode, SyntaxNode, ast::{self, HasName, Name}, - ted, AstNode, SyntaxNode, + ted, }; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, AssistKind, + assist_context::{AssistContext, Assists}, }; // Assist: convert_match_to_let_else diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs index 8d4ff84084bd3..7b8804e53f087 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs @@ -2,11 +2,12 @@ use either::Either; use ide_db::{defs::Definition, search::FileReference}; use itertools::Itertools; use syntax::{ + SyntaxKind, ast::{self, AstNode, HasAttrs, HasGenericParams, HasVisibility}, - match_ast, ted, SyntaxKind, + match_ast, ted, }; -use crate::{assist_context::SourceChangeBuilder, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists, assist_context::SourceChangeBuilder}; // Assist: convert_named_struct_to_tuple_struct // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs index b7a77644496fa..bd829d1e24bf9 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs @@ -5,20 +5,21 @@ use ide_db::{ ty_filter::TryEnum, }; use syntax::{ + AstNode, + SyntaxKind::{FN, FOR_EXPR, LOOP_EXPR, WHILE_EXPR, WHITESPACE}, + T, ast::{ self, edit::{AstNodeEdit, IndentLevel}, make, }, - ted, AstNode, - SyntaxKind::{FN, FOR_EXPR, LOOP_EXPR, WHILE_EXPR, WHITESPACE}, - T, + ted, }; use crate::{ + AssistId, AssistKind, assist_context::{AssistContext, Assists}, utils::invert_boolean_expression_legacy, - AssistId, AssistKind, }; // Assist: convert_to_guarded_return diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs index 91af9b05bbb85..0d79937885717 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs @@ -1,18 +1,19 @@ use either::Either; use hir::ModuleDef; use ide_db::{ + FxHashSet, assists::{AssistId, AssistKind}, defs::Definition, helpers::mod_path_to_ast, - imports::insert_use::{insert_use, ImportScope}, + imports::insert_use::{ImportScope, insert_use}, search::{FileReference, UsageSearchResult}, source_change::SourceChangeBuilder, syntax_helpers::node_ext::{for_each_tail_expr, walk_expr}, - FxHashSet, }; use syntax::{ - ast::{self, edit::IndentLevel, edit_in_place::Indent, make, HasName}, - match_ast, ted, AstNode, SyntaxNode, + AstNode, SyntaxNode, + ast::{self, HasName, edit::IndentLevel, edit_in_place::Indent, make}, + match_ast, ted, }; use crate::assist_context::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs index f6e516db88835..83e4737350c07 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs @@ -1,11 +1,12 @@ use either::Either; use ide_db::defs::{Definition, NameRefClass}; use syntax::{ + SyntaxKind, SyntaxNode, ast::{self, AstNode, HasAttrs, HasGenericParams, HasVisibility}, - match_ast, ted, SyntaxKind, SyntaxNode, + match_ast, ted, }; -use crate::{assist_context::SourceChangeBuilder, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists, assist_context::SourceChangeBuilder}; // Assist: convert_tuple_struct_to_named_struct // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs index beec64d13b689..724de1969cb53 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs @@ -3,18 +3,18 @@ use std::iter; use either::Either; use ide_db::syntax_helpers::node_ext::is_pattern_cond; use syntax::{ + AstNode, T, ast::{ - self, + self, HasLoopBody, edit::{AstNodeEdit, IndentLevel}, - make, HasLoopBody, + make, }, - AstNode, T, }; use crate::{ + AssistId, AssistKind, assist_context::{AssistContext, Assists}, utils::invert_boolean_expression_legacy, - AssistId, AssistKind, }; // Assist: convert_while_to_loop diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs index e34e50904875d..a8a3a8c927f81 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs @@ -1,14 +1,14 @@ -use hir::{sym, HasVisibility}; +use hir::{HasVisibility, sym}; use ide_db::text_edit::TextRange; use ide_db::{ + FxHashMap, FxHashSet, assists::{AssistId, AssistKind}, defs::Definition, helpers::mod_path_to_ast, search::{FileReference, SearchScope}, - FxHashMap, FxHashSet, }; use itertools::Itertools; -use syntax::{ast, ted, AstNode, Edition, SmolStr, SyntaxNode, ToSmolStr}; +use syntax::{AstNode, Edition, SmolStr, SyntaxNode, ToSmolStr, ast, ted}; use crate::{ assist_context::{AssistContext, Assists, SourceChangeBuilder}, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs index 39142d606207c..95eb88fa86878 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs @@ -7,7 +7,7 @@ use ide_db::{ }; use itertools::Itertools; use syntax::{ - ast::{self, make, AstNode, FieldExpr, HasName, IdentPat}, + ast::{self, AstNode, FieldExpr, HasName, IdentPat, make}, ted, }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs index d264928046707..9d0797d32a82f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs @@ -1,14 +1,14 @@ use either::Either; use itertools::Itertools; use syntax::{ - ast::{self, edit::IndentLevel, CommentPlacement, Whitespace}, AstToken, TextRange, + ast::{self, CommentPlacement, Whitespace, edit::IndentLevel}, }; use crate::{ + AssistContext, AssistId, AssistKind, Assists, handlers::convert_comment_block::{line_comment_text, relevant_line_comments}, utils::required_hashes, - AssistContext, AssistId, AssistKind, Assists, }; // Assist: desugar_doc_comment diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs index 0b95d6177f904..fae5530f99528 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs @@ -7,13 +7,14 @@ use ide_db::{ }; use stdx::never; use syntax::{ - ast::{self, make, Use, UseTree, VisibilityKind}, - ted, AstNode, Direction, SyntaxNode, SyntaxToken, T, + AstNode, Direction, SyntaxNode, SyntaxToken, T, + ast::{self, Use, UseTree, VisibilityKind, make}, + ted, }; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, AssistKind, + assist_context::{AssistContext, Assists}, }; // Assist: expand_glob_import diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs index c79a982c38d09..e437e7eb75122 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs @@ -1,8 +1,9 @@ use hir::{PathResolution, StructKind}; use ide_db::syntax_helpers::suggest_name::NameGenerator; use syntax::{ + AstNode, ToSmolStr, ast::{self, make}, - match_ast, AstNode, ToSmolStr, + match_ast, }; use crate::{AssistContext, AssistId, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs index e4d347ef16bd6..c9eb7c52379fc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs @@ -1,14 +1,15 @@ -use crate::{utils, AssistContext, Assists}; +use crate::{AssistContext, Assists, utils}; use ide_db::{ assists::{AssistId, AssistKind}, - syntax_helpers::format_string_exprs::{parse_format_exprs, Arg}, + syntax_helpers::format_string_exprs::{Arg, parse_format_exprs}, }; use itertools::Itertools; use syntax::{ - ast::{self, make}, - ted, AstNode, AstToken, NodeOrToken, + AstNode, AstToken, NodeOrToken, SyntaxKind::WHITESPACE, T, + ast::{self, make}, + ted, }; // Assist: extract_expressions_from_format_string @@ -61,21 +62,28 @@ pub(crate) fn extract_expressions_from_format_string( // Extract existing arguments in macro let tokens = tt.token_trees_and_tokens().collect_vec(); - let existing_args = if let [_opening_bracket, NodeOrToken::Token(_format_string), _args_start_comma, tokens @ .., NodeOrToken::Token(_end_bracket)] = - tokens.as_slice() + let existing_args = if let [ + _opening_bracket, + NodeOrToken::Token(_format_string), + _args_start_comma, + tokens @ .., + NodeOrToken::Token(_end_bracket), + ] = tokens.as_slice() { - let args = tokens.split(|it| matches!(it, NodeOrToken::Token(t) if t.kind() == T![,])).map(|arg| { - // Strip off leading and trailing whitespace tokens - let arg = match arg.split_first() { - Some((NodeOrToken::Token(t), rest)) if t.kind() == WHITESPACE => rest, - _ => arg, - }; - let arg = match arg.split_last() { - Some((NodeOrToken::Token(t), rest)) if t.kind() == WHITESPACE => rest, - _ => arg, - }; - arg - }); + let args = tokens + .split(|it| matches!(it, NodeOrToken::Token(t) if t.kind() == T![,])) + .map(|arg| { + // Strip off leading and trailing whitespace tokens + let arg = match arg.split_first() { + Some((NodeOrToken::Token(t), rest)) if t.kind() == WHITESPACE => rest, + _ => arg, + }; + let arg = match arg.split_last() { + Some((NodeOrToken::Token(t), rest)) if t.kind() == WHITESPACE => rest, + _ => arg, + }; + arg + }); args.collect() } else { @@ -100,7 +108,8 @@ pub(crate) fn extract_expressions_from_format_string( Arg::Expr(s) => { // insert arg // FIXME: use the crate's edition for parsing - let expr = ast::Expr::parse(&s, syntax::Edition::CURRENT_FIXME).syntax_node(); + let expr = + ast::Expr::parse(&s, syntax::Edition::CURRENT_FIXME).syntax_node(); let mut expr_tt = utils::tt_from_syntax(expr); new_tt_bits.append(&mut expr_tt); } @@ -120,7 +129,6 @@ pub(crate) fn extract_expressions_from_format_string( } } - // Insert new args let new_tt = make::token_tree(tt_delimiter, new_tt_bits).clone_for_update(); ted::replace(tt.syntax(), new_tt.syntax()); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs index 330587e0dbfbe..6b535a289776f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs @@ -7,33 +7,34 @@ use hir::{ TypeInfo, TypeParam, }; use ide_db::{ + FxIndexSet, RootDatabase, assists::GroupLabel, defs::{Definition, NameRefClass}, famous_defs::FamousDefs, helpers::mod_path_to_ast, - imports::insert_use::{insert_use, ImportScope}, + imports::insert_use::{ImportScope, insert_use}, search::{FileReference, ReferenceCategory, SearchScope}, source_change::SourceChangeBuilder, syntax_helpers::node_ext::{ for_each_tail_expr, preorder_expr, walk_expr, walk_pat, walk_patterns_in_expr, }, - FxIndexSet, RootDatabase, }; use itertools::Itertools; use syntax::{ + Edition, SyntaxElement, + SyntaxKind::{self, COMMENT}, + SyntaxNode, SyntaxToken, T, TextRange, TextSize, TokenAtOffset, WalkEvent, ast::{ - self, edit::IndentLevel, edit_in_place::Indent, AstNode, AstToken, HasGenericParams, - HasName, + self, AstNode, AstToken, HasGenericParams, HasName, edit::IndentLevel, + edit_in_place::Indent, }, - match_ast, ted, Edition, SyntaxElement, - SyntaxKind::{self, COMMENT}, - SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, WalkEvent, T, + match_ast, ted, }; use crate::{ + AssistId, assist_context::{AssistContext, Assists, TreeMutator}, utils::generate_impl, - AssistId, }; // Assist: extract_function @@ -1689,11 +1690,7 @@ fn make_where_clause( }) .peekable(); - if predicates.peek().is_some() { - Some(make::where_clause(predicates)) - } else { - None - } + if predicates.peek().is_some() { Some(make::where_clause(predicates)) } else { None } } fn pred_is_required( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs index b94422b13c1bc..8a7bb5a1f0d8b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs @@ -4,23 +4,24 @@ use either::Either; use hir::{HasSource, HirFileIdExt, ModuleSource}; use ide_db::base_db::salsa::AsDynDatabase; use ide_db::{ + FileId, FxHashMap, FxHashSet, assists::{AssistId, AssistKind}, defs::{Definition, NameClass, NameRefClass}, search::{FileReference, SearchScope}, - FileId, FxHashMap, FxHashSet, }; use itertools::Itertools; use smallvec::SmallVec; use syntax::{ + AstNode, + SyntaxKind::{self, WHITESPACE}, + SyntaxNode, TextRange, TextSize, algo::find_node_at_range, ast::{ - self, + self, HasVisibility, edit::{AstNodeEdit, IndentLevel}, - make, HasVisibility, + make, }, - match_ast, ted, AstNode, - SyntaxKind::{self, WHITESPACE}, - SyntaxNode, TextRange, TextSize, + match_ast, ted, }; use crate::{AssistContext, Assists}; @@ -1167,8 +1168,8 @@ mod modname { } #[test] - fn test_extract_module_for_impl_not_having_corresponding_adt_in_selection_and_not_in_same_mod_but_with_super( - ) { + fn test_extract_module_for_impl_not_having_corresponding_adt_in_selection_and_not_in_same_mod_but_with_super() + { check_assist( extract_module, r" diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs index d4f2ea3bd941b..7fba75f9e56d4 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs @@ -3,25 +3,26 @@ use std::iter; use either::Either; use hir::{HasCrate, Module, ModuleDef, Name, Variant}; use ide_db::{ + FxHashSet, RootDatabase, defs::Definition, helpers::mod_path_to_ast, - imports::insert_use::{insert_use, ImportScope, InsertUseConfig}, + imports::insert_use::{ImportScope, InsertUseConfig, insert_use}, path_transform::PathTransform, search::FileReference, - FxHashSet, RootDatabase, }; use itertools::Itertools; use syntax::{ - ast::{ - self, edit::IndentLevel, edit_in_place::Indent, make, AstNode, HasAttrs, HasGenericParams, - HasName, HasVisibility, - }, - match_ast, ted, Edition, SyntaxElement, + Edition, SyntaxElement, SyntaxKind::*, SyntaxNode, T, + ast::{ + self, AstNode, HasAttrs, HasGenericParams, HasName, HasVisibility, edit::IndentLevel, + edit_in_place::Indent, make, + }, + match_ast, ted, }; -use crate::{assist_context::SourceChangeBuilder, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists, assist_context::SourceChangeBuilder}; // Assist: extract_struct_from_enum_variant // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs index 67b8f5e505031..e6fb4d40d46b5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs @@ -1,7 +1,7 @@ use either::Either; use ide_db::syntax_helpers::node_ext::walk_ty; use syntax::{ - ast::{self, edit::IndentLevel, make, AstNode, HasGenericArgs, HasGenericParams, HasName}, + ast::{self, AstNode, HasGenericArgs, HasGenericParams, HasName, edit::IndentLevel, make}, syntax_editor, }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs index 7b6f76d00452e..2e58e62ab0ccc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs @@ -1,19 +1,19 @@ use hir::{HirDisplay, TypeInfo}; use ide_db::{ assists::GroupLabel, - syntax_helpers::{suggest_name, LexedStr}, + syntax_helpers::{LexedStr, suggest_name}, }; use syntax::{ + NodeOrToken, SyntaxKind, SyntaxNode, T, algo::ancestors_at_offset, ast::{ - self, edit::IndentLevel, edit_in_place::Indent, make, syntax_factory::SyntaxFactory, - AstNode, + self, AstNode, edit::IndentLevel, edit_in_place::Indent, make, + syntax_factory::SyntaxFactory, }, syntax_editor::Position, - NodeOrToken, SyntaxKind, SyntaxNode, T, }; -use crate::{utils::is_body_const, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists, utils::is_body_const}; // Assist: extract_variable // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs index 47e4a68293f0c..51dbce2973179 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs @@ -1,10 +1,10 @@ use hir::{ - db::HirDatabase, HasSource, HasVisibility, HirFileIdExt, ModuleDef, PathResolution, ScopeDef, + HasSource, HasVisibility, HirFileIdExt, ModuleDef, PathResolution, ScopeDef, db::HirDatabase, }; use ide_db::FileId; use syntax::{ - ast::{self, edit_in_place::HasVisibilityEdit, make, HasVisibility as _}, AstNode, TextRange, + ast::{self, HasVisibility as _, edit_in_place::HasVisibilityEdit, make}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs index 818a868fe3449..75133c3a023b8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs @@ -1,6 +1,6 @@ use syntax::{ - ast::{self, syntax_factory::SyntaxFactory, AstNode, BinExpr}, SyntaxKind, T, + ast::{self, AstNode, BinExpr, syntax_factory::SyntaxFactory}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs index dd27269b001c6..6900e94bdd23b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs @@ -1,8 +1,8 @@ use syntax::{ + AstNode, Direction, NodeOrToken, SyntaxKind, SyntaxToken, T, algo::non_trivia_sibling, ast::{self, syntax_factory::SyntaxFactory}, syntax_editor::SyntaxMapping, - AstNode, Direction, NodeOrToken, SyntaxKind, SyntaxToken, T, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs index d9fa03e7191b3..6ef8aa6a739e0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs @@ -1,7 +1,7 @@ use syntax::{ + Direction, T, algo::non_trivia_sibling, ast::{self, AstNode}, - Direction, T, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs index 3528f5e81324d..af40b09643a33 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs @@ -1,7 +1,7 @@ use syntax::{ + Direction, T, algo::non_trivia_sibling, ast::{self, AstNode}, - Direction, T, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs index 7f7db07152d34..2f4b6a0421bbf 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs @@ -1,14 +1,14 @@ use crate::assist_context::{AssistContext, Assists}; use hir::{HasVisibility, HirDisplay, HirFileIdExt, Module}; use ide_db::{ + FileId, assists::{AssistId, AssistKind}, base_db::Upcast, defs::{Definition, NameRefClass}, - FileId, }; use syntax::{ - ast::{self, edit::IndentLevel, NameRef}, AstNode, Direction, SyntaxKind, TextSize, + ast::{self, NameRef, edit::IndentLevel}, }; // Assist: generate_constant diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs index a6e3d49e0d1ae..c6725a013e3b6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs @@ -1,4 +1,4 @@ -use ide_db::{famous_defs::FamousDefs, RootDatabase}; +use ide_db::{RootDatabase, famous_defs::FamousDefs}; use syntax::ast::{self, AstNode, HasName}; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -77,11 +77,7 @@ fn existing_default_impl( let default_trait = FamousDefs(sema, krate).core_default_Default()?; let enum_type = enum_.ty(sema.db); - if enum_type.impls_trait(sema.db, default_trait, &[]) { - Some(()) - } else { - None - } + if enum_type.impls_trait(sema.db, default_trait, &[]) { Some(()) } else { None } } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs index dc27af5cbed20..1a4349cfea91b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs @@ -1,13 +1,13 @@ use ide_db::famous_defs::FamousDefs; use stdx::format_to; use syntax::{ - ast::{self, make, HasGenericParams, HasName, Impl}, AstNode, + ast::{self, HasGenericParams, HasName, Impl, make}, }; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, + assist_context::{AssistContext, Assists}, }; // Assist: generate_default_from_new diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs index 220259451e860..750f160ec2d23 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -1,15 +1,15 @@ use hir::{HasCrate, HasVisibility}; -use ide_db::{path_transform::PathTransform, FxHashSet}; +use ide_db::{FxHashSet, path_transform::PathTransform}; use syntax::{ ast::{ - self, edit_in_place::Indent, make, AstNode, HasGenericParams, HasName, HasVisibility as _, + self, AstNode, HasGenericParams, HasName, HasVisibility as _, edit_in_place::Indent, make, }, ted, }; use crate::{ - utils::{convert_param_list_to_arg_list, find_struct_impl}, AssistContext, AssistId, AssistKind, Assists, GroupLabel, + utils::{convert_param_list_to_arg_list, find_struct_impl}, }; // Assist: generate_delegate_methods diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs index 55b860d0ff545..5c39214617e49 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -5,25 +5,25 @@ use crate::{ utils::convert_param_list_to_arg_list, }; use either::Either; -use hir::{db::HirDatabase, HasVisibility}; +use hir::{HasVisibility, db::HirDatabase}; use ide_db::{ + FxHashMap, FxHashSet, assists::{AssistId, GroupLabel}, path_transform::PathTransform, syntax_helpers::suggest_name, - FxHashMap, FxHashSet, }; use itertools::Itertools; use syntax::{ + AstNode, Edition, NodeOrToken, SmolStr, SyntaxKind, ToSmolStr, ast::{ - self, - edit::{self, AstNodeEdit}, - edit_in_place::AttrsOwnerEdit, - make, AssocItem, GenericArgList, GenericParamList, HasAttrs, HasGenericArgs, + self, AssocItem, GenericArgList, GenericParamList, HasAttrs, HasGenericArgs, HasGenericParams, HasName, HasTypeBounds, HasVisibility as astHasVisibility, Path, WherePred, + edit::{self, AstNodeEdit}, + edit_in_place::AttrsOwnerEdit, + make, }, ted::{self, Position}, - AstNode, Edition, NodeOrToken, SmolStr, SyntaxKind, ToSmolStr, }; // Assist: generate_delegate_trait diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs index e558bb6da89bc..7bf29978128e0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs @@ -1,16 +1,16 @@ use std::fmt::Display; use hir::{ModPath, ModuleDef}; -use ide_db::{famous_defs::FamousDefs, RootDatabase}; +use ide_db::{RootDatabase, famous_defs::FamousDefs}; use syntax::{ - ast::{self, HasName}, AstNode, Edition, SyntaxNode, + ast::{self, HasName}, }; use crate::{ + AssistId, AssistKind, assist_context::{AssistContext, Assists, SourceChangeBuilder}, utils::generate_trait_impl_text, - AssistId, AssistKind, }; // Assist: generate_deref diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs index 53ba144ba9e3b..8b4dbeff7cf48 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs @@ -1,6 +1,6 @@ use syntax::{ - ast::{self, edit_in_place::AttrsOwnerEdit, make, AstNode, HasAttrs}, T, + ast::{self, AstNode, HasAttrs, edit_in_place::AttrsOwnerEdit, make}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs index 862be791d1737..df05c0d6b2f35 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs @@ -3,9 +3,10 @@ use ide_db::assists::{AssistId, AssistKind}; use itertools::Itertools; use stdx::{format_to, to_lower_snake_case}; use syntax::{ + AstNode, AstToken, Edition, algo::skip_whitespace_token, - ast::{self, edit::IndentLevel, HasDocComments, HasGenericArgs, HasName}, - match_ast, AstNode, AstToken, Edition, + ast::{self, HasDocComments, HasGenericArgs, HasName, edit::IndentLevel}, + match_ast, }; use crate::assist_context::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs index b5d3ed4369708..78fdca910c7a2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs @@ -4,8 +4,8 @@ use syntax::ast::HasVisibility; use syntax::ast::{self, AstNode, HasName}; use crate::{ - utils::{add_method_to_adt, find_struct_impl}, AssistContext, AssistId, AssistKind, Assists, + utils::{add_method_to_adt, find_struct_impl}, }; // Assist: generate_enum_is_method diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs index ee643ce9a4ac3..e96be673a1b6b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs @@ -5,8 +5,8 @@ use syntax::ast::HasVisibility; use syntax::ast::{self, AstNode, HasName}; use crate::{ - utils::{add_method_to_adt, find_struct_impl}, AssistContext, AssistId, AssistKind, Assists, + utils::{add_method_to_adt, find_struct_impl}, }; // Assist: generate_enum_try_into_method diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs index bb08cb904ead7..51b6a4be019dd 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs @@ -1,8 +1,9 @@ use hir::{HasSource, HirDisplay, InRealFile}; use ide_db::assists::{AssistId, AssistKind}; use syntax::{ - ast::{self, syntax_factory::SyntaxFactory, HasArgList}, - match_ast, AstNode, SyntaxNode, + AstNode, SyntaxNode, + ast::{self, HasArgList, syntax_factory::SyntaxFactory}, + match_ast, }; use crate::assist_context::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs index 9d01ec00f836c..bc890ac53b88b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs @@ -1,8 +1,9 @@ use either::Either; use ide_db::assists::{AssistId, AssistKind, GroupLabel}; use syntax::{ - ast::{self, edit::IndentLevel, make, HasGenericParams, HasName}, - syntax_editor, AstNode, + AstNode, + ast::{self, HasGenericParams, HasName, edit::IndentLevel, make}, + syntax_editor, }; use crate::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs index 6091f06b96699..88226820cf274 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs @@ -1,8 +1,8 @@ -use ide_db::{famous_defs::FamousDefs, RootDatabase}; +use ide_db::{RootDatabase, famous_defs::FamousDefs}; use syntax::ast::{self, AstNode, HasName}; use crate::{ - utils::generate_trait_impl_text_intransitive, AssistContext, AssistId, AssistKind, Assists, + AssistContext, AssistId, AssistKind, Assists, utils::generate_trait_impl_text_intransitive, }; // Assist: generate_from_impl_for_enum @@ -92,11 +92,7 @@ fn existing_from_impl( let wrapped_type = variant.fields(sema.db).first()?.ty(sema.db); - if enum_type.impls_trait(sema.db, from_trait, &[wrapped_type]) { - Some(()) - } else { - None - } + if enum_type.impls_trait(sema.db, from_trait, &[wrapped_type]) { Some(()) } else { None } } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs index 29bd8cf0d1a65..a74d477ec8950 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs @@ -4,26 +4,27 @@ use hir::{ }; use ide_db::base_db::salsa::AsDynDatabase; use ide_db::{ + FileId, FxHashMap, FxHashSet, RootDatabase, SnippetCap, defs::{Definition, NameRefClass}, famous_defs::FamousDefs, helpers::is_editable_crate, path_transform::PathTransform, source_change::SourceChangeBuilder, - FileId, FxHashMap, FxHashSet, RootDatabase, SnippetCap, }; use itertools::Itertools; use stdx::to_lower_snake_case; use syntax::{ + Edition, SyntaxKind, SyntaxNode, T, TextRange, ast::{ - self, edit::IndentLevel, edit_in_place::Indent, make, AstNode, BlockExpr, CallExpr, - HasArgList, HasGenericParams, HasModuleItem, HasTypeBounds, + self, AstNode, BlockExpr, CallExpr, HasArgList, HasGenericParams, HasModuleItem, + HasTypeBounds, edit::IndentLevel, edit_in_place::Indent, make, }, - ted, Edition, SyntaxKind, SyntaxNode, TextRange, T, + ted, }; use crate::{ - utils::{convert_reference_type, find_struct_impl}, AssistContext, AssistId, AssistKind, Assists, + utils::{convert_reference_type, find_struct_impl}, }; // Assist: generate_function @@ -179,9 +180,8 @@ fn add_func_to_accumulator( let edition = function_builder.target_edition; let func = function_builder.render(ctx.config.snippet_cap, edit); - if let Some(adt) = - adt_info - .and_then(|adt_info| if adt_info.impl_exists { None } else { Some(adt_info.adt) }) + if let Some(adt) = adt_info + .and_then(|adt_info| if adt_info.impl_exists { None } else { Some(adt_info.adt) }) { let name = make::ty_path(make::ext::ident_path(&format!( "{}", diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs index 1b16ba5fc8ff3..8183a11e1ba0c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs @@ -1,13 +1,14 @@ use ide_db::{famous_defs::FamousDefs, source_change::SourceChangeBuilder}; use stdx::{format_to, to_lower_snake_case}; use syntax::{ - ast::{self, edit_in_place::Indent, make, AstNode, HasName, HasVisibility}, - ted, TextRange, + TextRange, + ast::{self, AstNode, HasName, HasVisibility, edit_in_place::Indent, make}, + ted, }; use crate::{ - utils::{convert_reference_type, find_struct_impl, generate_impl}, AssistContext, AssistId, AssistKind, Assists, GroupLabel, + utils::{convert_reference_type, find_struct_impl, generate_impl}, }; // Assist: generate_setter diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs index 4439830947ade..ff4f388e39cb0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs @@ -1,9 +1,9 @@ use syntax::{ - ast::{self, edit_in_place::Indent, make, AstNode, HasName}, + ast::{self, AstNode, HasName, edit_in_place::Indent, make}, ted, }; -use crate::{utils, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists, utils}; fn insert_impl(impl_: ast::Impl, nominal: &ast::Adt) { let indent = nominal.indent_level(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs index ad422b25c39e0..d9ed8111c6f8d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs @@ -1,12 +1,12 @@ -use hir::{sym, HasSource, Name}; +use hir::{HasSource, Name, sym}; use syntax::{ - ast::{self, HasName}, AstNode, + ast::{self, HasName}, }; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, AssistKind, + assist_context::{AssistContext, Assists}, }; // Assist: generate_is_empty_from_len diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs index 6aa561ad7f037..8d107e412896e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs @@ -1,7 +1,8 @@ use ide_db::famous_defs::FamousDefs; use syntax::{ + AstNode, ast::{self, make}, - ted, AstNode, + ted, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs index 70d14d6b95d85..f14a4c1070751 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs @@ -2,13 +2,13 @@ use ide_db::{ imports::import_assets::item_for_path_search, use_trivial_constructor::use_trivial_constructor, }; use syntax::{ - ast::{self, edit_in_place::Indent, make, AstNode, HasName, HasVisibility, StructKind}, + ast::{self, AstNode, HasName, HasVisibility, StructKind, edit_in_place::Indent, make}, ted, }; use crate::{ - utils::{find_struct_impl, generate_impl}, AssistContext, AssistId, AssistKind, Assists, + utils::{find_struct_impl, generate_impl}, }; // Assist: generate_new diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs index 5f7350bc2812b..3470a4d660dce 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs @@ -1,13 +1,13 @@ use crate::assist_context::{AssistContext, Assists}; use ide_db::assists::AssistId; use syntax::{ + AstNode, SyntaxKind, T, ast::{ - self, + self, HasGenericParams, HasName, edit_in_place::{HasVisibilityEdit, Indent}, - make, HasGenericParams, HasName, + make, }, ted::{self, Position}, - AstNode, SyntaxKind, T, }; // NOTES : diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs index 5a791c58bfd52..b8381a8cce100 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs @@ -3,10 +3,12 @@ use std::collections::BTreeSet; use ast::make; use either::Either; use hir::{ + FileRange, PathResolution, Semantics, TypeInfo, db::{ExpandDatabase, HirDatabase}, - sym, FileRange, PathResolution, Semantics, TypeInfo, + sym, }; use ide_db::{ + EditionedFileId, RootDatabase, base_db::Crate, defs::Definition, imports::insert_use::remove_path_if_in_use_stmt, @@ -14,19 +16,19 @@ use ide_db::{ search::{FileReference, FileReferenceNode, SearchScope}, source_change::SourceChangeBuilder, syntax_helpers::{node_ext::expr_as_name_ref, prettify_macro_expansion}, - EditionedFileId, RootDatabase, }; -use itertools::{izip, Itertools}; +use itertools::{Itertools, izip}; use syntax::{ + AstNode, NodeOrToken, SyntaxKind, ast::{ - self, edit::IndentLevel, edit_in_place::Indent, HasArgList, HasGenericArgs, Pat, PathExpr, + self, HasArgList, HasGenericArgs, Pat, PathExpr, edit::IndentLevel, edit_in_place::Indent, }, - ted, AstNode, NodeOrToken, SyntaxKind, + ted, }; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, AssistKind, + assist_context::{AssistContext, Assists}, }; // Assist: inline_into_callers diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs index ca5882d0313ac..10f9652cfe91e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs @@ -1,5 +1,5 @@ use hir::HasCrate; -use syntax::{ast, AstNode}; +use syntax::{AstNode, ast}; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs index 36eed290dc88d..8b7aa8f4af34f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs @@ -1,17 +1,17 @@ use hir::{PathResolution, Semantics}; use ide_db::{ + EditionedFileId, RootDatabase, defs::Definition, search::{FileReference, FileReferenceNode, UsageSearchResult}, - EditionedFileId, RootDatabase, }; use syntax::{ - ast::{self, syntax_factory::SyntaxFactory, AstNode, AstToken, HasName}, SyntaxElement, TextRange, + ast::{self, AstNode, AstToken, HasName, syntax_factory::SyntaxFactory}, }; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, AssistKind, + assist_context::{AssistContext, Assists}, }; // Assist: inline_local_variable diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs index 76d465b011039..936b09d5a46ca 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs @@ -10,13 +10,14 @@ use ide_db::{ }; use itertools::Itertools; use syntax::{ - ast::{self, make, HasGenericParams, HasName}, - ted, AstNode, NodeOrToken, SyntaxNode, + AstNode, NodeOrToken, SyntaxNode, + ast::{self, HasGenericParams, HasName, make}, + ted, }; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, AssistKind, + assist_context::{AssistContext, Assists}, }; use super::inline_call::split_refs_and_uses; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs index e405af5533d5e..c8ec3da180b8f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs @@ -3,7 +3,7 @@ use ide_db::{ assists::{AssistId, AssistKind}, famous_defs::FamousDefs, }; -use syntax::{ast, AstNode}; +use syntax::{AstNode, ast}; use crate::assist_context::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs index 62909c586e3d4..587e76585f14a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs @@ -1,11 +1,11 @@ use ide_db::FxHashSet; use syntax::{ - ast::{self, edit_in_place::GenericParamsOwnerEdit, make, HasGenericParams}, - ted::{self, Position}, AstNode, TextRange, + ast::{self, HasGenericParams, edit_in_place::GenericParamsOwnerEdit, make}, + ted::{self, Position}, }; -use crate::{assist_context::SourceChangeBuilder, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists, assist_context::SourceChangeBuilder}; static ASSIST_NAME: &str = "introduce_named_lifetime"; static ASSIST_LABEL: &str = "Introduce named lifetime"; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs index 994e4a0eddaf6..d60106cc80423 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs @@ -1,6 +1,6 @@ use ide_db::syntax_helpers::suggest_name; use itertools::Itertools; -use syntax::ast::{self, syntax_factory::SyntaxFactory, AstNode, HasGenericParams, HasName}; +use syntax::ast::{self, AstNode, HasGenericParams, HasName, syntax_factory::SyntaxFactory}; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs index ac710503d8a0d..4273a85df5a6a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs @@ -1,13 +1,13 @@ use ide_db::syntax_helpers::node_ext::is_pattern_cond; use syntax::{ - ast::{self, AstNode}, T, + ast::{self, AstNode}, }; use crate::{ + AssistId, AssistKind, assist_context::{AssistContext, Assists}, utils::invert_boolean_expression_legacy, - AssistId, AssistKind, }; // Assist: invert_if diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs index 4171230836908..aae007577c245 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs @@ -1,19 +1,20 @@ use either::Either; use ide_db::imports::{ insert_use::{ImportGranularity, InsertUseConfig}, - merge_imports::{try_merge_imports, try_merge_trees, try_normalize_use_tree, MergeBehavior}, + merge_imports::{MergeBehavior, try_merge_imports, try_merge_trees, try_normalize_use_tree}, }; use itertools::Itertools; use syntax::{ + AstNode, SyntaxElement, SyntaxNode, algo::neighbor, ast::{self, edit_in_place::Removable}, - match_ast, ted, AstNode, SyntaxElement, SyntaxNode, + match_ast, ted, }; use crate::{ + AssistId, AssistKind, assist_context::{AssistContext, Assists}, utils::next_prev, - AssistId, AssistKind, }; use Edit::*; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs index f83de931eaba7..be73377070f3f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs @@ -2,9 +2,9 @@ use hir::Type; use ide_db::FxHashMap; use std::iter::successors; use syntax::{ + Direction, algo::neighbor, ast::{self, AstNode, HasName}, - Direction, }; use crate::{AssistContext, AssistId, AssistKind, Assists, TextRange}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_nested_if.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_nested_if.rs index 7a0037fa202bb..89bd62a084a3c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_nested_if.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_nested_if.rs @@ -1,12 +1,12 @@ use ide_db::syntax_helpers::node_ext::is_pattern_cond; use syntax::{ - ast::{self, AstNode, BinaryOp}, T, + ast::{self, AstNode, BinaryOp}, }; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, AssistKind, + assist_context::{AssistContext, Assists}, }; // Assist: merge_nested_if // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs index 5101d8fa0a9e3..35571ed8341d7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs @@ -1,8 +1,8 @@ use syntax::{ ast::{ - self, + self, AstNode, HasName, HasTypeBounds, edit_in_place::{GenericParamsOwnerEdit, Removable}, - make, AstNode, HasName, HasTypeBounds, + make, }, match_ast, }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs index 743ea9476150d..71b1461a6ea6c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs @@ -1,8 +1,8 @@ use hir::{AsAssocItem, AssocItemContainer, FileRange, HasCrate, HasSource}; use ide_db::{assists::AssistId, defs::Definition, search::SearchScope}; use syntax::{ - ast::{self, edit::IndentLevel, edit_in_place::Indent, AstNode}, SyntaxKind, + ast::{self, AstNode, edit::IndentLevel, edit_in_place::Indent}, }; use crate::assist_context::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs index 10915f8aafb8d..0d6fc49e5fe3d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs @@ -2,7 +2,7 @@ use ide_db::{ assists::{AssistId, AssistKind}, base_db::AnchoredPathBuf, }; -use syntax::{ast, AstNode, ToSmolStr}; +use syntax::{AstNode, ToSmolStr, ast}; use crate::{ assist_context::{AssistContext, Assists}, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs index a487960d8d4c5..abba3de4a1fa1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs @@ -1,6 +1,6 @@ use syntax::{ - ast::{edit::AstNodeEdit, make, AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat}, SyntaxKind::WHITESPACE, + ast::{AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat, edit::AstNodeEdit, make}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs index bbf18e21948eb..5f547593b43a9 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs @@ -1,13 +1,13 @@ use std::iter; use ast::edit::IndentLevel; -use hir::{sym, HasAttrs}; +use hir::{HasAttrs, sym}; use ide_db::base_db::AnchoredPathBuf; use itertools::Itertools; use stdx::format_to; use syntax::{ - ast::{self, edit::AstNodeEdit, HasName}, AstNode, SmolStr, TextRange, + ast::{self, HasName, edit::AstNodeEdit}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs index 7b38c795dc80f..a19c122ddf078 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs @@ -2,7 +2,7 @@ use ide_db::{ assists::{AssistId, AssistKind}, base_db::AnchoredPathBuf, }; -use syntax::{ast, AstNode, ToSmolStr}; +use syntax::{AstNode, ToSmolStr, ast}; use crate::{ assist_context::{AssistContext, Assists}, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs index 0b91eb676df01..813c2dd191dbd 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs @@ -1,9 +1,9 @@ use ide_db::imports::merge_imports::try_normalize_import; -use syntax::{ast, AstNode}; +use syntax::{AstNode, ast}; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, AssistKind, + assist_context::{AssistContext, Assists}, }; // Assist: normalize_import diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs index a13799f9b1317..9b81aecd7da84 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs @@ -1,4 +1,4 @@ -use syntax::{ast, ast::Radix, AstToken}; +use syntax::{AstToken, ast, ast::Radix}; use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs index 0cc771ff39791..04a19d7869c5e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs @@ -5,8 +5,9 @@ use ide_db::{ }; use stdx::to_upper_snake_case; use syntax::{ - ast::{self, make, HasName}, - ted, AstNode, + AstNode, + ast::{self, HasName, make}, + ted, }; use crate::{ diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/pull_assignment_up.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/pull_assignment_up.rs index f222b3eb903c4..d9e71ec763d01 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/pull_assignment_up.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/pull_assignment_up.rs @@ -1,11 +1,12 @@ use syntax::{ + AstNode, ast::{self, make}, - ted, AstNode, + ted, }; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, AssistKind, + assist_context::{AssistContext, Assists}, }; // Assist: pull_assignment_up diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs index c3600af5a6c58..d8ade0eb8718f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs @@ -1,6 +1,6 @@ -use hir::{db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, ItemInNs, ModuleDef}; +use hir::{AsAssocItem, AssocItem, AssocItemContainer, ItemInNs, ModuleDef, db::HirDatabase}; use ide_db::assists::{AssistId, AssistKind}; -use syntax::{ast, AstNode}; +use syntax::{AstNode, ast}; use crate::{ assist_context::{AssistContext, Assists}, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs index 2a8465f634cfb..a4f066ad364f8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs @@ -7,18 +7,17 @@ use ide_db::{ helpers::mod_path_to_ast, imports::import_assets::{ImportCandidate, LocatedImport}, }; -use syntax::ast::HasGenericArgs; use syntax::Edition; +use syntax::ast::HasGenericArgs; use syntax::{ - ast, - ast::{make, HasArgList}, - AstNode, NodeOrToken, + AstNode, NodeOrToken, ast, + ast::{HasArgList, make}, }; use crate::{ + AssistId, AssistKind, GroupLabel, assist_context::{AssistContext, Assists}, handlers::auto_import::find_importable_node, - AssistId, AssistKind, GroupLabel, }; // Assist: qualify_path diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs index 5a197f23d0e3a..21c697f538694 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs @@ -1,8 +1,8 @@ use std::borrow::Cow; -use syntax::{ast, ast::IsString, AstToken, TextRange, TextSize}; +use syntax::{AstToken, TextRange, TextSize, ast, ast::IsString}; -use crate::{utils::required_hashes, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists, utils::required_hashes}; // Assist: make_raw_string // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs index 1f57f7d3d3765..cbc2e4f004733 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs @@ -1,7 +1,8 @@ use itertools::Itertools; use syntax::{ - ast::{self, make, AstNode, AstToken}, - match_ast, ted, Edition, NodeOrToken, SyntaxElement, TextRange, TextSize, T, + Edition, NodeOrToken, SyntaxElement, T, TextRange, TextSize, + ast::{self, AstNode, AstToken, make}, + match_ast, ted, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs index e7beb23bf8e7f..9bd8decbedcdb 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs @@ -1,7 +1,7 @@ use syntax::{ + AstNode, SyntaxKind, T, ast::{self, syntax_factory::SyntaxFactory}, syntax_editor::Position, - AstNode, SyntaxKind, T, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs index 0570b447782ec..01c4eedd3e2d2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs @@ -3,13 +3,13 @@ use std::collections::hash_map::Entry; use hir::{FileRange, HirFileIdExt, InFile, InRealFile, Module, ModuleSource}; use ide_db::text_edit::TextRange; use ide_db::{ + FxHashMap, RootDatabase, defs::Definition, search::{FileReference, ReferenceCategory, SearchScope}, - FxHashMap, RootDatabase, }; use syntax::{ - ast::{self, Rename}, AstNode, + ast::{self, Rename}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs index 2d7722a654e8e..6ebc9007cf1cb 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs @@ -1,18 +1,18 @@ use ide_db::{ - base_db::salsa::AsDynDatabase, defs::Definition, search::FileReference, EditionedFileId, + EditionedFileId, base_db::salsa::AsDynDatabase, defs::Definition, search::FileReference, }; use syntax::{ + AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, T, TextRange, algo::{find_node_at_range, least_common_ancestor_element}, ast::{self, HasArgList}, syntax_editor::Element, - AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, T, }; use SyntaxKind::WHITESPACE; use crate::{ - assist_context::SourceChangeBuilder, utils::next_prev, AssistContext, AssistId, AssistKind, - Assists, + AssistContext, AssistId, AssistKind, Assists, assist_context::SourceChangeBuilder, + utils::next_prev, }; // Assist: remove_unused_param diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs index a79a82be45079..410e2bbbdffcd 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs @@ -1,7 +1,7 @@ use either::Either; use ide_db::FxHashMap; use itertools::Itertools; -use syntax::{ast, syntax_editor::SyntaxEditor, AstNode, SmolStr, SyntaxElement, ToSmolStr}; +use syntax::{AstNode, SmolStr, SyntaxElement, ToSmolStr, ast, syntax_editor::SyntaxEditor}; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs index c3404173eafe6..e254fb9949d49 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs @@ -2,8 +2,8 @@ use hir::{PathResolution, Semantics}; use ide_db::{FxHashMap, RootDatabase}; use itertools::Itertools; use syntax::{ - ast::{self, HasName}, AstNode, SyntaxElement, + ast::{self, HasName}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs index 4b20b35c44624..39f350fb68d5e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs @@ -1,7 +1,7 @@ use ide_db::assists::{AssistId, AssistKind, GroupLabel}; use syntax::{ - ast::{self, ArithOp, BinaryOp}, AstNode, TextRange, + ast::{self, ArithOp, BinaryOp}, }; use crate::assist_context::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index 31e828eae2712..7696a14a4f592 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -2,19 +2,19 @@ use hir::{InFile, MacroFileIdExt, ModuleDef}; use ide_db::{helpers::mod_path_to_ast, imports::import_assets::NameToImport, items_locator}; use itertools::Itertools; use syntax::{ - ast::{self, make, AstNode, HasName}, - ted, SyntaxKind::WHITESPACE, T, + ast::{self, AstNode, HasName, make}, + ted, }; use crate::{ + AssistId, AssistKind, assist_context::{AssistContext, Assists, SourceChangeBuilder}, utils::{ - add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body, generate_trait_impl, - DefaultMethods, IgnoreAssocItems, + DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items, + gen_trait_fn_body, generate_trait_impl, }, - AssistId, AssistKind, }; // Assist: replace_derive_with_manual_impl diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs index e324d6eaaad2f..c3b753653c212 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs @@ -2,19 +2,19 @@ use std::iter::successors; use either::Either; use ide_db::{ + RootDatabase, defs::NameClass, syntax_helpers::node_ext::{is_pattern_cond, single_let}, ty_filter::TryEnum, - RootDatabase, }; use syntax::{ - ast::{self, edit::IndentLevel, edit_in_place::Indent, syntax_factory::SyntaxFactory, HasName}, - AstNode, TextRange, T, + AstNode, T, TextRange, + ast::{self, HasName, edit::IndentLevel, edit_in_place::Indent, syntax_factory::SyntaxFactory}, }; use crate::{ - utils::{does_pat_match_variant, does_pat_variant_nested_or_literal, unwrap_trivial_block}, AssistContext, AssistId, AssistKind, Assists, + utils::{does_pat_match_variant, does_pat_variant_nested_or_literal, unwrap_trivial_block}, }; // Assist: replace_if_let_with_match diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs index 47972ff619acb..c49f285d8e9d3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs @@ -1,6 +1,6 @@ use ide_db::syntax_helpers::suggest_name; use syntax::{ - ast::{self, make, AstNode}, + ast::{self, AstNode, make}, ted, }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs index c071d3022d251..34bbd6ba5be7b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs @@ -1,7 +1,7 @@ use ide_db::ty_filter::TryEnum; use syntax::{ - ast::{self, edit::IndentLevel, edit_in_place::Indent, syntax_factory::SyntaxFactory}, AstNode, T, + ast::{self, edit::IndentLevel, edit_in_place::Indent, syntax_factory::SyntaxFactory}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs index 12d025f07594e..88b56ebb4b1cd 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs @@ -1,7 +1,7 @@ use ide_db::assists::{AssistId, AssistKind}; use syntax::{ - ast::{self, make, Expr, HasArgList}, AstNode, + ast::{self, Expr, HasArgList, make}, }; use crate::{AssistContext, Assists}; @@ -74,11 +74,7 @@ pub(crate) fn replace_with_lazy_method(acc: &mut Assists, ctx: &AssistContext<'_ fn into_closure(param: &Expr) -> Expr { (|| { if let ast::Expr::CallExpr(call) = param { - if call.arg_list()?.args().count() == 0 { - Some(call.expr()?) - } else { - None - } + if call.arg_list()?.args().count() == 0 { Some(call.expr()?) } else { None } } else { None } @@ -154,11 +150,7 @@ pub(crate) fn replace_with_eager_method(acc: &mut Assists, ctx: &AssistContext<' fn into_call(param: &Expr) -> Expr { (|| { if let ast::Expr::ClosureExpr(closure) = param { - if closure.param_list()?.params().count() == 0 { - Some(closure.body()?) - } else { - None - } + if closure.param_list()?.params().count() == 0 { Some(closure.body()?) } else { None } } else { None } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs index 26fd887cc99e9..f99394e8775e0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs @@ -1,16 +1,17 @@ use hir::{FileRange, Semantics}; use ide_db::text_edit::TextRange; use ide_db::{ + EditionedFileId, RootDatabase, defs::Definition, search::{SearchScope, UsageSearchResult}, - EditionedFileId, RootDatabase, }; use syntax::{ + AstNode, ast::{ - self, make::impl_trait_type, HasGenericParams, HasName, HasTypeBounds, Name, NameLike, - PathType, + self, HasGenericParams, HasName, HasTypeBounds, Name, NameLike, PathType, + make::impl_trait_type, }, - match_ast, ted, AstNode, + match_ast, ted, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs index f026b3230dd6d..08a4d28e9fea9 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs @@ -1,11 +1,12 @@ use hir::AsAssocItem; use ide_db::{ helpers::mod_path_to_ast, - imports::insert_use::{insert_use, ImportScope}, + imports::insert_use::{ImportScope, insert_use}, }; use syntax::{ - ast::{self, make, HasGenericArgs}, - match_ast, ted, AstNode, Edition, SyntaxNode, + AstNode, Edition, SyntaxNode, + ast::{self, HasGenericArgs, make}, + match_ast, ted, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs index a48b20acbcac8..176b4e4af088d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs @@ -1,9 +1,8 @@ use syntax::{ - ast, - ast::IsString, AstToken, SyntaxKind::{CHAR, STRING}, - TextRange, TextSize, + TextRange, TextSize, ast, + ast::IsString, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs index 88b50543dda87..93dfe48ebcab8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs @@ -5,12 +5,12 @@ use ide_db::{ ty_filter::TryEnum, }; use syntax::{ + AstNode, T, ast::{ self, edit::{AstNodeEdit, IndentLevel}, make, }, - AstNode, T, }; use crate::assist_context::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs index 3a6391cd38006..39ebca25a90f6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs @@ -1,12 +1,12 @@ use hir::HirDisplay; use syntax::{ - ast::{Expr, GenericArg, GenericArgList, HasGenericArgs, LetStmt, Type::InferType}, AstNode, TextRange, + ast::{Expr, GenericArg, GenericArgList, HasGenericArgs, LetStmt, Type::InferType}, }; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, AssistKind, + assist_context::{AssistContext, Assists}, }; // Assist: replace_turbofish_with_explicit_type diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs index 54e16d4d80a4c..73dfbf023792c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs @@ -3,11 +3,11 @@ use std::cmp::Ordering; use itertools::Itertools; use syntax::{ - ast::{self, HasName}, AstNode, SyntaxNode, + ast::{self, HasName}, }; -use crate::{utils::get_methods, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists, utils::get_methods}; // Assist: sort_items // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/split_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/split_import.rs index 775ededecbcc8..63371ddf9fbc5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/split_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/split_import.rs @@ -1,4 +1,4 @@ -use syntax::{ast, AstNode, T}; +use syntax::{AstNode, T, ast}; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs index e10897b3bef75..7b2598b45575d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs @@ -6,7 +6,7 @@ use ide_db::{ }; use itertools::Itertools; -use syntax::{ast, AstNode}; +use syntax::{AstNode, ast}; use crate::assist_context::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs index 8f937a04122d6..9f45b2898a769 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs @@ -4,8 +4,8 @@ use ide_db::{ famous_defs::FamousDefs, }; use syntax::{ - ast::{self, HasGenericArgs, HasVisibility}, AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, + ast::{self, HasGenericArgs, HasVisibility}, }; use crate::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs index 264a2f0326ecf..c1ea7dc4c78c5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs @@ -1,9 +1,9 @@ use syntax::{ - ast::{self, HasAttrs}, AstNode, AstToken, + ast::{self, HasAttrs}, }; -use crate::{utils::test_related_attribute_syn, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists, utils::test_related_attribute_syn}; // Assist: toggle_ignore // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs index e452b5f77870c..80834abecc95a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs @@ -1,7 +1,8 @@ use ide_db::assists::{AssistId, AssistKind}; use syntax::{ + AstNode, T, ast::{self, make}, - ted, AstNode, T, + ted, }; use crate::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs index 6b9f661d4de54..8b6aef02eccd0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs @@ -1,8 +1,8 @@ use syntax::{ + Direction, SyntaxKind, T, algo::neighbor, - ast::{self, edit::IndentLevel, make, AstNode}, + ast::{self, AstNode, edit::IndentLevel, make}, ted::{self, Position}, - Direction, SyntaxKind, T, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs index 38ca572fa6609..7f2dd19ce0755 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs @@ -1,12 +1,12 @@ use syntax::{ - ast::{self, edit_in_place::Removable, make, HasVisibility}, - ted::{self, Position}, AstNode, SyntaxKind, + ast::{self, HasVisibility, edit_in_place::Removable, make}, + ted::{self, Position}, }; use crate::{ - assist_context::{AssistContext, Assists}, AssistId, AssistKind, + assist_context::{AssistContext, Assists}, }; // Assist: unmerge_use diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs index abe7fb132f0b3..f3ae70160bf3a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs @@ -1,13 +1,13 @@ use ide_db::{ + EditionedFileId, assists::{AssistId, AssistKind}, defs::Definition, search::{FileReference, FileReferenceNode}, syntax_helpers::node_ext::full_path_of_name_ref, - EditionedFileId, }; use syntax::{ - ast::{self, NameRef}, AstNode, SyntaxKind, TextRange, + ast::{self, NameRef}, }; use crate::{AssistContext, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs index baf4ddae2fbc9..712c8c3d14d0f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs @@ -1,7 +1,7 @@ use ide_db::imports::insert_use::ImportScope; use syntax::{ - ast::{self, prec::ExprPrecedence, AstNode, HasArgList}, TextRange, + ast::{self, AstNode, HasArgList, prec::ExprPrecedence}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs index fd37140e9c2bf..80d8cebff5bb3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs @@ -1,10 +1,10 @@ use syntax::{ + AstNode, SyntaxKind, T, TextRange, ast::{ self, edit::{AstNodeEdit, IndentLevel}, make, }, - AstNode, SyntaxKind, TextRange, T, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs index f647b531b7742..f6eb68524f2df 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs @@ -4,8 +4,9 @@ use ide_db::{ syntax_helpers::node_ext::{for_each_tail_expr, walk_expr}, }; use syntax::{ - ast::{self, syntax_factory::SyntaxFactory, HasArgList, HasGenericArgs}, - match_ast, AstNode, NodeOrToken, SyntaxKind, + AstNode, NodeOrToken, SyntaxKind, + ast::{self, HasArgList, HasGenericArgs, syntax_factory::SyntaxFactory}, + match_ast, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs index d09614c51127e..55053ac97dc6e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs @@ -1,6 +1,6 @@ use syntax::{ - ast::{self, edit::AstNodeEdit}, AstNode, T, + ast::{self, edit::AstNodeEdit}, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs index 0b145dcb06ba3..8857c446f6d53 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs @@ -7,8 +7,9 @@ use ide_db::{ syntax_helpers::node_ext::{for_each_tail_expr, walk_expr}, }; use syntax::{ - ast::{self, syntax_factory::SyntaxFactory, Expr, HasGenericArgs, HasGenericParams}, - match_ast, AstNode, + AstNode, + ast::{self, Expr, HasGenericArgs, HasGenericParams, syntax_factory::SyntaxFactory}, + match_ast, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs index 149cb4c43849d..717c68d04e05b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs @@ -1,10 +1,9 @@ use ide_db::source_change::SourceChangeBuilder; use itertools::Itertools; use syntax::{ - algo, - ast::{self, make, AstNode}, + NodeOrToken, SyntaxToken, T, TextRange, algo, + ast::{self, AstNode, make}, ted::{self, Position}, - NodeOrToken, SyntaxToken, TextRange, T, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -296,11 +295,7 @@ fn unwrap_cfg_attr(acc: &mut Assists, attr: ast::Attr) -> Option<()> { continue; } let Some(attr_name) = tt.into_token().and_then(|token| { - if token.kind() == T![ident] { - Some(make::ext::ident_path(token.text())) - } else { - None - } + if token.kind() == T![ident] { Some(make::ext::ident_path(token.text())) } else { None } }) else { continue; }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs index 4f751b68e7f0b..a23461e69a5fc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -3,10 +3,10 @@ mod generated; use expect_test::expect; use hir::{FileRange, Semantics}; use ide_db::{ + EditionedFileId, RootDatabase, SnippetCap, base_db::SourceDatabase, imports::insert_use::{ImportGranularity, InsertUseConfig}, source_change::FileSystemEdit, - EditionedFileId, RootDatabase, SnippetCap, }; use stdx::{format_to, trim_indent}; use syntax::TextRange; @@ -14,8 +14,8 @@ use test_fixture::WithFixture; use test_utils::{assert_eq_text, extract_offset}; use crate::{ - assists, handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, - AssistResolveStrategy, Assists, SingleResolve, + Assist, AssistConfig, AssistContext, AssistKind, AssistResolveStrategy, Assists, SingleResolve, + assists, handlers::Handler, }; pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index a6fa1706710d1..0806d5feb13b2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -2,29 +2,29 @@ pub(crate) use gen_trait_fn_body::gen_trait_fn_body; use hir::{ - db::{ExpandDatabase, HirDatabase}, DisplayTarget, HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution, Semantics, + db::{ExpandDatabase, HirDatabase}, }; use ide_db::{ + RootDatabase, famous_defs::FamousDefs, path_transform::PathTransform, syntax_helpers::{node_ext::preorder_expr, prettify_macro_expansion}, - RootDatabase, }; use stdx::format_to; use syntax::{ + AstNode, AstToken, Direction, NodeOrToken, SourceFile, + SyntaxKind::*, + SyntaxNode, SyntaxToken, T, TextRange, TextSize, WalkEvent, ast::{ - self, + self, HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds, Whitespace, edit::{AstNodeEdit, IndentLevel}, edit_in_place::{AttrsOwnerEdit, Indent, Removable}, make, syntax_factory::SyntaxFactory, - HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds, Whitespace, }, - ted, AstNode, AstToken, Direction, NodeOrToken, SourceFile, - SyntaxKind::*, - SyntaxNode, SyntaxToken, TextRange, TextSize, WalkEvent, T, + ted, }; use crate::assist_context::{AssistContext, SourceChangeBuilder}; @@ -82,11 +82,7 @@ pub fn test_related_attribute_syn(fn_def: &ast::Fn) -> Option { fn_def.attrs().find_map(|attr| { let path = attr.path()?; let text = path.syntax().text().to_string(); - if text.starts_with("test") || text.ends_with("test") { - Some(attr) - } else { - None - } + if text.starts_with("test") || text.ends_with("test") { Some(attr) } else { None } }) } @@ -498,11 +494,7 @@ pub(crate) fn find_struct_impl( }; let not_trait_impl = blk.trait_(db).is_none(); - if !(same_ty && not_trait_impl) { - None - } else { - Some(impl_blk) - } + if !(same_ty && not_trait_impl) { None } else { Some(impl_blk) } }); if let Some(ref impl_blk) = block { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs index 7a9bdfe1ecc24..5c2e27b3430f4 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs @@ -2,7 +2,7 @@ use hir::TraitRef; use syntax::{ - ast::{self, edit::AstNodeEdit, make, AstNode, BinaryOp, CmpOp, HasName, LogicOp}, + ast::{self, AstNode, BinaryOp, CmpOp, HasName, LogicOp, edit::AstNodeEdit, make}, ted, }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs index d434872ea595e..28830cf2f92b3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs @@ -4,8 +4,8 @@ //! It determines whether to deref the new expression and/or wrap it in parentheses, //! based on the parent of the existing expression. use syntax::{ - ast::{self, make, FieldExpr, MethodCallExpr}, AstNode, T, + ast::{self, FieldExpr, MethodCallExpr, make}, }; use crate::AssistContext; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs index a22e7b272ea05..c8cdad594978d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs @@ -24,17 +24,19 @@ pub(crate) mod vis; use std::iter; -use hir::{sym, HasAttrs, Name, ScopeDef, Variant}; -use ide_db::{imports::import_assets::LocatedImport, RootDatabase, SymbolKind}; -use syntax::{ast, SmolStr, ToSmolStr}; +use hir::{HasAttrs, Name, ScopeDef, Variant, sym}; +use ide_db::{RootDatabase, SymbolKind, imports::import_assets::LocatedImport}; +use syntax::{SmolStr, ToSmolStr, ast}; use crate::{ + CompletionContext, CompletionItem, CompletionItemKind, context::{ DotAccess, ItemListKind, NameContext, NameKind, NameRefContext, NameRefKind, PathCompletionCtx, PathKind, PatternContext, TypeLocation, Visible, }, item::Builder, render::{ + RenderContext, const_::render_const, function::{render_fn, render_method}, literal::{render_struct_literal, render_variant_lit}, @@ -44,9 +46,7 @@ use crate::{ render_tuple_field, type_alias::{render_type_alias, render_type_alias_with_eq}, union_literal::render_union_literal, - RenderContext, }, - CompletionContext, CompletionItem, CompletionItemKind, }; /// Represents an in-progress set of completions being built. diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs index cf5427bae38de..fb7df8cc7f448 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs @@ -5,22 +5,22 @@ use std::sync::LazyLock; use ide_db::{ + FxHashMap, SymbolKind, generated::lints::{ - Lint, CLIPPY_LINTS, CLIPPY_LINT_GROUPS, DEFAULT_LINTS, FEATURES, RUSTDOC_LINTS, + CLIPPY_LINT_GROUPS, CLIPPY_LINTS, DEFAULT_LINTS, FEATURES, Lint, RUSTDOC_LINTS, }, syntax_helpers::node_ext::parse_tt_as_comma_sep_paths, - FxHashMap, SymbolKind, }; use itertools::Itertools; use syntax::{ - ast::{self, AttrKind}, AstNode, Edition, SyntaxKind, T, + ast::{self, AttrKind}, }; use crate::{ + Completions, context::{AttrCtx, CompletionContext, PathCompletionCtx, Qualified}, item::CompletionItem, - Completions, }; mod cfg; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs index cda0da13b26eb..1676a8467c85f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs @@ -2,9 +2,9 @@ use ide_db::SymbolKind; use itertools::Itertools; -use syntax::{algo, ast::Ident, AstToken, Direction, NodeOrToken, SyntaxKind}; +use syntax::{AstToken, Direction, NodeOrToken, SyntaxKind, algo, ast::Ident}; -use crate::{completions::Completions, context::CompletionContext, CompletionItem}; +use crate::{CompletionItem, completions::Completions, context::CompletionContext}; pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext<'_>) { let add_completion = |item: &str| { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/derive.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/derive.rs index 1f8927401b2f8..2fc07e0138280 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/derive.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/derive.rs @@ -1,13 +1,13 @@ //! Completion for derives use hir::ScopeDef; -use ide_db::{documentation::HasDocs, SymbolKind}; +use ide_db::{SymbolKind, documentation::HasDocs}; use itertools::Itertools; use syntax::{SmolStr, ToSmolStr}; use crate::{ + Completions, context::{CompletionContext, ExistingDerives, PathCompletionCtx, Qualified}, item::CompletionItem, - Completions, }; pub(crate) fn complete_derive_path( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/lint.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/lint.rs index 04f40e805ad68..c87c46d98127b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/lint.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/lint.rs @@ -1,8 +1,8 @@ //! Completion for lints -use ide_db::{documentation::Documentation, generated::lints::Lint, SymbolKind}; +use ide_db::{SymbolKind, documentation::Documentation, generated::lints::Lint}; use syntax::ast; -use crate::{context::CompletionContext, item::CompletionItem, Completions}; +use crate::{Completions, context::CompletionContext, item::CompletionItem}; pub(super) fn complete_lint( acc: &mut Completions, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/macro_use.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/macro_use.rs index deb12282c025b..0641a4f6c3fe5 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/macro_use.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/macro_use.rs @@ -3,7 +3,7 @@ use hir::ModuleDef; use ide_db::SymbolKind; use syntax::ast; -use crate::{context::CompletionContext, item::CompletionItem, Completions}; +use crate::{Completions, context::CompletionContext, item::CompletionItem}; pub(super) fn complete_macro_use( acc: &mut Completions, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/repr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/repr.rs index 12652b448925b..cb7ccf7373123 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/repr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/repr.rs @@ -3,7 +3,7 @@ use ide_db::SymbolKind; use syntax::ast; -use crate::{context::CompletionContext, item::CompletionItem, Completions}; +use crate::{Completions, context::CompletionContext, item::CompletionItem}; pub(super) fn complete_repr( acc: &mut Completions, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs index b38b9ac1f5391..dea983b6ea812 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs @@ -7,11 +7,11 @@ use ide_db::FxHashSet; use syntax::SmolStr; use crate::{ + CompletionItem, CompletionItemKind, Completions, context::{ CompletionContext, DotAccess, DotAccessExprCtx, DotAccessKind, PathCompletionCtx, PathExprCtx, Qualified, }, - CompletionItem, CompletionItemKind, Completions, }; /// Complete dot accesses, i.e. fields or methods. diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs index 40af5203e9c32..ab8d8a6169c94 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs @@ -3,34 +3,46 @@ use hir::MacroFileIdExt; use ide_db::syntax_helpers::node_ext::macro_call_for_string_token; use syntax::{ - ast::{self, IsString}, AstToken, + ast::{self, IsString}, }; use crate::{ - completions::Completions, context::CompletionContext, CompletionItem, CompletionItemKind, + CompletionItem, CompletionItemKind, completions::Completions, context::CompletionContext, }; const CARGO_DEFINED_VARS: &[(&str, &str)] = &[ - ("CARGO","Path to the cargo binary performing the build"), - ("CARGO_MANIFEST_DIR","The directory containing the manifest of your package"), - ("CARGO_PKG_VERSION","The full version of your package"), - ("CARGO_PKG_VERSION_MAJOR","The major version of your package"), - ("CARGO_PKG_VERSION_MINOR","The minor version of your package"), - ("CARGO_PKG_VERSION_PATCH","The patch version of your package"), - ("CARGO_PKG_VERSION_PRE","The pre-release version of your package"), - ("CARGO_PKG_AUTHORS","Colon separated list of authors from the manifest of your package"), - ("CARGO_PKG_NAME","The name of your package"), - ("CARGO_PKG_DESCRIPTION","The description from the manifest of your package"), - ("CARGO_PKG_HOMEPAGE","The home page from the manifest of your package"), - ("CARGO_PKG_REPOSITORY","The repository from the manifest of your package"), - ("CARGO_PKG_LICENSE","The license from the manifest of your package"), - ("CARGO_PKG_LICENSE_FILE","The license file from the manifest of your package"), - ("CARGO_PKG_RUST_VERSION","The Rust version from the manifest of your package. Note that this is the minimum Rust version supported by the package, not the current Rust version"), - ("CARGO_CRATE_NAME","The name of the crate that is currently being compiled"), - ("CARGO_BIN_NAME","The name of the binary that is currently being compiled (if it is a binary). This name does not include any file extension, such as .exe"), - ("CARGO_PRIMARY_PACKAGE","This environment variable will be set if the package being built is primary. Primary packages are the ones the user selected on the command-line, either with -p flags or the defaults based on the current directory and the default workspace members. This environment variable will not be set when building dependencies. This is only set when compiling the package (not when running binaries or tests)"), - ("CARGO_TARGET_TMPDIR","Only set when building integration test or benchmark code. This is a path to a directory inside the target directory where integration tests or benchmarks are free to put any data needed by the tests/benches. Cargo initially creates this directory but doesn't manage its content in any way, this is the responsibility of the test code") + ("CARGO", "Path to the cargo binary performing the build"), + ("CARGO_MANIFEST_DIR", "The directory containing the manifest of your package"), + ("CARGO_PKG_VERSION", "The full version of your package"), + ("CARGO_PKG_VERSION_MAJOR", "The major version of your package"), + ("CARGO_PKG_VERSION_MINOR", "The minor version of your package"), + ("CARGO_PKG_VERSION_PATCH", "The patch version of your package"), + ("CARGO_PKG_VERSION_PRE", "The pre-release version of your package"), + ("CARGO_PKG_AUTHORS", "Colon separated list of authors from the manifest of your package"), + ("CARGO_PKG_NAME", "The name of your package"), + ("CARGO_PKG_DESCRIPTION", "The description from the manifest of your package"), + ("CARGO_PKG_HOMEPAGE", "The home page from the manifest of your package"), + ("CARGO_PKG_REPOSITORY", "The repository from the manifest of your package"), + ("CARGO_PKG_LICENSE", "The license from the manifest of your package"), + ("CARGO_PKG_LICENSE_FILE", "The license file from the manifest of your package"), + ( + "CARGO_PKG_RUST_VERSION", + "The Rust version from the manifest of your package. Note that this is the minimum Rust version supported by the package, not the current Rust version", + ), + ("CARGO_CRATE_NAME", "The name of the crate that is currently being compiled"), + ( + "CARGO_BIN_NAME", + "The name of the binary that is currently being compiled (if it is a binary). This name does not include any file extension, such as .exe", + ), + ( + "CARGO_PRIMARY_PACKAGE", + "This environment variable will be set if the package being built is primary. Primary packages are the ones the user selected on the command-line, either with -p flags or the defaults based on the current directory and the default workspace members. This environment variable will not be set when building dependencies. This is only set when compiling the package (not when running binaries or tests)", + ), + ( + "CARGO_TARGET_TMPDIR", + "Only set when building integration test or benchmark code. This is a path to a directory inside the target directory where integration tests or benchmarks are free to put any data needed by the tests/benches. Cargo initially creates this directory but doesn't manage its content in any way, this is the responsibility of the test code", + ), ]; pub(crate) fn complete_cargo_env_vars( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index b28b6e50e2284..eb26543a4bd39 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -2,14 +2,14 @@ use std::ops::ControlFlow; -use hir::{sym, Name, PathCandidateCallback, ScopeDef}; +use hir::{Name, PathCandidateCallback, ScopeDef, sym}; use ide_db::FxHashSet; use syntax::ast; use crate::{ + CompletionContext, Completions, completions::record::add_default_update, context::{BreakableKind, PathCompletionCtx, PathExprCtx, Qualified}, - CompletionContext, Completions, }; struct PathCallback<'a, F> { @@ -79,11 +79,7 @@ pub(crate) fn complete_expr_path( let wants_const_token = ref_expr_parent.is_some() && has_raw_token && !has_const_token && !has_mut_token; let wants_mut_token = if ref_expr_parent.is_some() { - if has_raw_token { - !has_const_token && !has_mut_token - } else { - !has_mut_token - } + if has_raw_token { !has_const_token && !has_mut_token } else { !has_mut_token } } else { false }; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs index 7c2cc2a6c1d8f..570d1a0a2db8a 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs @@ -1,11 +1,11 @@ //! Completes function abi strings. use syntax::{ - ast::{self, IsString}, AstNode, AstToken, SmolStr, + ast::{self, IsString}, }; use crate::{ - completions::Completions, context::CompletionContext, CompletionItem, CompletionItemKind, + CompletionItem, CompletionItemKind, completions::Completions, context::CompletionContext, }; // Most of these are feature gated, we should filter/add feature gate completions once we have them. diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_crate.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_crate.rs index 7cb710c2d963c..71a3e4eb4ed6d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_crate.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_crate.rs @@ -1,10 +1,10 @@ //! Completion for extern crates use hir::Name; -use ide_db::{documentation::HasDocs, SymbolKind}; +use ide_db::{SymbolKind, documentation::HasDocs}; use syntax::ToSmolStr; -use crate::{context::CompletionContext, CompletionItem, CompletionItemKind}; +use crate::{CompletionItem, CompletionItemKind, context::CompletionContext}; use super::Completions; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/field.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/field.rs index b795bbd872a0a..1441b0e3a01ae 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/field.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/field.rs @@ -1,8 +1,8 @@ //! Completion of field list position. use crate::{ - context::{PathCompletionCtx, Qualified}, CompletionContext, Completions, + context::{PathCompletionCtx, Qualified}, }; pub(crate) fn complete_field_list_tuple_variant( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs index b5555e6610240..b3ba076489307 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs @@ -5,16 +5,16 @@ use ide_db::imports::{ insert_use::ImportScope, }; use itertools::Itertools; -use syntax::{ast, AstNode, SyntaxNode}; +use syntax::{AstNode, SyntaxNode, ast}; use crate::{ + Completions, config::AutoImportExclusionType, context::{ CompletionContext, DotAccess, PathCompletionCtx, PathKind, PatternContext, Qualified, TypeLocation, }, - render::{render_resolution_with_import, render_resolution_with_import_pat, RenderContext}, - Completions, + render::{RenderContext, render_resolution_with_import, render_resolution_with_import_pat}, }; // Feature: Completion With Autoimport @@ -404,11 +404,7 @@ fn import_on_the_fly_method( fn import_name(ctx: &CompletionContext<'_>) -> String { let token_kind = ctx.token.kind(); - if token_kind.is_any_identifier() { - ctx.token.to_string() - } else { - String::new() - } + if token_kind.is_any_identifier() { ctx.token.to_string() } else { String::new() } } fn import_assets_for_path( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs index e86eaad4d0f24..6d1e973dc4c5c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs @@ -3,14 +3,14 @@ use hir::HirDisplay; use ide_db::FxHashMap; use syntax::{ - algo, + AstNode, Direction, SyntaxKind, TextRange, TextSize, algo, ast::{self, HasModuleItem}, - match_ast, AstNode, Direction, SyntaxKind, TextRange, TextSize, + match_ast, }; use crate::{ - context::{ParamContext, ParamKind, PatternContext}, CompletionContext, CompletionItem, CompletionItemKind, Completions, + context::{ParamContext, ParamKind, PatternContext}, }; // FIXME: Make this a submodule of [`pattern`] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs index dcd40c3412c70..5ae65b05bc42e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs @@ -1,11 +1,11 @@ //! Completes identifiers in format string literals. use hir::{ModuleDef, ScopeDef}; -use ide_db::{syntax_helpers::format_string::is_format_string, SymbolKind}; +use ide_db::{SymbolKind, syntax_helpers::format_string::is_format_string}; use itertools::Itertools; -use syntax::{ast, AstToken, TextRange, TextSize, ToSmolStr}; +use syntax::{AstToken, TextRange, TextSize, ToSmolStr, ast}; -use crate::{context::CompletionContext, CompletionItem, CompletionItemKind, Completions}; +use crate::{CompletionItem, CompletionItemKind, Completions, context::CompletionContext}; /// Complete identifiers in format strings. pub(crate) fn format_string( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs index 3ab341e4eded4..4ae00ccd81bc6 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs @@ -1,8 +1,8 @@ //! Completion of paths and keywords at item list position. use crate::{ - context::{ItemListKind, PathCompletionCtx, PathExprCtx, Qualified}, CompletionContext, Completions, + context::{ItemListKind, PathCompletionCtx, PathExprCtx, Qualified}, }; pub(crate) mod trait_impl; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs index 831f5665f4aa0..e08271f39a325 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs @@ -31,20 +31,21 @@ //! } //! ``` -use hir::{db::ExpandDatabase, MacroFileId, Name}; +use hir::{MacroFileId, Name, db::ExpandDatabase}; use ide_db::text_edit::TextEdit; use ide_db::{ - documentation::HasDocs, path_transform::PathTransform, - syntax_helpers::prettify_macro_expansion, traits::get_missing_assoc_items, SymbolKind, + SymbolKind, documentation::HasDocs, path_transform::PathTransform, + syntax_helpers::prettify_macro_expansion, traits::get_missing_assoc_items, }; use syntax::{ - ast::{self, edit_in_place::AttrsOwnerEdit, make, HasGenericArgs, HasTypeBounds}, - format_smolstr, ted, AstNode, SmolStr, SyntaxElement, SyntaxKind, TextRange, ToSmolStr, T, + AstNode, SmolStr, SyntaxElement, SyntaxKind, T, TextRange, ToSmolStr, + ast::{self, HasGenericArgs, HasTypeBounds, edit_in_place::AttrsOwnerEdit, make}, + format_smolstr, ted, }; use crate::{ - context::PathCompletionCtx, CompletionContext, CompletionItem, CompletionItemKind, - CompletionRelevance, Completions, + CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance, Completions, + context::PathCompletionCtx, }; #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs index 53a62fe49c5aa..9bb2bea74b7d4 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs @@ -7,7 +7,7 @@ //! there is no value in lifting these out into the outline module test since they will either not //! show up for normal completions, or they won't show completions other than lifetimes depending //! on the fixture input. -use hir::{sym, Name, ScopeDef}; +use hir::{Name, ScopeDef, sym}; use crate::{ completions::Completions, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs index fad7c92d8aecb..dc81e49c531f3 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs @@ -4,12 +4,12 @@ use std::iter; use hir::{HirFileIdExt, Module}; use ide_db::{ - base_db::{SourceDatabase, VfsPath}, FxHashSet, RootDatabase, SymbolKind, + base_db::{SourceDatabase, VfsPath}, }; -use syntax::{ast, AstNode, SyntaxKind}; +use syntax::{AstNode, SyntaxKind, ast}; -use crate::{context::CompletionContext, CompletionItem, Completions}; +use crate::{CompletionItem, Completions, context::CompletionContext}; /// Complete mod declaration, i.e. `mod $0;` pub(crate) fn complete_mod( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs index 9df13c5a4ef53..59ef94d83b30e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs @@ -5,8 +5,8 @@ use ide_db::syntax_helpers::suggest_name; use syntax::ast::Pat; use crate::{ - context::{PathCompletionCtx, PatternContext, PatternRefutability, Qualified}, CompletionContext, Completions, + context::{PathCompletionCtx, PatternContext, PatternRefutability, Qualified}, }; /// Completes constants and paths in unqualified patterns. diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs index 611f8a2873d7b..eb84debcafb35 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs @@ -5,24 +5,24 @@ mod format_like; use base_db::SourceDatabase; use hir::{ItemInNs, Semantics}; use ide_db::{ + RootDatabase, SnippetCap, documentation::{Documentation, HasDocs}, imports::insert_use::ImportScope, text_edit::TextEdit, ty_filter::TryEnum, - RootDatabase, SnippetCap, }; use stdx::never; use syntax::{ - ast::{self, AstNode, AstToken}, SyntaxKind::{BLOCK_EXPR, EXPR_STMT, FOR_EXPR, IF_EXPR, LOOP_EXPR, STMT_LIST, WHILE_EXPR}, TextRange, TextSize, + ast::{self, AstNode, AstToken}, }; use crate::{ + CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope, completions::postfix::format_like::add_format_like_completions, context::{BreakableKind, CompletionContext, DotAccess, DotAccessKind}, item::{Builder, CompletionRelevancePostfixMatch}, - CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope, }; pub(crate) fn complete_postfix( @@ -414,8 +414,8 @@ mod tests { use expect_test::expect; use crate::{ - tests::{check, check_edit, check_edit_with_config, TEST_CONFIG}, CompletionConfig, Snippet, + tests::{TEST_CONFIG, check, check_edit, check_edit_with_config}, }; #[test] @@ -697,15 +697,17 @@ fn main() { #[test] fn custom_postfix_completion() { let config = CompletionConfig { - snippets: vec![Snippet::new( - &[], - &["break".into()], - &["ControlFlow::Break(${receiver})".into()], - "", - &["core::ops::ControlFlow".into()], - crate::SnippetScope::Expr, - ) - .unwrap()], + snippets: vec![ + Snippet::new( + &[], + &["break".into()], + &["ControlFlow::Break(${receiver})".into()], + "", + &["core::ops::ControlFlow".into()], + crate::SnippetScope::Expr, + ) + .unwrap(), + ], ..TEST_CONFIG }; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs index c612170eb54bc..7faa1139595f8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs @@ -17,15 +17,15 @@ // ![Format String Completion](https://user-images.githubusercontent.com/48062697/113020656-b560f500-917a-11eb-87de-02991f61beb8.gif) use ide_db::{ - syntax_helpers::format_string_exprs::{parse_format_exprs, with_placeholders, Arg}, SnippetCap, + syntax_helpers::format_string_exprs::{Arg, parse_format_exprs, with_placeholders}, }; -use syntax::{ast, AstToken}; +use syntax::{AstToken, ast}; use crate::{ + Completions, completions::postfix::{build_postfix_snippet_builder, escape_snippet_bits}, context::CompletionContext, - Completions, }; /// Mapping ("postfix completion item" => "macro to use") diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs index d0c4c24d060f8..c18aab007b2cf 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs @@ -1,14 +1,14 @@ //! Complete fields in record literals and patterns. use ide_db::SymbolKind; use syntax::{ - ast::{self, Expr}, SmolStr, + ast::{self, Expr}, }; use crate::{ - context::{DotAccess, DotAccessExprCtx, DotAccessKind, PatternContext}, CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch, Completions, + context::{DotAccess, DotAccessExprCtx, DotAccessKind, PatternContext}, }; pub(crate) fn complete_record_pattern_fields( @@ -144,8 +144,8 @@ mod tests { use ide_db::SnippetCap; use crate::{ - tests::{check_edit, check_edit_with_config, TEST_CONFIG}, CompletionConfig, + tests::{TEST_CONFIG, check_edit, check_edit_with_config}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs index 357709e0c1fde..31aae11676228 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs @@ -1,11 +1,11 @@ //! This file provides snippet completions, like `pd` => `eprintln!(...)`. -use ide_db::{documentation::Documentation, imports::insert_use::ImportScope, SnippetCap}; +use ide_db::{SnippetCap, documentation::Documentation, imports::insert_use::ImportScope}; use crate::{ + CompletionContext, CompletionItem, CompletionItemKind, Completions, SnippetScope, context::{ItemListKind, PathCompletionCtx, PathExprCtx, Qualified}, item::Builder, - CompletionContext, CompletionItem, CompletionItemKind, Completions, SnippetScope, }; pub(crate) fn complete_expr_snippet( @@ -153,23 +153,25 @@ fn add_custom_completions( #[cfg(test)] mod tests { use crate::{ - tests::{check_edit_with_config, TEST_CONFIG}, CompletionConfig, Snippet, + tests::{TEST_CONFIG, check_edit_with_config}, }; #[test] fn custom_snippet_completion() { check_edit_with_config( CompletionConfig { - snippets: vec![Snippet::new( - &["break".into()], - &[], - &["ControlFlow::Break(())".into()], - "", - &["core::ops::ControlFlow".into()], - crate::SnippetScope::Expr, - ) - .unwrap()], + snippets: vec![ + Snippet::new( + &["break".into()], + &[], + &["ControlFlow::Break(())".into()], + "", + &["core::ops::ControlFlow".into()], + crate::SnippetScope::Expr, + ) + .unwrap(), + ], ..TEST_CONFIG }, "break", diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs index b07148809323f..79db705af495d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs @@ -1,12 +1,12 @@ //! Completion of names from the current scope in type position. use hir::{HirDisplay, ScopeDef}; -use syntax::{ast, AstNode}; +use syntax::{AstNode, ast}; use crate::{ + CompletionContext, Completions, context::{PathCompletionCtx, Qualified, TypeAscriptionTarget, TypeLocation}, render::render_type_inference, - CompletionContext, Completions, }; pub(crate) fn complete_type_path( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs index b384987c51ce1..4d6d0b758a381 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs @@ -2,12 +2,12 @@ use hir::ScopeDef; use ide_db::{FxHashSet, SymbolKind}; -use syntax::{ast, format_smolstr, AstNode}; +use syntax::{AstNode, ast, format_smolstr}; use crate::{ + CompletionItem, CompletionItemKind, CompletionRelevance, Completions, context::{CompletionContext, PathCompletionCtx, Qualified}, item::Builder, - CompletionItem, CompletionItemKind, CompletionRelevance, Completions, }; pub(crate) fn complete_use_path( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/vis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/vis.rs index 0ea5157fb46fe..d15c35ac84991 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/vis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/vis.rs @@ -1,8 +1,8 @@ //! Completion for visibility specifiers. use crate::{ - context::{CompletionContext, PathCompletionCtx, Qualified}, Completions, + context::{CompletionContext, PathCompletionCtx, Qualified}, }; pub(crate) fn complete_vis_path( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs index 45aab38e8ea09..844fce5ef8019 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs @@ -5,9 +5,9 @@ //! completions if we are allowed to. use hir::ImportPathConfig; -use ide_db::{imports::insert_use::InsertUseConfig, SnippetCap}; +use ide_db::{SnippetCap, imports::insert_use::InsertUseConfig}; -use crate::{snippet::Snippet, CompletionFieldsToResolve}; +use crate::{CompletionFieldsToResolve, snippet::Snippet}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct CompletionConfig<'a> { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index 54620bbad1bce..aa0b6060f6f1d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -6,26 +6,27 @@ mod tests; use std::{iter, ops::ControlFlow}; -use base_db::{salsa::AsDynDatabase, RootQueryDb as _}; +use base_db::{RootQueryDb as _, salsa::AsDynDatabase}; use hir::{ DisplayTarget, HasAttrs, Local, ModPath, ModuleDef, ModuleSource, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Symbol, Type, TypeInfo, }; use ide_db::{ - famous_defs::FamousDefs, helpers::is_editable_crate, FilePosition, FxHashMap, FxHashSet, - RootDatabase, + FilePosition, FxHashMap, FxHashSet, RootDatabase, famous_defs::FamousDefs, + helpers::is_editable_crate, }; use syntax::{ - ast::{self, AttrKind, NameOrNameRef}, - match_ast, AstNode, Edition, SmolStr, + AstNode, Edition, SmolStr, SyntaxKind::{self, *}, - SyntaxToken, TextRange, TextSize, T, + SyntaxToken, T, TextRange, TextSize, + ast::{self, AttrKind, NameOrNameRef}, + match_ast, }; use crate::{ - config::AutoImportExclusionType, - context::analysis::{expand_and_analyze, AnalysisResult}, CompletionConfig, + config::AutoImportExclusionType, + context::analysis::{AnalysisResult, expand_and_analyze}, }; const COMPLETION_MARKER: &str = "raCompletionMarker"; @@ -676,11 +677,7 @@ impl CompletionContext<'_> { }; } - if self.is_doc_hidden(attrs, defining_crate) { - Visible::No - } else { - Visible::Yes - } + if self.is_doc_hidden(attrs, defining_crate) { Visible::No } else { Visible::Yes } } pub(crate) fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs index 1a34548f70824..8f58c2181ef45 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs @@ -2,24 +2,25 @@ use std::iter; use hir::{ExpandResult, Semantics, Type, TypeInfo, Variant}; -use ide_db::{active_parameter::ActiveParameter, RootDatabase}; +use ide_db::{RootDatabase, active_parameter::ActiveParameter}; use itertools::Either; use syntax::{ + AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, + T, TextRange, TextSize, algo::{self, ancestors_at_offset, find_node_at_offset, non_trivia_sibling}, ast::{ self, AttrKind, HasArgList, HasGenericArgs, HasGenericParams, HasLoopBody, HasName, NameOrNameRef, }, - match_ast, AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, - SyntaxToken, TextRange, TextSize, T, + match_ast, }; use crate::context::{ - AttrCtx, BreakableKind, CompletionAnalysis, DotAccess, DotAccessExprCtx, DotAccessKind, - ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, NameRefContext, - NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathExprCtx, PathKind, PatternContext, - PatternRefutability, Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation, - COMPLETION_MARKER, + AttrCtx, BreakableKind, COMPLETION_MARKER, CompletionAnalysis, DotAccess, DotAccessExprCtx, + DotAccessKind, ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, + NameRefContext, NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathExprCtx, PathKind, + PatternContext, PatternRefutability, Qualified, QualifierCtx, TypeAscriptionTarget, + TypeLocation, }; #[derive(Debug)] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs index a03f632cdfdfa..72bcbf366d2ed 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs @@ -1,9 +1,9 @@ -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use hir::HirDisplay; use crate::{ context::CompletionContext, - tests::{position, TEST_CONFIG}, + tests::{TEST_CONFIG, position}, }; fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index 8d6dc4c801301..e208b9fd41ae2 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -5,17 +5,17 @@ use std::{fmt, mem}; use hir::Mutability; use ide_db::text_edit::TextEdit; use ide_db::{ - documentation::Documentation, imports::import_assets::LocatedImport, RootDatabase, SnippetCap, - SymbolKind, + RootDatabase, SnippetCap, SymbolKind, documentation::Documentation, + imports::import_assets::LocatedImport, }; use itertools::Itertools; use smallvec::SmallVec; use stdx::{format_to, impl_from, never}; -use syntax::{format_smolstr, Edition, SmolStr, TextRange, TextSize}; +use syntax::{Edition, SmolStr, TextRange, TextSize, format_smolstr}; use crate::{ context::{CompletionContext, PathCompletionCtx}, - render::{render_path_resolution, RenderContext}, + render::{RenderContext, render_path_resolution}, }; /// `CompletionItem` describes a single completion entity which expands to 1 or more entries in the diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs index c9fc5ae152400..8d8dfb083e405 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs @@ -11,11 +11,11 @@ mod snippet; mod tests; use ide_db::{ + FilePosition, FxHashSet, RootDatabase, base_db::salsa::AsDynDatabase, imports::insert_use::{self, ImportScope}, syntax_helpers::tree_diff::diff, text_edit::TextEdit, - FilePosition, FxHashSet, RootDatabase, }; use syntax::ast::make; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 0f0fa115af0b3..54094a8f8e3ba 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -10,17 +10,19 @@ pub(crate) mod type_alias; pub(crate) mod union_literal; pub(crate) mod variant; -use hir::{sym, AsAssocItem, HasAttrs, HirDisplay, ModuleDef, ScopeDef, Type}; +use hir::{AsAssocItem, HasAttrs, HirDisplay, ModuleDef, ScopeDef, Type, sym}; use ide_db::text_edit::TextEdit; use ide_db::{ + RootDatabase, SnippetCap, SymbolKind, documentation::{Documentation, HasDocs}, helpers::item_name, imports::import_assets::LocatedImport, - RootDatabase, SnippetCap, SymbolKind, }; -use syntax::{ast, format_smolstr, AstNode, SmolStr, SyntaxKind, TextRange, ToSmolStr}; +use syntax::{AstNode, SmolStr, SyntaxKind, TextRange, ToSmolStr, ast, format_smolstr}; use crate::{ + CompletionContext, CompletionItem, CompletionItemKind, CompletionItemRefMode, + CompletionRelevance, context::{DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext}, item::{Builder, CompletionRelevanceTypeMatch}, render::{ @@ -28,8 +30,6 @@ use crate::{ literal::render_variant_lit, macro_::{render_macro, render_macro_pat}, }, - CompletionContext, CompletionItem, CompletionItemKind, CompletionItemRefMode, - CompletionRelevance, }; /// Interface for data and methods required for items rendering. #[derive(Debug, Clone)] @@ -683,14 +683,14 @@ fn path_ref_match( mod tests { use std::cmp; - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use ide_db::SymbolKind; use itertools::Itertools; use crate::{ - item::CompletionRelevanceTypeMatch, - tests::{check_edit, do_completion, get_all_items, TEST_CONFIG}, CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch, + item::CompletionRelevanceTypeMatch, + tests::{TEST_CONFIG, check_edit, do_completion, get_all_items}, }; #[track_caller] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index 4693bdc047f97..dd0f24522fc9b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -1,12 +1,13 @@ //! Renderer for function calls. -use hir::{db::HirDatabase, AsAssocItem, HirDisplay}; +use hir::{AsAssocItem, HirDisplay, db::HirDatabase}; use ide_db::{SnippetCap, SymbolKind}; use itertools::Itertools; use stdx::{format_to, to_lower_snake_case}; -use syntax::{format_smolstr, AstNode, SmolStr, ToSmolStr}; +use syntax::{AstNode, SmolStr, ToSmolStr, format_smolstr}; use crate::{ + CallableSnippets, context::{ CompleteSemicolon, CompletionContext, DotAccess, DotAccessKind, PathCompletionCtx, PathKind, }, @@ -15,9 +16,8 @@ use crate::{ CompletionRelevanceReturnType, CompletionRelevanceTraitInfo, }, render::{ - compute_exact_name_match, compute_ref_match, compute_type_match, match_types, RenderContext, + RenderContext, compute_exact_name_match, compute_ref_match, compute_type_match, match_types, }, - CallableSnippets, }; #[derive(Debug)] @@ -293,11 +293,7 @@ fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'sta for (name, local) in ctx.locals.iter().sorted_by_key(|&(k, _)| k.clone()) { if name.as_str() == arg { return if local.ty(ctx.db) == derefed_ty { - if ty.is_mutable_reference() { - "&mut " - } else { - "&" - } + if ty.is_mutable_reference() { "&mut " } else { "&" } } else { "" }; @@ -398,8 +394,8 @@ fn params( #[cfg(test)] mod tests { use crate::{ - tests::{check_edit, check_edit_with_config, TEST_CONFIG}, CallableSnippets, CompletionConfig, + tests::{TEST_CONFIG, check_edit, check_edit_with_config}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs index ffda52fb47852..5a9e35a7290bf 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs @@ -1,23 +1,22 @@ //! Renderer for `enum` variants. -use hir::{db::HirDatabase, StructKind}; +use hir::{StructKind, db::HirDatabase}; use ide_db::{ - documentation::{Documentation, HasDocs}, SymbolKind, + documentation::{Documentation, HasDocs}, }; use crate::{ + CompletionItemKind, CompletionRelevance, CompletionRelevanceReturnType, context::{CompletionContext, PathCompletionCtx, PathKind}, item::{Builder, CompletionItem, CompletionRelevanceFn}, render::{ - compute_type_match, + RenderContext, compute_type_match, variant::{ - format_literal_label, format_literal_lookup, render_record_lit, render_tuple_lit, - visible_fields, RenderedLiteral, + RenderedLiteral, format_literal_label, format_literal_lookup, render_record_lit, + render_tuple_lit, visible_fields, }, - RenderContext, }, - CompletionItemKind, CompletionRelevance, CompletionRelevanceReturnType, }; pub(crate) fn render_variant_lit( @@ -164,11 +163,7 @@ impl Variant { Variant::Struct(it) => visible_fields(ctx, &fields, it)?, Variant::EnumVariant(it) => visible_fields(ctx, &fields, it)?, }; - if !fields_omitted { - Some(visible_fields) - } else { - None - } + if !fields_omitted { Some(visible_fields) } else { None } } fn kind(self, db: &dyn HirDatabase) -> StructKind { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs index 8b2476d153f1f..4674dae031440 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs @@ -1,8 +1,8 @@ //! Renderer for macro invocations. use hir::HirDisplay; -use ide_db::{documentation::Documentation, SymbolKind}; -use syntax::{format_smolstr, SmolStr, ToSmolStr}; +use ide_db::{SymbolKind, documentation::Documentation}; +use syntax::{SmolStr, ToSmolStr, format_smolstr}; use crate::{ context::{PathCompletionCtx, PathKind, PatternContext}, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs index 124abb17b6a1c..93e6c5237948f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs @@ -1,17 +1,17 @@ //! Renderer for patterns. -use hir::{db::HirDatabase, Name, StructKind}; -use ide_db::{documentation::HasDocs, SnippetCap}; +use hir::{Name, StructKind, db::HirDatabase}; +use ide_db::{SnippetCap, documentation::HasDocs}; use itertools::Itertools; use syntax::{Edition, SmolStr, ToSmolStr}; use crate::{ + CompletionItem, CompletionItemKind, context::{ParamContext, ParamKind, PathCompletionCtx, PatternContext}, render::{ - variant::{format_literal_label, format_literal_lookup, visible_fields}, RenderContext, + variant::{format_literal_label, format_literal_lookup, visible_fields}, }, - CompletionItem, CompletionItemKind, }; pub(crate) fn render_struct_pat( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs index 09154e81c0304..23f0d4e06f2c8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs @@ -6,11 +6,11 @@ use itertools::Itertools; use syntax::ToSmolStr; use crate::{ + CompletionItem, CompletionItemKind, render::{ - variant::{format_literal_label, format_literal_lookup, visible_fields}, RenderContext, + variant::{format_literal_label, format_literal_lookup, visible_fields}, }, - CompletionItem, CompletionItemKind, }; pub(crate) fn render_union_literal( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs index 83718e57229a5..5d7d68bb3d660 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs @@ -1,7 +1,7 @@ //! Code common to structs, unions, and enum variants. use crate::context::CompletionContext; -use hir::{sym, HasAttrs, HasCrate, HasVisibility, HirDisplay, StructKind}; +use hir::{HasAttrs, HasCrate, HasVisibility, HirDisplay, StructKind, sym}; use ide_db::SnippetCap; use itertools::Itertools; use syntax::SmolStr; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs index 2984348a3278d..85987f0de59ff 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs @@ -28,8 +28,8 @@ use base_db::SourceDatabase; use expect_test::Expect; use hir::PrefixKind; use ide_db::{ - imports::insert_use::{ImportGranularity, InsertUseConfig}, FilePosition, RootDatabase, SnippetCap, + imports::insert_use::{ImportGranularity, InsertUseConfig}, }; use itertools::Itertools; use stdx::{format_to, trim_indent}; @@ -37,8 +37,8 @@ use test_fixture::ChangeFixture; use test_utils::assert_eq_text; use crate::{ - resolve_completion_edits, CallableSnippets, CompletionConfig, CompletionFieldsToResolve, - CompletionItem, CompletionItemKind, + CallableSnippets, CompletionConfig, CompletionFieldsToResolve, CompletionItem, + CompletionItemKind, resolve_completion_edits, }; /// Lots of basic item definitions diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index 9b3c676c48a1f..61823811dcc7d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -1,13 +1,13 @@ //! Completion tests for expressions. -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use crate::{ + CompletionConfig, config::AutoImportExclusionType, tests::{ - check, check_edit, check_with_base_items, completion_list_with_config, BASE_ITEMS_FIXTURE, - TEST_CONFIG, + BASE_ITEMS_FIXTURE, TEST_CONFIG, check, check_edit, check_with_base_items, + completion_list_with_config, }, - CompletionConfig, }; fn check_with_config( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index 2e7c53def7fc5..8bba44c12bf60 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -1,9 +1,9 @@ -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use crate::{ - context::{CompletionAnalysis, NameContext, NameKind, NameRefKind}, - tests::{check_edit, check_edit_with_config, TEST_CONFIG}, CompletionConfig, + context::{CompletionAnalysis, NameContext, NameKind, NameRefKind}, + tests::{TEST_CONFIG, check_edit, check_edit_with_config}, }; fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs index 823cc8c3d8c55..00977ea4e533b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs @@ -1,8 +1,8 @@ use base_db::SourceDatabase; -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use itertools::Itertools; -use crate::tests::{completion_list_with_config_raw, position, TEST_CONFIG}; +use crate::tests::{TEST_CONFIG, completion_list_with_config_raw, position}; fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let completions = completion_list_with_config_raw(TEST_CONFIG, ra_fixture, true, None); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs index 005263d100a5b..355f04bf0aa88 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -1,14 +1,14 @@ //! Tests that don't fit into a specific category. -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use ide_db::SymbolKind; use crate::{ + CompletionItemKind, tests::{ - check, check_edit, check_no_kw, check_with_trigger_character, do_completion_with_config, - TEST_CONFIG, + TEST_CONFIG, check, check_edit, check_no_kw, check_with_trigger_character, + do_completion_with_config, }, - CompletionItemKind, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs index 11808fed3be6a..06ed4afdf9be3 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs @@ -4,8 +4,9 @@ use either::Either; use hir::{InFile, Semantics, Type}; use parser::T; use syntax::{ + AstNode, NodeOrToken, SyntaxToken, ast::{self, AstChildren, HasArgList, HasAttrs, HasName}, - match_ast, AstNode, NodeOrToken, SyntaxToken, + match_ast, }; use crate::RootDatabase; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs index 4e058bb0106a2..36745b012b00d 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs @@ -6,7 +6,7 @@ use rustc_hash::FxHashSet; use salsa::{Database as _, Durability}; use triomphe::Arc; -use crate::{symbol_index::SymbolsDatabase, ChangeWithProcMacros, RootDatabase}; +use crate::{ChangeWithProcMacros, RootDatabase, symbol_index::SymbolsDatabase}; impl RootDatabase { pub fn request_cancellation(&mut self) { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index 502314ed1e0ec..18126f616c9ec 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -5,9 +5,9 @@ // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). +use crate::RootDatabase; use crate::documentation::{Documentation, HasDocs}; use crate::famous_defs::FamousDefs; -use crate::RootDatabase; use arrayvec::ArrayVec; use either::Either; use hir::{ @@ -21,8 +21,9 @@ use hir::{ use span::Edition; use stdx::{format_to, impl_from}; use syntax::{ + SyntaxKind, SyntaxNode, SyntaxToken, ast::{self, AstNode}, - match_ast, SyntaxKind, SyntaxNode, SyntaxToken, + match_ast, }; // FIXME: a more precise name would probably be `Symbol`? diff --git a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs index b83efcd02f772..96654a2416b65 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs @@ -1,14 +1,15 @@ //! Documentation attribute related utilities. use either::Either; use hir::{ + AttrId, AttrSourceMap, AttrsWithOwner, HasAttrs, InFile, db::{DefDatabase, HirDatabase}, - resolve_doc_path_on, sym, AttrId, AttrSourceMap, AttrsWithOwner, HasAttrs, InFile, + resolve_doc_path_on, sym, }; use itertools::Itertools; use span::{TextRange, TextSize}; use syntax::{ - ast::{self, IsString}, AstToken, + ast::{self, IsString}, }; /// Holds documentation @@ -151,11 +152,7 @@ pub fn docs_from_attrs(attrs: &hir::Attrs) -> Option { buf.push('\n'); } buf.pop(); - if buf.is_empty() { - None - } else { - Some(buf) - } + if buf.is_empty() { None } else { Some(buf) } } macro_rules! impl_has_docs { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs index fe4662785af11..994150b1ac4c2 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs @@ -220,11 +220,7 @@ impl FamousDefs<'_, '_> { for segment in path { module = module.children(db).find_map(|child| { let name = child.name(db)?; - if name.as_str() == segment { - Some(child) - } else { - None - } + if name.as_str() == segment { Some(child) } else { None } })?; } let def = diff --git a/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs b/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs index ebafc8876f249..340429037e67a 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs @@ -6,13 +6,14 @@ use base_db::SourceDatabase; use hir::{Crate, ItemInNs, ModuleDef, Name, Semantics}; use span::{Edition, FileId}; use syntax::{ - ast::{self, make}, AstToken, SyntaxKind, SyntaxToken, ToSmolStr, TokenAtOffset, + ast::{self, make}, }; use crate::{ + RootDatabase, defs::{Definition, IdentClass}, - generated, RootDatabase, + generated, }; pub fn item_name(db: &RootDatabase, item: ItemInNs) -> Option { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index 77fc59b4eccb5..0fc287c57e7c3 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -3,20 +3,20 @@ use std::ops::ControlFlow; use hir::{ - db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ImportPathConfig, - ItemInNs, ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics, - SemanticsScope, Trait, TyFingerprint, Type, + AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ImportPathConfig, ItemInNs, + ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics, + SemanticsScope, Trait, TyFingerprint, Type, db::HirDatabase, }; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; use syntax::{ - ast::{self, make, HasName}, AstNode, SyntaxNode, + ast::{self, HasName, make}, }; use crate::{ - items_locator::{self, AssocSearchMode, DEFAULT_QUERY_SEARCH_LIMIT}, FxIndexSet, RootDatabase, + items_locator::{self, AssocSearchMode, DEFAULT_QUERY_SEARCH_LIMIT}, }; /// A candidate for import, derived during various IDE activities: @@ -433,7 +433,7 @@ fn validate_resolvable( false => ControlFlow::Continue(()), }, ) - .map(|item| LocatedImport::new(import_path_candidate, resolved_qualifier, item)) + .map(|item| LocatedImport::new(import_path_candidate, resolved_qualifier, item)); } // FIXME ModuleDef::Trait(_) => return None, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs index 8e25ad3472d3b..d26e5d62ced51 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs @@ -6,20 +6,20 @@ use std::cmp::Ordering; use hir::Semantics; use syntax::{ - algo, + Direction, NodeOrToken, SyntaxKind, SyntaxNode, algo, ast::{ - self, edit_in_place::Removable, make, AstNode, HasAttrs, HasModuleItem, HasVisibility, - PathSegmentKind, + self, AstNode, HasAttrs, HasModuleItem, HasVisibility, PathSegmentKind, + edit_in_place::Removable, make, }, - ted, Direction, NodeOrToken, SyntaxKind, SyntaxNode, + ted, }; use crate::{ + RootDatabase, imports::merge_imports::{ - common_prefix, eq_attrs, eq_visibility, try_merge_imports, use_tree_cmp, MergeBehavior, - NormalizationStyle, + MergeBehavior, NormalizationStyle, common_prefix, eq_attrs, eq_visibility, + try_merge_imports, use_tree_cmp, }, - RootDatabase, }; pub use hir::PrefixKind; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs index 39810c615bb77..541f6c379e874 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs @@ -1,7 +1,7 @@ use salsa::AsDynDatabase; use stdx::trim_indent; use test_fixture::WithFixture; -use test_utils::{assert_eq_text, CURSOR_MARKER}; +use test_utils::{CURSOR_MARKER, assert_eq_text}; use super::*; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs index 9e89dfe87abe5..61962e593476c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs @@ -5,13 +5,12 @@ use itertools::{EitherOrBoth, Itertools}; use parser::T; use stdx::is_upper_snake_case; use syntax::{ - algo, + Direction, SyntaxElement, algo, ast::{ - self, edit_in_place::Removable, make, AstNode, HasAttrs, HasName, HasVisibility, - PathSegmentKind, + self, AstNode, HasAttrs, HasName, HasVisibility, PathSegmentKind, edit_in_place::Removable, + make, }, ted::{self, Position}, - Direction, SyntaxElement, }; use crate::syntax_helpers::node_ext::vis_eq; @@ -191,7 +190,7 @@ fn recursive_merge(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior) && !use_trees.is_empty() && rhs_t.use_tree_list().is_some() => { - return None + return None; } Err(insert_idx) => { use_trees.insert(insert_idx, rhs_t.clone()); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs index 4d9c051354a61..80881829800e5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs @@ -5,12 +5,12 @@ use std::ops::ControlFlow; use either::Either; -use hir::{import_map, Crate, ItemInNs, Module, Semantics}; +use hir::{Crate, ItemInNs, Module, Semantics, import_map}; use crate::{ + RootDatabase, imports::import_assets::NameToImport, symbol_index::{self, SymbolsDatabase as _}, - RootDatabase, }; /// A value to use, when uncertain which limit to pick. diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs index 414cc6cd18fa9..c6bd8031281c1 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -51,12 +51,12 @@ use salsa::Durability; use std::{fmt, mem::ManuallyDrop}; use base_db::{ - query_group, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Files, RootQueryDb, - SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, Upcast, + CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Files, RootQueryDb, + SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, Upcast, query_group, }; use hir::{ - db::{DefDatabase, ExpandDatabase, HirDatabase}, FilePositionWrapper, FileRangeWrapper, + db::{DefDatabase, ExpandDatabase, HirDatabase}, }; use triomphe::Arc; @@ -360,11 +360,7 @@ pub struct SnippetCap { impl SnippetCap { pub const fn new(allow_snippets: bool) -> Option { - if allow_snippets { - Some(SnippetCap { _private: () }) - } else { - None - } + if allow_snippets { Some(SnippetCap { _private: () }) } else { None } } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs index a348a4ef7d3fb..5aef2a6e020c3 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs @@ -7,8 +7,9 @@ use itertools::Itertools; use rustc_hash::FxHashMap; use span::Edition; use syntax::{ - ast::{self, make, AstNode, HasGenericArgs}, - ted, NodeOrToken, SyntaxNode, + NodeOrToken, SyntaxNode, + ast::{self, AstNode, HasGenericArgs, make}, + ted, }; #[derive(Default)] diff --git a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs index cd3099fe93819..17c3f75ce1731 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs @@ -6,14 +6,14 @@ mod topologic_sort; use std::time::Duration; -use hir::{db::DefDatabase, Symbol}; +use hir::{Symbol, db::DefDatabase}; use itertools::Itertools; use salsa::{Cancelled, Database}; use crate::{ + FxIndexMap, RootDatabase, base_db::{Crate, RootQueryDb}, symbol_index::SymbolsDatabase, - FxIndexMap, RootDatabase, }; /// We're indexing many crates. diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs index 902ead977e582..4a5a28e8248ce 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs @@ -30,20 +30,20 @@ use base_db::AnchoredPathBuf; use either::Either; use hir::{FieldSource, FileRange, HirFileIdExt, InFile, ModuleSource, Semantics}; use span::{Edition, EditionedFileId, FileId, SyntaxContext}; -use stdx::{never, TupleExt}; +use stdx::{TupleExt, never}; use syntax::{ + AstNode, SyntaxKind, T, TextRange, ast::{self, HasName}, utils::is_raw_identifier, - AstNode, SyntaxKind, TextRange, T, }; use crate::{ + RootDatabase, defs::Definition, search::{FileReference, FileReferenceNode}, source_change::{FileSystemEdit, SourceChange}, syntax_helpers::node_ext::expr_as_name_ref, traits::convert_to_def_in_trait, - RootDatabase, }; pub type Result = std::result::Result; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index 4f9ef05b20e79..bb4bee91bbe8a 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -10,9 +10,9 @@ use std::{cell::LazyCell, cmp::Reverse}; use base_db::{RootQueryDb, SourceDatabase}; use either::Either; use hir::{ - sym, Adt, AsAssocItem, DefWithBody, FileRange, FileRangeWrapper, HasAttrs, HasContainer, - HasSource, HirFileIdExt, InFile, InFileWrapper, InRealFile, InlineAsmOperand, ItemContainer, - ModuleSource, PathResolution, Semantics, Visibility, + Adt, AsAssocItem, DefWithBody, FileRange, FileRangeWrapper, HasAttrs, HasContainer, HasSource, + HirFileIdExt, InFile, InFileWrapper, InRealFile, InlineAsmOperand, ItemContainer, ModuleSource, + PathResolution, Semantics, Visibility, sym, }; use memchr::memmem::Finder; use parser::SyntaxKind; @@ -20,16 +20,16 @@ use rustc_hash::{FxHashMap, FxHashSet}; use salsa::Database; use span::EditionedFileId; use syntax::{ + AstNode, AstToken, SmolStr, SyntaxElement, SyntaxNode, TextRange, TextSize, ToSmolStr, ast::{self, HasName, Rename}, - match_ast, AstNode, AstToken, SmolStr, SyntaxElement, SyntaxNode, TextRange, TextSize, - ToSmolStr, + match_ast, }; use triomphe::Arc; use crate::{ + RootDatabase, defs::{Definition, NameClass, NameRefClass}, traits::{as_trait_assoc_def, convert_to_def_in_trait}, - RootDatabase, }; #[derive(Debug, Default, Clone)] @@ -1292,7 +1292,7 @@ impl<'a> FindUsages<'a> { if convert_to_def_in_trait(self.sema.db, def) != convert_to_def_in_trait(self.sema.db, self.def) => { - return false + return false; } (Some(_), Definition::TypeAlias(_)) => {} // We looking at an assoc item of a trait definition, so reference all the diff --git a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs index b4d0b0dc9f0af..741dc6bb3c88a 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs @@ -6,7 +6,7 @@ use std::{collections::hash_map::Entry, fmt, iter, mem}; use crate::text_edit::{TextEdit, TextEditBuilder}; -use crate::{assists::Command, syntax_helpers::tree_diff::diff, SnippetCap}; +use crate::{SnippetCap, assists::Command, syntax_helpers::tree_diff::diff}; use base_db::AnchoredPathBuf; use itertools::Itertools; use nohash_hasher::IntMap; @@ -14,8 +14,8 @@ use rustc_hash::FxHashMap; use span::FileId; use stdx::never; use syntax::{ - syntax_editor::{SyntaxAnnotation, SyntaxEditor}, AstNode, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextSize, + syntax_editor::{SyntaxAnnotation, SyntaxEditor}, }; /// An annotation ID associated with an indel, to describe changes. @@ -479,13 +479,14 @@ impl SourceChangeBuilder { self.commit(); // Only one file can have snippet edits - stdx::never!(self - .source_change - .source_file_edits - .iter() - .filter(|(_, (_, snippet_edit))| snippet_edit.is_some()) - .at_most_one() - .is_err()); + stdx::never!( + self.source_change + .source_file_edits + .iter() + .filter(|(_, (_, snippet_edit))| snippet_edit.is_some()) + .at_most_one() + .is_err() + ); mem::take(&mut self.source_change) } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs index 5fea97b32dbde..e681a6d17ce34 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs @@ -28,12 +28,12 @@ use std::{ }; use base_db::{RootQueryDb, SourceDatabase, SourceRootId, Upcast}; -use fst::{raw::IndexedValue, Automaton, Streamer}; +use fst::{Automaton, Streamer, raw::IndexedValue}; use hir::{ + Crate, Module, db::HirDatabase, import_map::{AssocSearchMode, SearchMode}, symbols::{FileSymbol, SymbolCollector}, - Crate, Module, }; use rayon::prelude::*; use rustc_hash::FxHashSet; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs index 92478ef480d6a..7e8c921d9ed39 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs @@ -1,7 +1,7 @@ //! Tools to work with format string literals for the `format_args!` family of macros. use syntax::{ - ast::{self, IsString}, AstNode, AstToken, TextRange, TextSize, + ast::{self, IsString}, }; // FIXME: This can probably be re-implemented via the HIR? diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs index c104aa571894d..8f25833fffb8d 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs @@ -183,7 +183,7 @@ pub fn parse_format_exprs(input: &str) -> Result<(String, Vec), ()> { #[cfg(test)] mod tests { use super::*; - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; fn check(input: &str, expect: &Expect) { let (output, exprs) = parse_format_exprs(input).unwrap_or(("-".to_owned(), vec![])); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs index 0b2e8aa6836f2..f0aa3daf55b63 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs @@ -5,8 +5,8 @@ use itertools::Itertools; use parser::T; use span::Edition; use syntax::{ - ast::{self, HasLoopBody, MacroCall, PathSegmentKind, VisibilityKind}, AstNode, AstToken, Preorder, RustLanguage, WalkEvent, + ast::{self, HasLoopBody, MacroCall, PathSegmentKind, VisibilityKind}, }; pub fn expr_as_name_ref(expr: &ast::Expr) -> Option { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs index 21dd098781a85..6801856e5b80b 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs @@ -7,8 +7,9 @@ use itertools::Itertools; use rustc_hash::FxHashMap; use stdx::to_lower_snake_case; use syntax::{ + AstNode, Edition, SmolStr, SmolStrBuilder, ToSmolStr, ast::{self, HasName}, - match_ast, AstNode, Edition, SmolStr, SmolStrBuilder, ToSmolStr, + match_ast, }; use crate::RootDatabase; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/tree_diff.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/tree_diff.rs index 02e24c47761c9..7163c08e1e317 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/tree_diff.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/tree_diff.rs @@ -2,7 +2,7 @@ use rustc_hash::FxHashMap; use syntax::{NodeOrToken, SyntaxElement, SyntaxNode}; -use crate::{text_edit::TextEditBuilder, FxIndexMap}; +use crate::{FxIndexMap, text_edit::TextEditBuilder}; #[derive(Debug, Hash, PartialEq, Eq)] enum TreeDiffInsertPos { @@ -153,7 +153,7 @@ pub fn diff(from: &SyntaxNode, to: &SyntaxNode) -> TreeDiff { #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use itertools::Itertools; use parser::{Edition, SyntaxKind}; use syntax::{AstNode, SourceFile, SyntaxElement}; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/traits.rs b/src/tools/rust-analyzer/crates/ide-db/src/traits.rs index fb231393a473d..22a695c9a82ce 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/traits.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/traits.rs @@ -1,9 +1,9 @@ //! Functionality for obtaining data related to traits from the DB. -use crate::{defs::Definition, RootDatabase}; -use hir::{db::HirDatabase, AsAssocItem, Semantics}; +use crate::{RootDatabase, defs::Definition}; +use hir::{AsAssocItem, Semantics, db::HirDatabase}; use rustc_hash::FxHashSet; -use syntax::{ast, AstNode}; +use syntax::{AstNode, ast}; /// Given the `impl` block, attempts to find the trait this `impl` corresponds to. pub fn resolve_target_trait( @@ -113,7 +113,7 @@ fn assoc_item_of_trait( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use hir::FilePosition; use hir::Semantics; use salsa::AsDynDatabase; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs b/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs index 2fdd8358637df..63ce0ddbb8fc2 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs @@ -5,7 +5,7 @@ use std::iter; use hir::Semantics; -use syntax::ast::{self, make, Pat}; +use syntax::ast::{self, Pat, make}; use crate::RootDatabase; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs b/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs index c3f0bf3706904..a4a93e36f0e1a 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs @@ -3,8 +3,8 @@ use hir::StructKind; use span::Edition; use syntax::{ - ast::{make, Expr, Path}, ToSmolStr, + ast::{Expr, Path, make}, }; /// given a type return the trivial constructor (if one exists) diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/await_outside_of_async.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/await_outside_of_async.rs index 92b6e748ca5ed..92ca7a74184fb 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/await_outside_of_async.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/await_outside_of_async.rs @@ -1,4 +1,4 @@ -use crate::{adjusted_display_range, Diagnostic, DiagnosticsContext}; +use crate::{Diagnostic, DiagnosticsContext, adjusted_display_range}; // Diagnostic: await-outside-of-async // diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/field_shorthand.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/field_shorthand.rs index 876c2ccd49d7a..f7020a2c50e18 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/field_shorthand.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/field_shorthand.rs @@ -2,10 +2,10 @@ //! expressions and patterns. use ide_db::text_edit::TextEdit; -use ide_db::{source_change::SourceChange, EditionedFileId, FileRange}; -use syntax::{ast, match_ast, AstNode, SyntaxNode}; +use ide_db::{EditionedFileId, FileRange, source_change::SourceChange}; +use syntax::{AstNode, SyntaxNode, ast, match_ast}; -use crate::{fix, Diagnostic, DiagnosticCode}; +use crate::{Diagnostic, DiagnosticCode, fix}; pub(crate) fn field_shorthand( acc: &mut Vec, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs index 7d62daf716c47..3fa8c0133ae86 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs @@ -3,9 +3,9 @@ use hir::GenericArgsProhibitedReason; use ide_db::assists::Assist; use ide_db::source_change::SourceChange; use ide_db::text_edit::TextEdit; -use syntax::{ast, AstNode, TextRange}; +use syntax::{AstNode, TextRange, ast}; -use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, fix}; // Diagnostic: generic-args-prohibited // diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs index 96a368eb0ea3f..80ea6f5893505 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs @@ -39,7 +39,7 @@ pub(crate) fn inactive_code( #[cfg(test)] mod tests { - use crate::{tests::check_diagnostics_with_config, DiagnosticsConfig}; + use crate::{DiagnosticsConfig, tests::check_diagnostics_with_config}; pub(crate) fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let config = DiagnosticsConfig { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs index d3f302077528a..0b9a2ec9db3dd 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs @@ -1,7 +1,7 @@ use hir::InFile; use syntax::{AstNode, TextRange}; -use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, adjusted_display_range}; // Diagnostic: incoherent-impl // diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs index 246330e6efaac..72619445b5dcf 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -1,13 +1,13 @@ -use hir::{db::ExpandDatabase, CaseType, InFile}; +use hir::{CaseType, InFile, db::ExpandDatabase}; use ide_db::{assists::Assist, defs::NameClass}; use syntax::AstNode; use crate::{ - // references::rename::rename_with_semantics, - unresolved_fix, Diagnostic, DiagnosticCode, DiagnosticsContext, + // references::rename::rename_with_semantics, + unresolved_fix, }; // Diagnostic: incorrect-ident-case diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs index f22041ebe233b..38eeecb29b71e 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs @@ -4,19 +4,19 @@ use hir::{ImportPathConfig, PathResolution, Semantics}; use ide_db::text_edit::TextEdit; use ide_db::{ + EditionedFileId, FileRange, FxHashMap, RootDatabase, helpers::mod_path_to_ast, - imports::insert_use::{insert_use, ImportScope}, + imports::insert_use::{ImportScope, insert_use}, source_change::SourceChangeBuilder, - EditionedFileId, FileRange, FxHashMap, RootDatabase, }; use itertools::Itertools; use stdx::{format_to, never}; use syntax::{ - ast::{self, make}, Edition, SyntaxKind, SyntaxNode, + ast::{self, make}, }; -use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsConfig, Severity}; +use crate::{Diagnostic, DiagnosticCode, DiagnosticsConfig, Severity, fix}; #[derive(Default)] struct State { @@ -196,8 +196,8 @@ pub(crate) fn json_in_items( #[cfg(test)] mod tests { use crate::{ - tests::{check_diagnostics_with_config, check_fix, check_no_fix}, DiagnosticsConfig, + tests::{check_diagnostics_with_config, check_fix, check_no_fix}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs index 2f132985895c6..9efe251c9ae94 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs @@ -38,8 +38,8 @@ pub(crate) fn macro_def_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroDefErr #[cfg(test)] mod tests { use crate::{ - tests::{check_diagnostics, check_diagnostics_with_config}, DiagnosticsConfig, + tests::{check_diagnostics, check_diagnostics_with_config}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index 0520bb3fe9b9b..63fd9b4e3f06b 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -2,11 +2,11 @@ use either::Either; use hir::InFile; use ide_db::FileRange; use syntax::{ - ast::{self, HasArgList}, AstNode, AstPtr, + ast::{self, HasArgList}, }; -use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, adjusted_display_range}; // Diagnostic: mismatched-tuple-struct-pat-arg-count // diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs index 938b7182bc946..ac68f4186cc57 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -1,20 +1,22 @@ use either::Either; use hir::{ + AssocItem, HirDisplay, HirFileIdExt, ImportPathConfig, InFile, Type, db::{ExpandDatabase, HirDatabase}, - sym, AssocItem, HirDisplay, HirFileIdExt, ImportPathConfig, InFile, Type, + sym, }; use ide_db::{ - assists::Assist, famous_defs::FamousDefs, imports::import_assets::item_for_path_search, - source_change::SourceChange, syntax_helpers::tree_diff::diff, text_edit::TextEdit, - use_trivial_constructor::use_trivial_constructor, FxHashMap, + FxHashMap, assists::Assist, famous_defs::FamousDefs, + imports::import_assets::item_for_path_search, source_change::SourceChange, + syntax_helpers::tree_diff::diff, text_edit::TextEdit, + use_trivial_constructor::use_trivial_constructor, }; use stdx::format_to; use syntax::{ - ast::{self, make}, AstNode, Edition, SyntaxNode, SyntaxNodePtr, ToSmolStr, + ast::{self, make}, }; -use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, fix}; // Diagnostic: missing-fields // @@ -140,11 +142,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option, d: &hir::TypeMismatch) -> Option, d: &hir::TypedHole) -> Option }) .collect(); - if !assists.is_empty() { - Some(assists) - } else { - None - } + if !assists.is_empty() { Some(assists) } else { None } } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs index 550751b6c01c4..2602aa011f0ac 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs @@ -2,21 +2,21 @@ use std::iter; -use hir::{db::DefDatabase, DefMap, InFile, ModuleSource}; +use hir::{DefMap, InFile, ModuleSource, db::DefDatabase}; use ide_db::base_db::RootQueryDb; use ide_db::text_edit::TextEdit; use ide_db::{ + FileId, FileRange, LineIndexDatabase, base_db::{SourceDatabase, Upcast}, source_change::SourceChange, - FileId, FileRange, LineIndexDatabase, }; use paths::Utf8Component; use syntax::{ - ast::{self, edit::IndentLevel, HasModuleItem, HasName}, AstNode, TextRange, + ast::{self, HasModuleItem, HasName, edit::IndentLevel}, }; -use crate::{fix, Assist, Diagnostic, DiagnosticCode, DiagnosticsContext, Severity}; +use crate::{Assist, Diagnostic, DiagnosticCode, DiagnosticsContext, Severity, fix}; // Diagnostic: unlinked-file // @@ -37,7 +37,9 @@ pub(crate) fn unlinked_file( "This file is not included anywhere in the module tree, so rust-analyzer can't offer IDE services." }; - let message = format!("{message}\n\nIf you're intentionally working on unowned files, you can silence this warning by adding \"unlinked-file\" to rust-analyzer.diagnostics.disabled in your settings."); + let message = format!( + "{message}\n\nIf you're intentionally working on unowned files, you can silence this warning by adding \"unlinked-file\" to rust-analyzer.diagnostics.disabled in your settings." + ); let mut unused = true; diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs index 6ab713a5896c9..7020fce24ff3a 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs @@ -1,7 +1,7 @@ use std::iter; use either::Either; -use hir::{db::ExpandDatabase, Adt, FileRange, HasSource, HirDisplay, InFile, Struct, Union}; +use hir::{Adt, FileRange, HasSource, HirDisplay, InFile, Struct, Union, db::ExpandDatabase}; use ide_db::text_edit::TextEdit; use ide_db::{ assists::{Assist, AssistId, AssistKind}, @@ -10,16 +10,15 @@ use ide_db::{ source_change::{SourceChange, SourceChangeBuilder}, }; use syntax::{ - algo, - ast::{self, edit::IndentLevel, make, FieldList, Name, Visibility}, - AstNode, AstPtr, Direction, SyntaxKind, TextSize, + AstNode, AstPtr, Direction, SyntaxKind, TextSize, algo, + ast::{self, FieldList, Name, Visibility, edit::IndentLevel, make}, }; use syntax::{ - ast::{edit::AstNodeEdit, Type}, SyntaxNode, + ast::{Type, edit::AstNodeEdit}, }; -use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, adjusted_display_range}; // Diagnostic: unresolved-field // @@ -62,11 +61,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option, d: &hir::UnresolvedMethodCall) -> Option< fixes.push(assoc_func_fix); } - if fixes.is_empty() { - None - } else { - Some(fixes) - } + if fixes.is_empty() { None } else { Some(fixes) } } fn field_fix( diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_module.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_module.rs index 2bd8e484f8537..7b9dd55e01c6e 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_module.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_module.rs @@ -1,9 +1,9 @@ -use hir::{db::ExpandDatabase, HirFileIdExt}; +use hir::{HirFileIdExt, db::ExpandDatabase}; use ide_db::{assists::Assist, base_db::AnchoredPathBuf, source_change::FileSystemEdit}; use itertools::Itertools; use syntax::AstNode; -use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, fix}; // Diagnostic: unresolved-module // diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs index d5caf4de3367e..c412536d749e0 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs @@ -1,10 +1,10 @@ use hir::Name; use ide_db::text_edit::TextEdit; use ide_db::{ + FileRange, RootDatabase, assists::{Assist, AssistId, AssistKind}, label::Label, source_change::SourceChange, - FileRange, RootDatabase, }; use syntax::{Edition, TextRange}; diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/useless_braces.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/useless_braces.rs index e5c2eca171ae4..ac9b34f416b44 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/useless_braces.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/useless_braces.rs @@ -1,10 +1,10 @@ use hir::InFile; use ide_db::text_edit::TextEdit; -use ide_db::{source_change::SourceChange, EditionedFileId, FileRange}; +use ide_db::{EditionedFileId, FileRange, source_change::SourceChange}; use itertools::Itertools; -use syntax::{ast, AstNode, SyntaxNode, SyntaxNodePtr}; +use syntax::{AstNode, SyntaxNode, SyntaxNodePtr, ast}; -use crate::{fix, Diagnostic, DiagnosticCode}; +use crate::{Diagnostic, DiagnosticCode, fix}; // Diagnostic: unnecessary-braces // @@ -56,8 +56,8 @@ pub(crate) fn useless_braces( #[cfg(test)] mod tests { use crate::{ - tests::{check_diagnostics, check_diagnostics_with_config, check_fix}, DiagnosticsConfig, + tests::{check_diagnostics, check_diagnostics_with_config, check_fix}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index c6f60a9a9654e..e801ec50cff91 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -82,24 +82,24 @@ use std::{collections::hash_map, iter, sync::LazyLock}; use either::Either; use hir::{ - db::ExpandDatabase, diagnostics::AnyDiagnostic, Crate, DisplayTarget, HirFileId, InFile, - Semantics, + Crate, DisplayTarget, HirFileId, InFile, Semantics, db::ExpandDatabase, + diagnostics::AnyDiagnostic, }; use ide_db::base_db::salsa::AsDynDatabase; use ide_db::{ + EditionedFileId, FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, Severity, SnippetCap, assists::{Assist, AssistId, AssistKind, AssistResolveStrategy}, base_db::{ReleaseChannel, RootQueryDb as _}, - generated::lints::{Lint, LintGroup, CLIPPY_LINT_GROUPS, DEFAULT_LINTS, DEFAULT_LINT_GROUPS}, + generated::lints::{CLIPPY_LINT_GROUPS, DEFAULT_LINT_GROUPS, DEFAULT_LINTS, Lint, LintGroup}, imports::insert_use::InsertUseConfig, label::Label, source_change::SourceChange, syntax_helpers::node_ext::parse_tt_as_comma_sep_paths, - EditionedFileId, FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, Severity, SnippetCap, }; use itertools::Itertools; use syntax::{ + AstPtr, Edition, NodeOrToken, SmolStr, SyntaxKind, SyntaxNode, SyntaxNodePtr, T, TextRange, ast::{self, AstNode, HasAttrs}, - AstPtr, Edition, NodeOrToken, SmolStr, SyntaxKind, SyntaxNode, SyntaxNodePtr, TextRange, T, }; // FIXME: Make this an enum @@ -781,9 +781,8 @@ fn fill_lint_attrs( }); let lints = lint_groups(&diag.code, edition); - let all_matching_groups = lints - .iter() - .filter_map(|lint_group| cached.get(lint_group)); + let all_matching_groups = + lints.iter().filter_map(|lint_group| cached.get(lint_group)); let cached_severity = all_matching_groups.min_by_key(|it| it.depth).map(|it| it.severity); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs index 7b33bbdaa22c4..6e4ce1ea1840c 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs @@ -3,12 +3,12 @@ mod overly_long_real_world_cases; use ide_db::{ - assists::AssistResolveStrategy, base_db::SourceDatabase, LineIndexDatabase, RootDatabase, + LineIndexDatabase, RootDatabase, assists::AssistResolveStrategy, base_db::SourceDatabase, }; use itertools::Itertools; use stdx::trim_indent; use test_fixture::WithFixture; -use test_utils::{assert_eq_text, extract_annotations, MiniCore}; +use test_utils::{MiniCore, assert_eq_text, extract_annotations}; use crate::{DiagnosticsConfig, ExprFillDefaultMode, Severity}; diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/fragments.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/fragments.rs index ca937a03f82d2..8d6b7c637d730 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/fragments.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/fragments.rs @@ -6,7 +6,7 @@ //! needs to determine it somehow. We do this in a stupid way -- by pasting SSR //! rule into different contexts and checking what works. -use syntax::{ast, AstNode, SyntaxNode}; +use syntax::{AstNode, SyntaxNode, ast}; pub(crate) fn ty(s: &str) -> Result { fragment::("type T = {};", s) diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/from_comment.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/from_comment.rs index f6fe705a98741..5921a5df5312d 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/from_comment.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/from_comment.rs @@ -2,12 +2,12 @@ //! from a comment. use ide_db::{ - base_db::{salsa::AsDynDatabase, RootQueryDb}, EditionedFileId, FilePosition, FileRange, RootDatabase, + base_db::{RootQueryDb, salsa::AsDynDatabase}, }; use syntax::{ - ast::{self, AstNode, AstToken}, TextRange, + ast::{self, AstNode, AstToken}, }; use crate::MatchFinder; diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs index 971547ca1f8e6..757c77b67371b 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs @@ -83,11 +83,11 @@ use hir::{FileRange, Semantics}; use ide_db::symbol_index::SymbolsDatabase; use ide_db::text_edit::TextEdit; use ide_db::{ - base_db::{salsa::AsDynDatabase, SourceDatabase}, EditionedFileId, FileId, FxHashMap, RootDatabase, + base_db::{SourceDatabase, salsa::AsDynDatabase}, }; use resolving::ResolvedRule; -use syntax::{ast, AstNode, SyntaxNode, TextRange}; +use syntax::{AstNode, SyntaxNode, TextRange, ast}; // A structured search replace rule. Create by calling `parse` on a str. #[derive(Debug)] diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs index a76516f44f03b..0776b8bc5e43a 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs @@ -2,16 +2,16 @@ //! process of matching, placeholder values are recorded. use crate::{ + SsrMatches, parsing::{Constraint, NodeKind, Placeholder, Var}, resolving::{ResolvedPattern, ResolvedRule, UfcsCallInfo}, - SsrMatches, }; use hir::{FileRange, ImportPathConfig, Semantics}; -use ide_db::{base_db::RootQueryDb, FxHashMap}; +use ide_db::{FxHashMap, base_db::RootQueryDb}; use std::{cell::Cell, iter::Peekable}; use syntax::{ - ast::{self, AstNode, AstToken, HasGenericArgs}, SmolStr, SyntaxElement, SyntaxElementChildren, SyntaxKind, SyntaxNode, SyntaxToken, + ast::{self, AstNode, AstToken, HasGenericArgs}, }; // Creates a match error. If we're currently attempting to match some code that we thought we were diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/parsing.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/parsing.rs index ea40d5b815ef3..2c0f1658d837f 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/parsing.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/parsing.rs @@ -9,7 +9,7 @@ use std::{fmt::Display, str::FromStr}; use syntax::{SmolStr, SyntaxKind, SyntaxNode, T}; use crate::errors::bail; -use crate::{fragments, SsrError, SsrPattern, SsrRule}; +use crate::{SsrError, SsrPattern, SsrRule, fragments}; #[derive(Debug)] pub(crate) struct ParsedRule { diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/replacing.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/replacing.rs index 11c1615a560eb..2ad562f2427aa 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/replacing.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/replacing.rs @@ -5,11 +5,11 @@ use ide_db::{FxHashMap, FxHashSet}; use itertools::Itertools; use parser::Edition; use syntax::{ - ast::{self, AstNode, AstToken}, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize, + ast::{self, AstNode, AstToken}, }; -use crate::{fragments, resolving::ResolvedRule, Match, SsrMatches}; +use crate::{Match, SsrMatches, fragments, resolving::ResolvedRule}; /// Returns a text edit that will replace each match in `matches` with its corresponding replacement /// template. Placeholders in the template will have been substituted with whatever they matched to diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs index 8c98d8de9183e..ba6d981b8c153 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs @@ -1,14 +1,14 @@ //! This module is responsible for resolving paths within rules. use hir::AsAssocItem; -use ide_db::{base_db::salsa::AsDynDatabase, FxHashMap}; +use ide_db::{FxHashMap, base_db::salsa::AsDynDatabase}; use parsing::Placeholder; use syntax::{ - ast::{self, HasGenericArgs}, SmolStr, SyntaxKind, SyntaxNode, SyntaxToken, + ast::{self, HasGenericArgs}, }; -use crate::{errors::error, parsing, SsrError}; +use crate::{SsrError, errors::error, parsing}; pub(crate) struct ResolutionScope<'db> { scope: hir::SemanticsScope<'db>, diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs index b094712e1bd56..73dbefb51b22e 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs @@ -1,18 +1,17 @@ //! Searching for matches. use crate::{ - matching, + Match, MatchFinder, matching, resolving::{ResolvedPath, ResolvedPattern, ResolvedRule}, - Match, MatchFinder, }; use hir::FileRange; use ide_db::{ + EditionedFileId, FileId, FxHashSet, base_db::salsa::AsDynDatabase, defs::Definition, search::{SearchScope, UsageSearchResult}, - EditionedFileId, FileId, FxHashSet, }; -use syntax::{ast, AstNode, SyntaxKind, SyntaxNode}; +use syntax::{AstNode, SyntaxKind, SyntaxNode, ast}; /// A cache for the results of find_usages. This is for when we have multiple patterns that have the /// same path. e.g. if the pattern was `foo::Bar` that can parse as a path, an expression, a type diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/tests.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/tests.rs index 0b510c9c6b244..b26ea35f02a93 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/tests.rs @@ -1,8 +1,8 @@ -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use hir::{FilePosition, FileRange}; use ide_db::{ - base_db::{salsa::Durability, SourceDatabase}, EditionedFileId, FxHashSet, + base_db::{SourceDatabase, salsa::Durability}, }; use test_utils::RangeOrOffset; use triomphe::Arc; @@ -67,7 +67,7 @@ fn parser_undefined_placeholder_in_replacement() { /// the start of the file. If there's a second cursor marker, then we'll return a single range. pub(crate) fn single_file(code: &str) -> (ide_db::RootDatabase, FilePosition, Vec) { use ide_db::symbol_index::SymbolsDatabase; - use test_fixture::{WithFixture, WORKSPACE}; + use test_fixture::{WORKSPACE, WithFixture}; let (mut db, file_id, range_or_offset) = if code.contains(test_utils::CURSOR_MARKER) { ide_db::RootDatabase::with_range_or_offset(code) } else { diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations.rs b/src/tools/rust-analyzer/crates/ide/src/annotations.rs index e47891bbdfe7e..d44d4bfd2be7b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/annotations.rs +++ b/src/tools/rust-analyzer/crates/ide/src/annotations.rs @@ -1,17 +1,17 @@ use hir::{HasSource, InFile, InRealFile, Semantics}; use ide_db::{ - defs::Definition, helpers::visit_file_defs, FileId, FilePosition, FileRange, FxIndexSet, - RootDatabase, + FileId, FilePosition, FileRange, FxIndexSet, RootDatabase, defs::Definition, + helpers::visit_file_defs, }; use itertools::Itertools; -use syntax::{ast::HasName, AstNode, TextRange}; +use syntax::{AstNode, TextRange, ast::HasName}; use crate::{ + NavigationTarget, RunnableKind, annotations::fn_references::find_all_methods, goto_implementation::goto_implementation, references::find_all_refs, - runnables::{runnables, Runnable}, - NavigationTarget, RunnableKind, + runnables::{Runnable, runnables}, }; mod fn_references; @@ -209,9 +209,9 @@ fn should_skip_runnable(kind: &RunnableKind, binary_target: bool) -> bool { #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; - use crate::{fixture, Annotation, AnnotationConfig}; + use crate::{Annotation, AnnotationConfig, fixture}; use super::AnnotationLocation; diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations/fn_references.rs b/src/tools/rust-analyzer/crates/ide/src/annotations/fn_references.rs index 08cc10509cb8a..427a2eff82017 100644 --- a/src/tools/rust-analyzer/crates/ide/src/annotations/fn_references.rs +++ b/src/tools/rust-analyzer/crates/ide/src/annotations/fn_references.rs @@ -4,7 +4,7 @@ use hir::Semantics; use ide_assists::utils::test_related_attribute_syn; use ide_db::RootDatabase; -use syntax::{ast, ast::HasName, AstNode, SyntaxNode, TextRange}; +use syntax::{AstNode, SyntaxNode, TextRange, ast, ast::HasName}; use crate::FileId; @@ -34,8 +34,8 @@ fn method_range(item: SyntaxNode) -> Option<(TextRange, Option)> { mod tests { use syntax::TextRange; - use crate::fixture; use crate::TextSize; + use crate::fixture; use std::ops::RangeInclusive; #[test] diff --git a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs index afd6f740c42c6..5c0e113d5c6a7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs +++ b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs @@ -4,14 +4,14 @@ use std::iter; use hir::Semantics; use ide_db::{ + FileRange, FxIndexMap, RootDatabase, defs::{Definition, NameClass, NameRefClass}, helpers::pick_best_token, search::FileReference, - FileRange, FxIndexMap, RootDatabase, }; -use syntax::{ast, AstNode, SyntaxKind::IDENT}; +use syntax::{AstNode, SyntaxKind::IDENT, ast}; -use crate::{goto_definition, FilePosition, NavigationTarget, RangeInfo, TryToNav}; +use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav, goto_definition}; #[derive(Debug, Clone)] pub struct CallItem { @@ -165,7 +165,7 @@ impl CallLocations { #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use ide_db::FilePosition; use itertools::Itertools; diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index 9bdc2e7d13337..a01afd242e3b3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -6,28 +6,29 @@ mod tests; mod intra_doc_links; use pulldown_cmark::{BrokenLink, CowStr, Event, InlineStr, LinkType, Options, Parser, Tag}; -use pulldown_cmark_to_cmark::{cmark_resume_with_options, Options as CMarkOptions}; +use pulldown_cmark_to_cmark::{Options as CMarkOptions, cmark_resume_with_options}; use stdx::format_to; use url::Url; -use hir::{db::HirDatabase, sym, Adt, AsAssocItem, AssocItem, AssocItemContainer, HasAttrs}; +use hir::{Adt, AsAssocItem, AssocItem, AssocItemContainer, HasAttrs, db::HirDatabase, sym}; use ide_db::{ + RootDatabase, base_db::{CrateOrigin, LangCrateOrigin, ReleaseChannel, RootQueryDb}, defs::{Definition, NameClass, NameRefClass}, - documentation::{docs_with_rangemap, Documentation, HasDocs}, + documentation::{Documentation, HasDocs, docs_with_rangemap}, helpers::pick_best_token, - RootDatabase, }; use syntax::{ - ast::{self, IsString}, - match_ast, AstNode, AstToken, + AstNode, AstToken, SyntaxKind::*, - SyntaxNode, SyntaxToken, TextRange, TextSize, T, + SyntaxNode, SyntaxToken, T, TextRange, TextSize, + ast::{self, IsString}, + match_ast, }; use crate::{ - doc_links::intra_doc_links::{parse_intra_doc_link, strip_prefixes_suffixes}, FilePosition, Semantics, + doc_links::intra_doc_links::{parse_intra_doc_link, strip_prefixes_suffixes}, }; /// Web and local links to an item's documentation. diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links/intra_doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links/intra_doc_links.rs index 6cc240d652499..c331734c785ed 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links/intra_doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links/intra_doc_links.rs @@ -53,7 +53,7 @@ pub(super) fn strip_prefixes_suffixes(s: &str) -> &str { #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use super::*; diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs index d70a3f9706cfd..91785be8d8bad 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs @@ -1,18 +1,19 @@ use std::iter; -use expect_test::{expect, Expect}; +use expect_test::{Expect, expect}; use hir::Semantics; use ide_db::{ + FilePosition, FileRange, RootDatabase, defs::Definition, documentation::{Documentation, HasDocs}, - FilePosition, FileRange, RootDatabase, }; use itertools::Itertools; -use syntax::{ast, match_ast, AstNode, SyntaxNode}; +use syntax::{AstNode, SyntaxNode, ast, match_ast}; use crate::{ + TryToNav, doc_links::{extract_definitions_from_docs, resolve_doc_path_for_def, rewrite_links}, - fixture, TryToNav, + fixture, }; fn check_external_docs( @@ -683,7 +684,9 @@ fn rewrite_intra_doc_link_with_anchor() { //! $0[PartialEq#derivable] fn main() {} "#, - expect!["[PartialEq#derivable](https://doc.rust-lang.org/stable/core/cmp/trait.PartialEq.html#derivable)"], + expect![ + "[PartialEq#derivable](https://doc.rust-lang.org/stable/core/cmp/trait.PartialEq.html#derivable)" + ], ); } diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index a18eb9049ff67..4811f1f691c8c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -1,12 +1,12 @@ use hir::db::ExpandDatabase; use hir::{ExpandResult, InFile, MacroFileIdExt, Semantics}; use ide_db::{ - base_db::Crate, helpers::pick_best_token, syntax_helpers::prettify_macro_expansion, FileId, - RootDatabase, + FileId, RootDatabase, base_db::Crate, helpers::pick_best_token, + syntax_helpers::prettify_macro_expansion, }; use span::{Edition, SpanMap, SyntaxContext, TextRange, TextSize}; use stdx::format_to; -use syntax::{ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T}; +use syntax::{AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T, ast, ted}; use crate::FilePosition; @@ -289,7 +289,7 @@ fn _format( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use crate::fixture; diff --git a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs index 76414854e91ef..a374f9752fcfa 100644 --- a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs +++ b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs @@ -3,11 +3,11 @@ use std::iter::successors; use hir::Semantics; use ide_db::RootDatabase; use syntax::{ - algo::{self, skip_trivia_token}, - ast::{self, AstNode, AstToken}, Direction, NodeOrToken, SyntaxKind::{self, *}, - SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, T, + SyntaxNode, SyntaxToken, T, TextRange, TextSize, TokenAtOffset, + algo::{self, skip_trivia_token}, + ast::{self, AstNode, AstToken}, }; use crate::FileRange; @@ -178,11 +178,7 @@ fn extend_tokens_from_range( .last()?; let range = first.text_range().cover(last.text_range()); - if range.contains_range(original_range) && original_range != range { - Some(range) - } else { - None - } + if range.contains_range(original_range) && original_range != range { Some(range) } else { None } } /// Find the shallowest node with same range, which allows us to traverse siblings. @@ -216,11 +212,7 @@ fn extend_single_word_in_comment_or_string( let to: TextSize = (cursor_position + end_idx).into(); let range = TextRange::new(from, to); - if range.is_empty() { - None - } else { - Some(range + leaf.text_range().start()) - } + if range.is_empty() { None } else { Some(range + leaf.text_range().start()) } } fn extend_ws(root: &SyntaxNode, ws: SyntaxToken, offset: TextSize) -> TextRange { diff --git a/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs b/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs index b682c4bc0f791..956379e722d53 100644 --- a/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs +++ b/src/tools/rust-analyzer/crates/ide/src/fetch_crates.rs @@ -1,6 +1,6 @@ use ide_db::{ - base_db::{CrateOrigin, RootQueryDb}, FileId, FxIndexSet, RootDatabase, + base_db::{CrateOrigin, RootQueryDb}, }; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs index 52fbab6fa12b1..347da4e85b4aa 100644 --- a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs +++ b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs @@ -1,8 +1,8 @@ use ide_db::SymbolKind; use syntax::{ + AstNode, AstToken, NodeOrToken, SourceFile, SyntaxNode, SyntaxToken, TextRange, WalkEvent, ast::{self, HasAttrs, HasGenericParams, HasName}, - match_ast, AstNode, AstToken, NodeOrToken, SourceFile, SyntaxNode, SyntaxToken, TextRange, - WalkEvent, + match_ast, }; #[derive(Debug, Clone)] @@ -250,7 +250,7 @@ fn structure_token(token: SyntaxToken) -> Option { #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use super::*; diff --git a/src/tools/rust-analyzer/crates/ide/src/fixture.rs b/src/tools/rust-analyzer/crates/ide/src/fixture.rs index a0612f48d37e8..73b7e771ca954 100644 --- a/src/tools/rust-analyzer/crates/ide/src/fixture.rs +++ b/src/tools/rust-analyzer/crates/ide/src/fixture.rs @@ -1,6 +1,6 @@ //! Utilities for creating `Analysis` instances for tests. use test_fixture::ChangeFixture; -use test_utils::{extract_annotations, RangeOrOffset}; +use test_utils::{RangeOrOffset, extract_annotations}; use crate::{Analysis, AnalysisHost, FileId, FilePosition, FileRange}; diff --git a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs index e5a94ff9fe964..194e8c968f758 100755 --- a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs +++ b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs @@ -1,9 +1,10 @@ -use ide_db::{syntax_helpers::node_ext::vis_eq, FxHashSet}; +use ide_db::{FxHashSet, syntax_helpers::node_ext::vis_eq}; use syntax::{ - ast::{self, AstNode, AstToken}, - match_ast, Direction, NodeOrToken, SourceFile, + Direction, NodeOrToken, SourceFile, SyntaxKind::{self, *}, TextRange, TextSize, + ast::{self, AstNode, AstToken}, + match_ast, }; use std::hash::Hash; diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs index 3742edc8db84b..a022f1cede871 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs @@ -1,13 +1,13 @@ use hir::{AsAssocItem, Semantics}; use ide_db::{ - defs::{Definition, NameClass, NameRefClass}, RootDatabase, + defs::{Definition, NameClass, NameRefClass}, }; -use syntax::{ast, match_ast, AstNode, SyntaxKind::*, T}; +use syntax::{AstNode, SyntaxKind::*, T, ast, match_ast}; use crate::{ - goto_definition::goto_definition, navigation_target::TryToNav, FilePosition, NavigationTarget, - RangeInfo, + FilePosition, NavigationTarget, RangeInfo, goto_definition::goto_definition, + navigation_target::TryToNav, }; // Feature: Go to Declaration @@ -52,7 +52,7 @@ pub(crate) fn goto_declaration( }; let assoc = match def? { Definition::Module(module) => { - return Some(NavigationTarget::from_module_to_decl(db, module)) + return Some(NavigationTarget::from_module_to_decl(db, module)); } Definition::Const(c) => c.as_assoc_item(db), Definition::TypeAlias(ta) => ta.as_assoc_item(db), @@ -69,11 +69,7 @@ pub(crate) fn goto_declaration( .flatten() .collect(); - if info.is_empty() { - goto_definition(db, position) - } else { - Some(RangeInfo::new(range, info)) - } + if info.is_empty() { goto_definition(db, position) } else { Some(RangeInfo::new(range, info)) } } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index 84138986f66ba..e920ff5ab4c24 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -1,28 +1,29 @@ use std::{iter, mem::discriminant}; use crate::{ + FilePosition, NavigationTarget, RangeInfo, TryToNav, UpmappingResult, doc_links::token_as_doc_comment, navigation_target::{self, ToNav}, - FilePosition, NavigationTarget, RangeInfo, TryToNav, UpmappingResult, }; use hir::{ - sym, AsAssocItem, AssocItem, CallableKind, FileRange, HasCrate, InFile, MacroFileIdExt, - ModuleDef, Semantics, + AsAssocItem, AssocItem, CallableKind, FileRange, HasCrate, InFile, MacroFileIdExt, ModuleDef, + Semantics, sym, }; use ide_db::{ + RootDatabase, SymbolKind, base_db::{AnchoredPath, RootQueryDb, SourceDatabase, Upcast}, defs::{Definition, IdentClass}, famous_defs::FamousDefs, helpers::pick_best_token, - RootDatabase, SymbolKind, }; use itertools::Itertools; use span::{Edition, FileId}; use syntax::{ - ast::{self, HasLoopBody}, - match_ast, AstNode, AstToken, + AstNode, AstToken, SyntaxKind::*, - SyntaxNode, SyntaxToken, TextRange, T, + SyntaxNode, SyntaxToken, T, TextRange, + ast::{self, HasLoopBody}, + match_ast, }; // Feature: Go to Definition diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs index e1d834b5d1c69..1bc28f28b6f57 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs @@ -1,10 +1,10 @@ use hir::{AsAssocItem, Impl, Semantics}; use ide_db::{ + RootDatabase, defs::{Definition, NameClass, NameRefClass}, helpers::pick_best_token, - RootDatabase, }; -use syntax::{ast, AstNode, SyntaxKind::*, T}; +use syntax::{AstNode, SyntaxKind::*, T, ast}; use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav}; diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs index ddc274a830352..bf48a6e23227e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs @@ -1,6 +1,6 @@ use hir::GenericParam; -use ide_db::{base_db::Upcast, defs::Definition, helpers::pick_best_token, RootDatabase}; -use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, T}; +use ide_db::{RootDatabase, base_db::Upcast, defs::Definition, helpers::pick_best_token}; +use syntax::{AstNode, SyntaxKind::*, SyntaxToken, T, ast, match_ast}; use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav}; diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs index 0ef7eb503f64a..f367d76a126dd 100644 --- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs +++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs @@ -1,7 +1,8 @@ use std::iter; -use hir::{db, FilePosition, FileRange, HirFileId, InFile, Semantics}; +use hir::{FilePosition, FileRange, HirFileId, InFile, Semantics, db}; use ide_db::{ + FxHashMap, FxHashSet, RootDatabase, base_db::salsa::AsDynDatabase, defs::{Definition, IdentClass}, helpers::pick_best_token, @@ -10,17 +11,17 @@ use ide_db::{ eq_label_lt, for_each_tail_expr, full_path_of_name_ref, is_closure_or_blk_with_modif, preorder_expr_with_ctx_checker, }, - FxHashMap, FxHashSet, RootDatabase, }; use span::EditionedFileId; use syntax::{ - ast::{self, HasLoopBody}, - match_ast, AstNode, + AstNode, SyntaxKind::{self, IDENT, INT_NUMBER}, - SyntaxToken, TextRange, WalkEvent, T, + SyntaxToken, T, TextRange, WalkEvent, + ast::{self, HasLoopBody}, + match_ast, }; -use crate::{goto_definition, navigation_target::ToNav, NavigationTarget, TryToNav}; +use crate::{NavigationTarget, TryToNav, goto_definition, navigation_target::ToNav}; #[derive(PartialEq, Eq, Hash)] pub struct HighlightedRange { @@ -156,7 +157,7 @@ fn highlight_references( match resolution.map(Definition::from) { Some(def) => iter::once(def).collect(), None => { - return Some(vec![HighlightedRange { range, category: ReferenceCategory::empty() }]) + return Some(vec![HighlightedRange { range, category: ReferenceCategory::empty() }]); } } } else { @@ -278,11 +279,7 @@ fn highlight_references( } res.extend(usages); - if res.is_empty() { - None - } else { - Some(res.into_iter().collect()) - } + if res.is_empty() { None } else { Some(res.into_iter().collect()) } } fn hl_exit_points( diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 04189ed52aa79..ea1f673e5be1a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -7,26 +7,26 @@ use std::{iter, ops::Not}; use either::Either; use hir::{ - db::DefDatabase, DisplayTarget, GenericDef, GenericSubstitution, HasCrate, HasSource, LangItem, - Semantics, + DisplayTarget, GenericDef, GenericSubstitution, HasCrate, HasSource, LangItem, Semantics, + db::DefDatabase, }; use ide_db::{ + FileRange, FxIndexSet, Ranker, RootDatabase, defs::{Definition, IdentClass, NameRefClass, OperatorClass}, famous_defs::FamousDefs, helpers::pick_best_token, - FileRange, FxIndexSet, Ranker, RootDatabase, }; -use itertools::{multizip, Itertools}; +use itertools::{Itertools, multizip}; use span::Edition; -use syntax::{ast, AstNode, SyntaxKind::*, SyntaxNode, T}; +use syntax::{AstNode, SyntaxKind::*, SyntaxNode, T, ast}; use crate::{ + FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, TryToNav, doc_links::token_as_doc_comment, markdown_remove::remove_markdown, markup::Markup, navigation_target::UpmappingResult, runnables::{runnable_fn, runnable_mod}, - FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, TryToNav, }; #[derive(Clone, Debug, PartialEq, Eq)] pub struct HoverConfig { @@ -512,7 +512,7 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option { - return it.try_to_nav(db).map(UpmappingResult::call_site).map(to_action) + return it.try_to_nav(db).map(UpmappingResult::call_site).map(to_action); } Definition::Adt(it) => Some(it), Definition::SelfType(it) => it.self_ty(db).as_adt(), diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index 1d807fb14c7bf..cf2ff1c9560dc 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -3,33 +3,34 @@ use std::{env, mem, ops::Not}; use either::Either; use hir::{ - db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind, DisplayTarget, DropGlue, + Adt, AsAssocItem, AsExternAssocItem, CaptureKind, DisplayTarget, DropGlue, DynCompatibilityViolation, HasCrate, HasSource, HirDisplay, Layout, LayoutError, MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef, + db::ExpandDatabase, }; use ide_db::{ + RootDatabase, defs::Definition, documentation::HasDocs, famous_defs::FamousDefs, generated::lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, syntax_helpers::prettify_macro_expansion, - RootDatabase, }; use itertools::Itertools; use rustc_apfloat::{ - ieee::{Half as f16, Quad as f128}, Float, + ieee::{Half as f16, Quad as f128}, }; use span::Edition; use stdx::format_to; -use syntax::{algo, ast, match_ast, AstNode, AstToken, Direction, SyntaxToken, T}; +use syntax::{AstNode, AstToken, Direction, SyntaxToken, T, algo, ast, match_ast}; use crate::{ - doc_links::{remove_links, rewrite_links}, - hover::{notable_traits, walk_and_push_ty, SubstTyLen}, - interpret::render_const_eval_error, HoverAction, HoverConfig, HoverResult, Markup, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, + doc_links::{remove_links, rewrite_links}, + hover::{SubstTyLen, notable_traits, walk_and_push_ty}, + interpret::render_const_eval_error, }; pub(super) fn type_info_of( @@ -345,11 +346,7 @@ pub(super) fn try_for_lint(attr: &ast::Attr, token: &SyntaxToken) -> Option return None, }; @@ -417,7 +414,7 @@ fn definition_owner_name(db: &RootDatabase, def: Definition, edition: Edition) - "{}::{}", name.display(db, edition), it.name(db).display(db, edition) - )) + )); } None => Some(it.name(db)), } @@ -435,7 +432,7 @@ fn definition_owner_name(db: &RootDatabase, def: Definition, edition: Edition) - "{}::{}", name.display(db, edition), it.name(db)?.display(db, edition) - )) + )); } None => it.name(db), } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index afddeb6deaa62..0266b87499da2 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -1,9 +1,9 @@ -use expect_test::{expect, Expect}; -use ide_db::{base_db::SourceDatabase, FileRange}; +use expect_test::{Expect, expect}; +use ide_db::{FileRange, base_db::SourceDatabase}; use syntax::TextRange; use crate::{ - fixture, HoverConfig, HoverDocFormat, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, + HoverConfig, HoverDocFormat, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, fixture, }; const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index 57adf3e2a4721..a260944d05536 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -5,21 +5,22 @@ use std::{ use either::Either; use hir::{ - sym, ClosureStyle, DisplayTarget, HasVisibility, HirDisplay, HirDisplayError, HirWrite, - ModuleDef, ModuleDefId, Semantics, + ClosureStyle, DisplayTarget, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef, + ModuleDefId, Semantics, sym, }; -use ide_db::{base_db::salsa::AsDynDatabase, famous_defs::FamousDefs, FileRange, RootDatabase}; -use ide_db::{text_edit::TextEdit, FxHashSet}; +use ide_db::{FileRange, RootDatabase, base_db::salsa::AsDynDatabase, famous_defs::FamousDefs}; +use ide_db::{FxHashSet, text_edit::TextEdit}; use itertools::Itertools; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use span::EditionedFileId; use stdx::never; use syntax::{ + SmolStr, SyntaxNode, TextRange, TextSize, WalkEvent, ast::{self, AstNode, HasGenericParams}, - format_smolstr, match_ast, SmolStr, SyntaxNode, TextRange, TextSize, WalkEvent, + format_smolstr, match_ast, }; -use crate::{navigation_target::TryToNav, FileId}; +use crate::{FileId, navigation_target::TryToNav}; mod adjustment; mod bind_pat; @@ -843,9 +844,9 @@ mod tests { use itertools::Itertools; use test_utils::extract_annotations; - use crate::inlay_hints::{AdjustmentHints, AdjustmentHintsMode}; use crate::DiscriminantHints; - use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints}; + use crate::inlay_hints::{AdjustmentHints, AdjustmentHintsMode}; + use crate::{LifetimeElisionHints, fixture, inlay_hints::InlayHintsConfig}; use super::{ClosureReturnTypeHints, GenericParameterHints, InlayFieldsToResolve}; diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs index 91b8187295236..f2844a2eaa614 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs @@ -13,7 +13,7 @@ use hir::{ use ide_db::famous_defs::FamousDefs; use ide_db::text_edit::TextEditBuilder; -use syntax::ast::{self, prec::ExprPrecedence, AstNode}; +use syntax::ast::{self, AstNode, prec::ExprPrecedence}; use crate::{ AdjustmentHints, AdjustmentHintsMode, InlayHint, InlayHintLabel, InlayHintLabelPart, @@ -224,7 +224,7 @@ fn mode_and_needs_parens_for_adjustment_hints( expr: &ast::Expr, mode: AdjustmentHintsMode, ) -> (bool, bool, bool) { - use {std::cmp::Ordering::*, AdjustmentHintsMode::*}; + use {AdjustmentHintsMode::*, std::cmp::Ordering::*}; match mode { Prefix | Postfix => { @@ -284,8 +284,8 @@ fn needs_parens_for_adjustment_hints(expr: &ast::Expr, postfix: bool) -> (bool, #[cfg(test)] mod tests { use crate::{ - inlay_hints::tests::{check_with_config, DISABLED_CONFIG}, AdjustmentHints, AdjustmentHintsMode, InlayHintsConfig, + inlay_hints::tests::{DISABLED_CONFIG, check_with_config}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs index aab8a3f873994..10cb91713d259 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs @@ -4,7 +4,7 @@ //! let _x /* i32 */= f(4, 4); //! ``` use hir::{DisplayTarget, Semantics}; -use ide_db::{famous_defs::FamousDefs, RootDatabase}; +use ide_db::{RootDatabase, famous_defs::FamousDefs}; use itertools::Itertools; use syntax::{ @@ -13,8 +13,8 @@ use syntax::{ }; use crate::{ - inlay_hints::{closure_has_block_body, label_of_ty, ty_to_text_edit}, InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind, + inlay_hints::{closure_has_block_body, label_of_ty, ty_to_text_edit}, }; pub(super) fn hints( @@ -181,10 +181,10 @@ mod tests { use syntax::{TextRange, TextSize}; use test_utils::extract_annotations; - use crate::{fixture, inlay_hints::InlayHintsConfig, ClosureReturnTypeHints}; + use crate::{ClosureReturnTypeHints, fixture, inlay_hints::InlayHintsConfig}; use crate::inlay_hints::tests::{ - check, check_edit, check_no_edit, check_with_config, DISABLED_CONFIG, TEST_CONFIG, + DISABLED_CONFIG, TEST_CONFIG, check, check_edit, check_no_edit, check_with_config, }; #[track_caller] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs index 5bbb4fe4e66e3..d29173206889d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs @@ -128,8 +128,8 @@ mod tests { use expect_test::expect; use crate::{ - inlay_hints::tests::{check_edit, check_with_config, DISABLED_CONFIG}, InlayHintsConfig, + inlay_hints::tests::{DISABLED_CONFIG, check_edit, check_with_config}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs index e9b728bcaa75d..8ddbfaeffe879 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs @@ -1,7 +1,7 @@ //! Implementation of trait bound hints. //! //! Currently this renders the implied `Sized` bound. -use ide_db::{famous_defs::FamousDefs, FileRange}; +use ide_db::{FileRange, famous_defs::FamousDefs}; use span::EditionedFileId; use syntax::ast::{self, AstNode, HasTypeBounds}; @@ -86,7 +86,7 @@ mod tests { use crate::inlay_hints::InlayHintsConfig; - use crate::inlay_hints::tests::{check_expect, check_with_config, DISABLED_CONFIG}; + use crate::inlay_hints::tests::{DISABLED_CONFIG, check_expect, check_with_config}; #[track_caller] fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs index 604719bc366f5..ff157fa171b50 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs @@ -2,8 +2,8 @@ use hir::DisplayTarget; use ide_db::famous_defs::FamousDefs; use syntax::{ - ast::{self, AstNode}, Direction, NodeOrToken, SyntaxKind, T, + ast::{self, AstNode}, }; use crate::{InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind}; @@ -76,16 +76,15 @@ pub(super) fn hints( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use ide_db::text_edit::{TextRange, TextSize}; use crate::{ - fixture, + InlayHintsConfig, fixture, inlay_hints::{ - tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG}, LazyProperty, + tests::{DISABLED_CONFIG, TEST_CONFIG, check_expect, check_with_config}, }, - InlayHintsConfig, }; #[track_caller] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs index bec6d38ee9cac..de9ca8c000f0b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs @@ -7,13 +7,14 @@ use hir::{DisplayTarget, HirDisplay, Semantics}; use ide_db::{FileRange, RootDatabase}; use span::EditionedFileId; use syntax::{ + SyntaxKind, SyntaxNode, T, ast::{self, AstNode, HasLoopBody, HasName}, - match_ast, SyntaxKind, SyntaxNode, T, + match_ast, }; use crate::{ - inlay_hints::LazyProperty, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, - InlayKind, + InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind, + inlay_hints::LazyProperty, }; pub(super) fn hints( @@ -159,8 +160,8 @@ pub(super) fn hints( #[cfg(test)] mod tests { use crate::{ - inlay_hints::tests::{check_with_config, DISABLED_CONFIG}, InlayHintsConfig, + inlay_hints::tests::{DISABLED_CONFIG, check_with_config}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs index 9b981c0a3acf7..07a86b2c9d3f4 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs @@ -4,7 +4,7 @@ use ide_db::famous_defs::FamousDefs; use ide_db::text_edit::{TextRange, TextSize}; use span::EditionedFileId; -use stdx::{never, TupleExt}; +use stdx::{TupleExt, never}; use syntax::ast::{self, AstNode}; use crate::{ @@ -96,8 +96,8 @@ pub(super) fn hints( #[cfg(test)] mod tests { use crate::{ - inlay_hints::tests::{check_with_config, DISABLED_CONFIG}, InlayHintsConfig, + inlay_hints::tests::{DISABLED_CONFIG, check_with_config}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs index 61c9c25fe7396..16551b64f7ef6 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs @@ -6,8 +6,8 @@ use ide_db::famous_defs::FamousDefs; use syntax::ast::{self, AstNode}; use crate::{ - inlay_hints::{closure_has_block_body, label_of_ty, ty_to_text_edit}, ClosureReturnTypeHints, InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind, + inlay_hints::{closure_has_block_body, label_of_ty, ty_to_text_edit}, }; pub(super) fn hints( @@ -80,7 +80,7 @@ pub(super) fn hints( #[cfg(test)] mod tests { - use crate::inlay_hints::tests::{check_with_config, DISABLED_CONFIG}; + use crate::inlay_hints::tests::{DISABLED_CONFIG, check_with_config}; use super::*; diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs index f1e1955d14ca7..827a0438dd022 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs @@ -6,7 +6,7 @@ //! ``` use hir::Semantics; use ide_db::text_edit::TextEdit; -use ide_db::{famous_defs::FamousDefs, RootDatabase}; +use ide_db::{RootDatabase, famous_defs::FamousDefs}; use span::EditionedFileId; use syntax::ast::{self, AstNode, HasName}; @@ -107,8 +107,8 @@ mod tests { use expect_test::expect; use crate::inlay_hints::{ - tests::{check_edit, check_with_config, DISABLED_CONFIG}, DiscriminantHints, InlayHintsConfig, + tests::{DISABLED_CONFIG, check_edit, check_with_config}, }; #[track_caller] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs index 652dff0bc56e7..20f54b2cd19d6 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs @@ -1,7 +1,7 @@ //! Extern block hints use ide_db::{famous_defs::FamousDefs, text_edit::TextEdit}; use span::EditionedFileId; -use syntax::{ast, AstNode, SyntaxToken}; +use syntax::{AstNode, SyntaxToken, ast}; use crate::{InlayHint, InlayHintsConfig}; @@ -98,7 +98,7 @@ fn item_hint( #[cfg(test)] mod tests { - use crate::inlay_hints::tests::{check_with_config, DISABLED_CONFIG}; + use crate::inlay_hints::tests::{DISABLED_CONFIG, check_with_config}; #[test] fn unadorned() { diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs index 762a4c2655181..fc1083fdca657 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs @@ -1,12 +1,12 @@ //! Implementation of inlay hints for generic parameters. use ide_db::{active_parameter::generic_def_for_node, famous_defs::FamousDefs}; use syntax::{ - ast::{self, AnyHasGenericArgs, HasGenericArgs, HasName}, AstNode, + ast::{self, AnyHasGenericArgs, HasGenericArgs, HasName}, }; use crate::{ - inlay_hints::GenericParameterHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind, + InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind, inlay_hints::GenericParameterHints, }; use super::param_name::is_argument_similar_to_param_name; @@ -145,11 +145,11 @@ fn get_string_representation(arg: &ast::GenericArg) -> Option { #[cfg(test)] mod tests { use crate::{ + InlayHintsConfig, inlay_hints::{ - tests::{check_with_config, DISABLED_CONFIG}, GenericParameterHints, + tests::{DISABLED_CONFIG, check_with_config}, }, - InlayHintsConfig, }; #[track_caller] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs index 390139d214eb0..668232d301c95 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs @@ -6,16 +6,17 @@ //! } //! ``` use hir::{ + ChalkTyInterner, DefWithBody, db::{DefDatabase as _, HirDatabase as _}, mir::{MirSpan, TerminatorKind}, - ChalkTyInterner, DefWithBody, }; -use ide_db::{famous_defs::FamousDefs, FileRange}; +use ide_db::{FileRange, famous_defs::FamousDefs}; use span::EditionedFileId; use syntax::{ + ToSmolStr, ast::{self, AstNode}, - match_ast, ToSmolStr, + match_ast, }; use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind}; @@ -143,8 +144,8 @@ fn nearest_token_after_node( #[cfg(test)] mod tests { use crate::{ - inlay_hints::tests::{check_with_config, DISABLED_CONFIG}, InlayHintsConfig, + inlay_hints::tests::{DISABLED_CONFIG, check_with_config}, }; const ONLY_DROP_CONFIG: InlayHintsConfig = diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs index ae5b519b43d00..f3be09f30a135 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs @@ -7,8 +7,8 @@ use ide_db::famous_defs::FamousDefs; use ide_db::text_edit::TextEdit; use span::EditionedFileId; use syntax::{ - ast::{self, AstNode}, SyntaxKind, + ast::{self, AstNode}, }; use crate::{InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind, LifetimeElisionHints}; @@ -56,8 +56,8 @@ pub(super) fn hints( #[cfg(test)] mod tests { use crate::{ - inlay_hints::tests::{check_with_config, TEST_CONFIG}, InlayHintsConfig, LifetimeElisionHints, + inlay_hints::tests::{TEST_CONFIG, check_with_config}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs index 7b0b3e19f2f08..baba49a427d19 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs @@ -4,18 +4,18 @@ //! ``` use std::iter; -use ide_db::{famous_defs::FamousDefs, syntax_helpers::node_ext::walk_ty, FxHashMap}; +use ide_db::{FxHashMap, famous_defs::FamousDefs, syntax_helpers::node_ext::walk_ty}; use itertools::Itertools; use span::EditionedFileId; +use syntax::{SmolStr, format_smolstr}; use syntax::{ - ast::{self, AstNode, HasGenericParams, HasName}, SyntaxKind, SyntaxToken, + ast::{self, AstNode, HasGenericParams, HasName}, }; -use syntax::{format_smolstr, SmolStr}; use crate::{ - inlay_hints::InlayHintCtx, InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind, - LifetimeElisionHints, + InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind, LifetimeElisionHints, + inlay_hints::InlayHintCtx, }; pub(super) fn fn_hints( @@ -274,7 +274,8 @@ fn hints_( }); let ctx = &*ctx; move || { - generic.by_ref() + generic + .by_ref() .find(|s| ctx.lifetime_stacks.iter().flat_map(|it| it.iter()).all(|n| n != s)) .unwrap_or_default() } @@ -406,8 +407,8 @@ fn hints_( #[cfg(test)] mod tests { use crate::{ - inlay_hints::tests::{check, check_with_config, TEST_CONFIG}, InlayHintsConfig, LifetimeElisionHints, + inlay_hints::tests::{TEST_CONFIG, check, check_with_config}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs index 8f01b1bd38b50..44ea5351fbdd6 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs @@ -6,13 +6,13 @@ use either::Either; use hir::{Callable, Semantics}; -use ide_db::{famous_defs::FamousDefs, RootDatabase}; +use ide_db::{RootDatabase, famous_defs::FamousDefs}; use span::EditionedFileId; use stdx::to_lower_snake_case; use syntax::{ - ast::{self, AstNode, HasArgList, HasName, UnaryOp}, ToSmolStr, + ast::{self, AstNode, HasArgList, HasName, UnaryOp}, }; use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind}; @@ -257,8 +257,8 @@ fn is_adt_constructor_similar_to_param_name( #[cfg(test)] mod tests { use crate::{ - inlay_hints::tests::{check_with_config, DISABLED_CONFIG}, InlayHintsConfig, + inlay_hints::tests::{DISABLED_CONFIG, check_with_config}, }; #[track_caller] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs index de9b0e98a4beb..d67d84588402e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs @@ -5,7 +5,7 @@ //! ``` use ide_db::famous_defs::FamousDefs; use span::EditionedFileId; -use syntax::{ast, SyntaxToken, T}; +use syntax::{SyntaxToken, T, ast}; use crate::{InlayHint, InlayHintsConfig}; @@ -41,8 +41,8 @@ fn inlay_hint(token: SyntaxToken) -> InlayHint { #[cfg(test)] mod tests { use crate::{ - inlay_hints::tests::{check_with_config, DISABLED_CONFIG}, InlayHintsConfig, + inlay_hints::tests::{DISABLED_CONFIG, check_with_config}, }; #[test] diff --git a/src/tools/rust-analyzer/crates/ide/src/interpret.rs b/src/tools/rust-analyzer/crates/ide/src/interpret.rs index 0499d8a447fbf..8f9d2d6bf111b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/interpret.rs +++ b/src/tools/rust-analyzer/crates/ide/src/interpret.rs @@ -1,8 +1,8 @@ use hir::{ConstEvalError, DefWithBody, DisplayTarget, Semantics}; -use ide_db::{base_db::SourceDatabase, FilePosition, LineIndexDatabase, RootDatabase}; +use ide_db::{FilePosition, LineIndexDatabase, RootDatabase, base_db::SourceDatabase}; use std::time::{Duration, Instant}; use stdx::format_to; -use syntax::{algo::ancestors_at_offset, ast, AstNode, TextRange}; +use syntax::{AstNode, TextRange, algo::ancestors_at_offset, ast}; // Feature: Interpret A Function, Static Or Const. // diff --git a/src/tools/rust-analyzer/crates/ide/src/join_lines.rs b/src/tools/rust-analyzer/crates/ide/src/join_lines.rs index ea18a97070c3a..0188c105faa78 100644 --- a/src/tools/rust-analyzer/crates/ide/src/join_lines.rs +++ b/src/tools/rust-analyzer/crates/ide/src/join_lines.rs @@ -2,10 +2,10 @@ use ide_assists::utils::extract_trivial_expression; use ide_db::syntax_helpers::node_ext::expr_as_name_ref; use itertools::Itertools; use syntax::{ - ast::{self, AstNode, AstToken, IsString}, NodeOrToken, SourceFile, SyntaxElement, SyntaxKind::{self, USE_TREE, WHITESPACE}, - SyntaxToken, TextRange, TextSize, T, + SyntaxToken, T, TextRange, TextSize, + ast::{self, AstNode, AstToken, IsString}, }; use ide_db::text_edit::{TextEdit, TextEditBuilder}; diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index 79863f4680d80..f8eb676bfc442 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -61,19 +61,20 @@ use std::panic::UnwindSafe; use cfg::CfgOptions; use fetch_crates::CrateInfo; -use hir::{sym, ChangeWithProcMacros}; +use hir::{ChangeWithProcMacros, sym}; use ide_db::{ + FxHashMap, FxIndexSet, LineIndexDatabase, base_db::{ - salsa::{AsDynDatabase, Cancelled}, CrateOrigin, CrateWorkspaceData, Env, FileSet, RootQueryDb, SourceDatabase, Upcast, VfsPath, + salsa::{AsDynDatabase, Cancelled}, }, - prime_caches, symbol_index, FxHashMap, FxIndexSet, LineIndexDatabase, + prime_caches, symbol_index, }; use span::EditionedFileId; use syntax::SourceFile; use triomphe::Arc; -use view_memory_layout::{view_memory_layout, RecursiveMemoryLayout}; +use view_memory_layout::{RecursiveMemoryLayout, view_memory_layout}; use crate::navigation_target::ToNav; @@ -110,8 +111,8 @@ pub use crate::{ StaticIndex, StaticIndexedFile, TokenId, TokenStaticData, VendoredLibrariesConfig, }, syntax_highlighting::{ - tags::{Highlight, HlMod, HlMods, HlOperator, HlPunct, HlTag}, HighlightConfig, HlRange, + tags::{Highlight, HlMod, HlMods, HlOperator, HlPunct, HlTag}, }, test_explorer::{TestItem, TestItemKind}, }; @@ -125,6 +126,7 @@ pub use ide_completion::{ }; pub use ide_db::text_edit::{Indel, TextEdit}; pub use ide_db::{ + FileId, FilePosition, FileRange, RootDatabase, Severity, SymbolKind, base_db::{Crate, CrateGraphBuilder, FileChange, SourceRoot, SourceRootId}, documentation::Documentation, label::Label, @@ -133,7 +135,6 @@ pub use ide_db::{ search::{ReferenceCategory, SearchScope}, source_change::{FileSystemEdit, SnippetEdit, SourceChange}, symbol_index::Query, - FileId, FilePosition, FileRange, RootDatabase, Severity, SymbolKind, }; pub use ide_diagnostics::{Diagnostic, DiagnosticCode, DiagnosticsConfig, ExprFillDefaultMode}; pub use ide_ssr::SsrError; diff --git a/src/tools/rust-analyzer/crates/ide/src/matching_brace.rs b/src/tools/rust-analyzer/crates/ide/src/matching_brace.rs index 67346ea9cf90f..b2b91d6e3cf34 100644 --- a/src/tools/rust-analyzer/crates/ide/src/matching_brace.rs +++ b/src/tools/rust-analyzer/crates/ide/src/matching_brace.rs @@ -1,6 +1,6 @@ use syntax::{ + SourceFile, SyntaxKind, T, TextSize, ast::{self, AstNode}, - SourceFile, SyntaxKind, TextSize, T, }; // Feature: Matching Brace diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs index 5754b4fa82f43..4a06cd919fc3b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs +++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs @@ -5,15 +5,15 @@ use core::fmt; use hir::{Adt, AsAssocItem, Crate, HirDisplay, MacroKind, Semantics}; use ide_db::{ + FilePosition, RootDatabase, base_db::{CrateOrigin, LangCrateOrigin}, defs::{Definition, IdentClass}, helpers::pick_best_token, - FilePosition, RootDatabase, }; use itertools::Itertools; use syntax::{AstNode, SyntaxKind::*, T}; -use crate::{doc_links::token_as_doc_comment, parent_module::crates_for, RangeInfo}; +use crate::{RangeInfo, doc_links::token_as_doc_comment, parent_module::crates_for}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum MonikerDescriptorKind { @@ -194,11 +194,7 @@ pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformati Definition::Function(it) => { if it.as_assoc_item(db).is_some() { if it.has_self_param(db) { - if it.has_body(db) { - Method - } else { - TraitMethod - } + if it.has_body(db) { Method } else { TraitMethod } } else { StaticMethod } @@ -405,7 +401,7 @@ fn display(db: &RootDatabase, module: hir::Module, it: T) -> Stri #[cfg(test)] mod tests { - use crate::{fixture, MonikerResult}; + use crate::{MonikerResult, fixture}; use super::MonikerKind; diff --git a/src/tools/rust-analyzer/crates/ide/src/move_item.rs b/src/tools/rust-analyzer/crates/ide/src/move_item.rs index 3fb3a788b9182..f3bb3df1cd8d7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/move_item.rs +++ b/src/tools/rust-analyzer/crates/ide/src/move_item.rs @@ -3,9 +3,9 @@ use std::{iter::once, mem}; use hir::Semantics; use ide_db::syntax_helpers::tree_diff::diff; use ide_db::text_edit::{TextEdit, TextEditBuilder}; -use ide_db::{helpers::pick_best_token, FileRange, RootDatabase}; +use ide_db::{FileRange, RootDatabase, helpers::pick_best_token}; use itertools::Itertools; -use syntax::{ast, match_ast, AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange}; +use syntax::{AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, ast, match_ast}; #[derive(Copy, Clone, Debug)] pub enum Direction { @@ -174,7 +174,7 @@ fn replace_nodes<'a>( #[cfg(test)] mod tests { use crate::fixture; - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use crate::Direction; diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs index d67aaac06fb95..4679794287b2e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs +++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs @@ -5,19 +5,20 @@ use std::fmt; use arrayvec::ArrayVec; use either::Either; use hir::{ - db::ExpandDatabase, symbols::FileSymbol, AssocItem, FieldSource, HasContainer, HasCrate, - HasSource, HirDisplay, HirFileId, InFile, LocalSource, ModuleSource, + AssocItem, FieldSource, HasContainer, HasCrate, HasSource, HirDisplay, HirFileId, InFile, + LocalSource, ModuleSource, db::ExpandDatabase, symbols::FileSymbol, }; use ide_db::{ + FileId, FileRange, RootDatabase, SymbolKind, defs::Definition, documentation::{Documentation, HasDocs}, - FileId, FileRange, RootDatabase, SymbolKind, }; use span::Edition; use stdx::never; use syntax::{ + AstNode, SmolStr, SyntaxNode, TextRange, ToSmolStr, ast::{self, HasName}, - format_smolstr, AstNode, SmolStr, SyntaxNode, TextRange, ToSmolStr, + format_smolstr, }; /// `NavigationTarget` represents an element in the editor's UI which you can @@ -953,7 +954,7 @@ fn orig_range_r( mod tests { use expect_test::expect; - use crate::{fixture, Query}; + use crate::{Query, fixture}; #[test] fn test_nav_for_symbol() { diff --git a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs index 06ab4750ac5b9..4e70bf3af3aaa 100644 --- a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs +++ b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs @@ -1,7 +1,7 @@ -use hir::{db::DefDatabase, Semantics}; +use hir::{Semantics, db::DefDatabase}; use ide_db::{ - base_db::{Crate, RootQueryDb, Upcast}, FileId, FilePosition, RootDatabase, + base_db::{Crate, RootQueryDb, Upcast}, }; use itertools::Itertools; use syntax::{ diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs index 069818d50e76a..71c42cc8b579e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/references.rs +++ b/src/tools/rust-analyzer/crates/ide/src/references.rs @@ -11,21 +11,22 @@ use hir::{PathResolution, Semantics}; use ide_db::{ + FileId, RootDatabase, defs::{Definition, NameClass, NameRefClass}, search::{ReferenceCategory, SearchScope, UsageSearchResult}, - FileId, RootDatabase, }; use itertools::Itertools; use nohash_hasher::IntMap; use span::Edition; use syntax::{ - ast::{self, HasName}, - match_ast, AstNode, + AstNode, SyntaxKind::*, - SyntaxNode, TextRange, TextSize, T, + SyntaxNode, T, TextRange, TextSize, + ast::{self, HasName}, + match_ast, }; -use crate::{highlight_related, FilePosition, HighlightedRange, NavigationTarget, TryToNav}; +use crate::{FilePosition, HighlightedRange, NavigationTarget, TryToNav, highlight_related}; #[derive(Debug, Clone)] pub struct ReferenceSearchResult { @@ -336,12 +337,12 @@ fn handle_control_flow_keywords( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use ide_db::FileId; use span::EditionedFileId; use stdx::format_to; - use crate::{fixture, SearchScope}; + use crate::{SearchScope, fixture}; #[test] fn exclude_tests() { diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs index 57d297700ad37..8fdd460a09f8e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs @@ -6,15 +6,15 @@ use hir::{AsAssocItem, HirFileIdExt, InFile, Semantics}; use ide_db::{ + FileId, FileRange, RootDatabase, base_db::salsa::AsDynDatabase, defs::{Definition, NameClass, NameRefClass}, - rename::{bail, format_err, source_edit_from_references, IdentifierKind}, + rename::{IdentifierKind, bail, format_err, source_edit_from_references}, source_change::SourceChangeBuilder, - FileId, FileRange, RootDatabase, }; use itertools::Itertools; use stdx::{always, never}; -use syntax::{ast, AstNode, SyntaxKind, SyntaxNode, TextRange, TextSize}; +use syntax::{AstNode, SyntaxKind, SyntaxNode, TextRange, TextSize, ast}; use ide_db::text_edit::TextEdit; @@ -446,7 +446,7 @@ fn text_edit_from_self_param(self_param: &ast::SelfParam, new_name: &str) -> Opt #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use ide_db::source_change::SourceChange; use ide_db::text_edit::TextEdit; use itertools::Itertools; diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index f2cb3c1f991a7..44dd38ed9c99d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -4,28 +4,29 @@ use arrayvec::ArrayVec; use ast::HasName; use cfg::{CfgAtom, CfgExpr}; use hir::{ - db::HirDatabase, sym, symbols::FxIndexSet, AsAssocItem, AttrsWithOwner, HasAttrs, HasCrate, - HasSource, HirFileIdExt, ModPath, Name, PathKind, Semantics, Symbol, + AsAssocItem, AttrsWithOwner, HasAttrs, HasCrate, HasSource, HirFileIdExt, ModPath, Name, + PathKind, Semantics, Symbol, db::HirDatabase, sym, symbols::FxIndexSet, }; use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn}; use ide_db::{ + FilePosition, FxHashMap, FxIndexMap, RootDatabase, SymbolKind, base_db::RootQueryDb, defs::Definition, documentation::docs_from_attrs, helpers::visit_file_defs, search::{FileReferenceNode, SearchScope}, - FilePosition, FxHashMap, FxIndexMap, RootDatabase, SymbolKind, }; use itertools::Itertools; use smallvec::SmallVec; use span::{Edition, TextSize}; use stdx::format_to; use syntax::{ + SmolStr, SyntaxNode, ToSmolStr, ast::{self, AstNode}, - format_smolstr, SmolStr, SyntaxNode, ToSmolStr, + format_smolstr, }; -use crate::{references, FileId, NavigationTarget, ToNav, TryToNav}; +use crate::{FileId, NavigationTarget, ToNav, TryToNav, references}; #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Runnable { @@ -752,7 +753,7 @@ impl UpdateTest { #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use crate::fixture; diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs index ce3c4238b5b18..bd14f830dd4d3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs +++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs @@ -8,17 +8,17 @@ use hir::{ AssocItem, DisplayTarget, GenericParam, HirDisplay, ModuleDef, PathResolution, Semantics, Trait, }; use ide_db::{ + FilePosition, FxIndexMap, active_parameter::{callable_for_node, generic_def_for_node}, documentation::{Documentation, HasDocs}, - FilePosition, FxIndexMap, }; use span::Edition; use stdx::format_to; use syntax::{ - algo, + AstNode, Direction, NodeOrToken, SyntaxElementChildren, SyntaxNode, SyntaxToken, T, TextRange, + TextSize, ToSmolStr, algo, ast::{self, AstChildren, HasArgList}, - match_ast, AstNode, Direction, NodeOrToken, SyntaxElementChildren, SyntaxNode, SyntaxToken, - TextRange, TextSize, ToSmolStr, T, + match_ast, }; use crate::RootDatabase; @@ -327,7 +327,7 @@ fn signature_help_for_generics( } // These don't have generic args that can be specified hir::GenericDef::Impl(_) | hir::GenericDef::Const(_) | hir::GenericDef::Static(_) => { - return None + return None; } } @@ -695,9 +695,8 @@ fn signature_help_for_tuple_pat_ish( } #[cfg(test)] mod tests { - - use expect_test::{expect, Expect}; + use expect_test::{Expect, expect}; use ide_db::FilePosition; use stdx::format_to; use test_fixture::ChangeFixture; diff --git a/src/tools/rust-analyzer/crates/ide/src/ssr.rs b/src/tools/rust-analyzer/crates/ide/src/ssr.rs index 81b5988126519..5e439bd38a58a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/ssr.rs +++ b/src/tools/rust-analyzer/crates/ide/src/ssr.rs @@ -3,7 +3,7 @@ //! depend on the ide_ssr crate. use ide_assists::{Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel}; -use ide_db::{label::Label, source_change::SourceChange, FileRange, RootDatabase}; +use ide_db::{FileRange, RootDatabase, label::Label, source_change::SourceChange}; pub(crate) fn ssr_assists( db: &RootDatabase, @@ -59,8 +59,8 @@ mod tests { use expect_test::expect; use ide_assists::{Assist, AssistResolveStrategy}; use ide_db::{ - base_db::salsa::Durability, symbol_index::SymbolsDatabase, FileRange, FxHashSet, - RootDatabase, + FileRange, FxHashSet, RootDatabase, base_db::salsa::Durability, + symbol_index::SymbolsDatabase, }; use test_fixture::WithFixture; use triomphe::Arc; diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs index c1562769309ed..1244132065045 100644 --- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs +++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs @@ -1,25 +1,25 @@ //! This module provides `StaticIndex` which is used for powering //! read-only code browsers and emitting LSIF -use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics}; +use hir::{Crate, HirFileIdExt, Module, Semantics, db::HirDatabase}; use ide_db::{ + FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, base_db::{RootQueryDb, SourceDatabase, VfsPath}, defs::Definition, documentation::Documentation, famous_defs::FamousDefs, helpers::get_definition, - FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, }; use span::Edition; -use syntax::{AstNode, SyntaxKind::*, SyntaxNode, TextRange, T}; +use syntax::{AstNode, SyntaxKind::*, SyntaxNode, T, TextRange}; use crate::navigation_target::UpmappingResult; use crate::{ - hover::{hover_for_definition, SubstTyLen}, + Analysis, Fold, HoverConfig, HoverResult, InlayHint, InlayHintsConfig, TryToNav, + hover::{SubstTyLen, hover_for_definition}, inlay_hints::{AdjustmentHintsMode, InlayFieldsToResolve}, - moniker::{def_to_kind, def_to_moniker, MonikerResult, SymbolInformationKind}, + moniker::{MonikerResult, SymbolInformationKind, def_to_kind, def_to_moniker}, parent_module::crates_for, - Analysis, Fold, HoverConfig, HoverResult, InlayHint, InlayHintsConfig, TryToNav, }; /// A static representation of fully analyzed source code. @@ -307,8 +307,8 @@ impl StaticIndex<'_> { #[cfg(test)] mod tests { - use crate::{fixture, StaticIndex}; - use ide_db::{base_db::VfsPath, FileRange, FxHashSet}; + use crate::{StaticIndex, fixture}; + use ide_db::{FileRange, FxHashSet, base_db::VfsPath}; use syntax::TextSize; use super::VendoredLibrariesConfig; diff --git a/src/tools/rust-analyzer/crates/ide/src/status.rs b/src/tools/rust-analyzer/crates/ide/src/status.rs index 52d38041ec125..55a0db2d82046 100644 --- a/src/tools/rust-analyzer/crates/ide/src/status.rs +++ b/src/tools/rust-analyzer/crates/ide/src/status.rs @@ -1,5 +1,5 @@ -use ide_db::base_db::{BuiltCrateData, ExtraCrateData}; use ide_db::RootDatabase; +use ide_db::base_db::{BuiltCrateData, ExtraCrateData}; use itertools::Itertools; use span::FileId; use stdx::format_to; diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs index ef5d480b49c70..79e5baf4a77d3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs @@ -19,24 +19,24 @@ use hir::{ DefWithBody, HirFileIdExt, InFile, InRealFile, MacroFileIdExt, MacroKind, Name, Semantics, }; use ide_db::{ - base_db::salsa::AsDynDatabase, FxHashMap, FxHashSet, Ranker, RootDatabase, SymbolKind, + FxHashMap, FxHashSet, Ranker, RootDatabase, SymbolKind, base_db::salsa::AsDynDatabase, }; use span::EditionedFileId; use syntax::{ - ast::{self, IsString}, AstNode, AstToken, NodeOrToken, SyntaxKind::*, - SyntaxNode, SyntaxToken, TextRange, WalkEvent, T, + SyntaxNode, SyntaxToken, T, TextRange, WalkEvent, + ast::{self, IsString}, }; use crate::{ + FileId, HlMod, HlOperator, HlPunct, HlTag, syntax_highlighting::{ escape::{highlight_escape_byte, highlight_escape_char, highlight_escape_string}, format::highlight_format_string, highlights::Highlights, tags::Highlight, }, - FileId, HlMod, HlOperator, HlPunct, HlTag, }; pub(crate) use html::highlight_as_html; diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs index cc02aff2acf8a..00f5b3264cbac 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs @@ -1,15 +1,15 @@ //! Syntax highlighting for format macro strings. use ide_db::{ - defs::Definition, - syntax_helpers::format_string::{is_format_string, lex_format_specifiers, FormatSpecifier}, SymbolKind, + defs::Definition, + syntax_helpers::format_string::{FormatSpecifier, is_format_string, lex_format_specifiers}, }; use span::Edition; -use syntax::{ast, AstToken}; +use syntax::{AstToken, ast}; use crate::{ - syntax_highlighting::{highlight::highlight_def, highlights::Highlights}, HlRange, HlTag, + syntax_highlighting::{highlight::highlight_def, highlights::Highlights}, }; pub(super) fn highlight_format_string( diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index 2b7c871a386d2..fb25f0015585e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -5,21 +5,21 @@ use std::ops::ControlFlow; use either::Either; use hir::{AsAssocItem, HasVisibility, MacroFileIdExt, Semantics}; use ide_db::{ + FxHashMap, RootDatabase, SymbolKind, defs::{Definition, IdentClass, NameClass, NameRefClass}, syntax_helpers::node_ext::walk_pat, - FxHashMap, RootDatabase, SymbolKind, }; use span::Edition; use stdx::hash_once; use syntax::{ - ast, match_ast, AstNode, AstPtr, AstToken, NodeOrToken, + AstNode, AstPtr, AstToken, NodeOrToken, SyntaxKind::{self, *}, - SyntaxNode, SyntaxNodePtr, SyntaxToken, T, + SyntaxNode, SyntaxNodePtr, SyntaxToken, T, ast, match_ast, }; use crate::{ - syntax_highlighting::tags::{HlOperator, HlPunct}, Highlight, HlMod, HlTag, + syntax_highlighting::tags::{HlOperator, HlPunct}, }; pub(super) fn token( @@ -143,11 +143,7 @@ fn punctuation( let ptr = operator_parent .as_ref() .and_then(|it| AstPtr::try_from_raw(SyntaxNodePtr::new(it))); - if ptr.is_some_and(is_unsafe_node) { - h | HlMod::Unsafe - } else { - h - } + if ptr.is_some_and(is_unsafe_node) { h | HlMod::Unsafe } else { h } } (T![-], PREFIX_EXPR) => { let prefix_expr = @@ -223,11 +219,7 @@ fn punctuation( let is_unsafe = is_unsafe_macro || operator_parent .and_then(|it| { - if ast::ArgList::can_cast(it.kind()) { - it.parent() - } else { - Some(it) - } + if ast::ArgList::can_cast(it.kind()) { it.parent() } else { Some(it) } }) .and_then(|it| AstPtr::try_from_raw(SyntaxNodePtr::new(&it))) .is_some_and(is_unsafe_node); @@ -296,7 +288,7 @@ fn highlight_name_ref( let name_class = match NameRefClass::classify(sema, &name_ref) { Some(name_kind) => name_kind, None if syntactic_name_ref_highlighting => { - return highlight_name_ref_by_syntax(name_ref, sema, krate, is_unsafe_node) + return highlight_name_ref_by_syntax(name_ref, sema, krate, is_unsafe_node); } // FIXME: This is required for helper attributes used by proc-macros, as those do not map down // to anything when used. @@ -818,11 +810,7 @@ fn highlight_name_ref_by_syntax( let h = HlTag::Symbol(SymbolKind::Field); let is_unsafe = ast::Expr::cast(parent) .is_some_and(|it| is_unsafe_node(AstPtr::new(&it).wrap_left())); - if is_unsafe { - h | HlMod::Unsafe - } else { - h.into() - } + if is_unsafe { h | HlMod::Unsafe } else { h.into() } } RECORD_EXPR_FIELD | RECORD_PAT_FIELD => HlTag::Symbol(SymbolKind::Field).into(), PATH_SEGMENT => { diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs index 6a03da6a6eaa5..cd69a6eb23994 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs @@ -8,8 +8,8 @@ use stdx::format_to; use syntax::AstNode; use crate::{ - syntax_highlighting::{highlight, HighlightConfig}, FileId, RootDatabase, + syntax_highlighting::{HighlightConfig, highlight}, }; pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: bool) -> String { diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs index 1be90ad6a1ebc..13922eba19194 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs @@ -3,21 +3,21 @@ use std::mem; use either::Either; -use hir::{sym, HirFileId, InFile, Semantics}; +use hir::{HirFileId, InFile, Semantics, sym}; use ide_db::{ - active_parameter::ActiveParameter, defs::Definition, documentation::docs_with_rangemap, - rust_doc::is_rust_fence, SymbolKind, + SymbolKind, active_parameter::ActiveParameter, defs::Definition, + documentation::docs_with_rangemap, rust_doc::is_rust_fence, }; use span::EditionedFileId; use syntax::{ - ast::{self, AstNode, IsString, QuoteOffsets}, AstToken, NodeOrToken, SyntaxNode, TextRange, TextSize, + ast::{self, AstNode, IsString, QuoteOffsets}, }; use crate::{ - doc_links::{doc_attributes, extract_definitions_from_docs, resolve_doc_path_for_def}, - syntax_highlighting::{highlights::Highlights, injector::Injector, HighlightConfig}, Analysis, HlMod, HlRange, HlTag, RootDatabase, + doc_links::{doc_attributes, extract_definitions_from_docs, resolve_doc_path_for_def}, + syntax_highlighting::{HighlightConfig, highlights::Highlights, injector::Injector}, }; pub(super) fn ra_fixture( diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/injector.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/injector.rs index a902fd717f099..c30f797324967 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/injector.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/injector.rs @@ -53,11 +53,7 @@ impl Delta { where T: Ord + Sub, { - if to >= from { - Delta::Add(to - from) - } else { - Delta::Sub(from - to) - } + if to >= from { Delta::Add(to - from) } else { Delta::Sub(from - to) } } } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index 9e8af4bac2277..4b3fec1d2f7c9 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -1,11 +1,11 @@ use std::time::Instant; -use expect_test::{expect_file, ExpectFile}; +use expect_test::{ExpectFile, expect_file}; use ide_db::SymbolKind; use span::Edition; -use test_utils::{bench, bench_fixture, skip_slow_tests, AssertLinear}; +use test_utils::{AssertLinear, bench, bench_fixture, skip_slow_tests}; -use crate::{fixture, FileRange, HighlightConfig, HlTag, TextRange}; +use crate::{FileRange, HighlightConfig, HlTag, TextRange, fixture}; const HL_CONFIG: HighlightConfig = HighlightConfig { strings: true, diff --git a/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs index d22133c856587..06cbd50e946ac 100644 --- a/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs +++ b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs @@ -2,10 +2,10 @@ use hir::{Crate, Module, ModuleDef, Semantics}; use ide_db::base_db; -use ide_db::{base_db::RootQueryDb, FileId, RootDatabase}; +use ide_db::{FileId, RootDatabase, base_db::RootQueryDb}; use syntax::TextRange; -use crate::{runnables::runnable_fn, NavigationTarget, Runnable, TryToNav}; +use crate::{NavigationTarget, Runnable, TryToNav, runnables::runnable_fn}; #[derive(Debug)] pub enum TestItemKind { diff --git a/src/tools/rust-analyzer/crates/ide/src/typing.rs b/src/tools/rust-analyzer/crates/ide/src/typing.rs index f583aa801eaac..bb04fdbe88af7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/typing.rs +++ b/src/tools/rust-analyzer/crates/ide/src/typing.rs @@ -16,16 +16,16 @@ mod on_enter; use ide_db::{ - base_db::{salsa::AsDynDatabase, RootQueryDb}, FilePosition, RootDatabase, + base_db::{RootQueryDb, salsa::AsDynDatabase}, }; use span::{Edition, EditionedFileId}; use std::iter; use syntax::{ - algo::{ancestors_at_offset, find_node_at_offset}, - ast::{self, edit::IndentLevel, AstToken}, AstNode, Parse, SourceFile, SyntaxKind, TextRange, TextSize, + algo::{ancestors_at_offset, find_node_at_offset}, + ast::{self, AstToken, edit::IndentLevel}, }; use ide_db::text_edit::TextEdit; diff --git a/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs b/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs index 8cadb61040390..d684b0efc5149 100644 --- a/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs +++ b/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs @@ -2,14 +2,14 @@ //! comments, but should handle indent some time in the future as well. use ide_db::base_db::RootQueryDb; -use ide_db::{base_db::salsa::AsDynDatabase, FilePosition, RootDatabase}; +use ide_db::{FilePosition, RootDatabase, base_db::salsa::AsDynDatabase}; use span::EditionedFileId; use syntax::{ - algo::find_node_at_offset, - ast::{self, edit::IndentLevel, AstToken}, AstNode, SmolStr, SourceFile, SyntaxKind::*, SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, + algo::find_node_at_offset, + ast::{self, AstToken, edit::IndentLevel}, }; use ide_db::text_edit::TextEdit; diff --git a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs index 09f21ecfe41cc..e878c9afee2b1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs @@ -1,9 +1,9 @@ use dot::{Id, LabelText}; use ide_db::{ + FxHashMap, RootDatabase, base_db::{ BuiltCrateData, BuiltDependency, Crate, ExtraCrateData, RootQueryDb, SourceDatabase, }, - FxHashMap, RootDatabase, }; // Feature: View Crate Graph diff --git a/src/tools/rust-analyzer/crates/ide/src/view_hir.rs b/src/tools/rust-analyzer/crates/ide/src/view_hir.rs index bfdf9d0f3374e..954917d4c09ee 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_hir.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_hir.rs @@ -1,6 +1,6 @@ use hir::{DefWithBody, Semantics}; use ide_db::{FilePosition, RootDatabase}; -use syntax::{algo::ancestors_at_offset, ast, AstNode}; +use syntax::{AstNode, algo::ancestors_at_offset, ast}; // Feature: View Hir // diff --git a/src/tools/rust-analyzer/crates/ide/src/view_item_tree.rs b/src/tools/rust-analyzer/crates/ide/src/view_item_tree.rs index 67c241cbb9153..a230b30ed3712 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_item_tree.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_item_tree.rs @@ -1,4 +1,4 @@ -use hir::{db::DefDatabase, Semantics}; +use hir::{Semantics, db::DefDatabase}; use ide_db::{FileId, RootDatabase}; use span::EditionedFileId; diff --git a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs index 02e3b1d500f26..140ae4265be7d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs @@ -2,9 +2,9 @@ use std::fmt; use hir::{DisplayTarget, Field, HirDisplay, Layout, Semantics, Type}; use ide_db::{ + RootDatabase, defs::Definition, helpers::{get_definition, pick_best_token}, - RootDatabase, }; use syntax::{AstNode, SyntaxKind}; diff --git a/src/tools/rust-analyzer/crates/ide/src/view_mir.rs b/src/tools/rust-analyzer/crates/ide/src/view_mir.rs index aa4ff64a819e1..6ca231c7a81a6 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_mir.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_mir.rs @@ -1,6 +1,6 @@ use hir::{DefWithBody, Semantics}; use ide_db::{FilePosition, RootDatabase}; -use syntax::{algo::ancestors_at_offset, ast, AstNode}; +use syntax::{AstNode, algo::ancestors_at_offset, ast}; // Feature: View Mir // diff --git a/src/tools/rust-analyzer/crates/ide/src/view_syntax_tree.rs b/src/tools/rust-analyzer/crates/ide/src/view_syntax_tree.rs index 407720864bfdb..ecd93e8b28190 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_syntax_tree.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_syntax_tree.rs @@ -1,13 +1,13 @@ use hir::Semantics; use ide_db::{ - line_index::{LineCol, LineIndex}, FileId, LineIndexDatabase, RootDatabase, + line_index::{LineCol, LineIndex}, }; use span::{TextRange, TextSize}; use stdx::format_to; use syntax::{ - ast::{self, IsString}, AstNode, AstToken, NodeOrToken, SourceFile, SyntaxNode, SyntaxToken, WalkEvent, + ast::{self, IsString}, }; use triomphe::Arc; diff --git a/src/tools/rust-analyzer/crates/intern/src/lib.rs b/src/tools/rust-analyzer/crates/intern/src/lib.rs index 58327419f6314..6548bb18269b3 100644 --- a/src/tools/rust-analyzer/crates/intern/src/lib.rs +++ b/src/tools/rust-analyzer/crates/intern/src/lib.rs @@ -10,7 +10,7 @@ use std::{ }; use dashmap::{DashMap, SharedValue}; -use hashbrown::{hash_map::RawEntryMut, HashMap}; +use hashbrown::{HashMap, hash_map::RawEntryMut}; use rustc_hash::FxHasher; use triomphe::Arc; @@ -21,7 +21,7 @@ type Guard = dashmap::RwLockWriteGuard< >; mod symbol; -pub use self::symbol::{symbols as sym, Symbol}; +pub use self::symbol::{Symbol, symbols as sym}; pub struct Interned { arc: Arc, diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index f6a74d97416ef..f02fb6d14f17b 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -11,7 +11,7 @@ use std::{ }; use dashmap::{DashMap, SharedValue}; -use hashbrown::{hash_map::RawEntryMut, HashMap}; +use hashbrown::{HashMap, hash_map::RawEntryMut}; use rustc_hash::FxHasher; use triomphe::Arc; @@ -160,7 +160,7 @@ impl Symbol { SharedValue::new(()), ) .0 - .0, + .0, ), }, } @@ -236,7 +236,7 @@ impl Symbol { RawEntryMut::Vacant(_) => unreachable!(), } .0 - .0; + .0; // SAFETY: We're dropping, we have ownership. ManuallyDrop::into_inner(unsafe { ptr.try_as_arc_owned().unwrap() }); debug_assert_eq!(Arc::count(arc), 1); diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index 6b77c72cee897..cc9b3ef457366 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -7,8 +7,8 @@ use dashmap::{DashMap, SharedValue}; use rustc_hash::FxHasher; use crate::{ - symbol::{SymbolProxy, TaggedArcPtr}, Symbol, + symbol::{SymbolProxy, TaggedArcPtr}, }; macro_rules! define_symbols { diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 01d29d88df4a2..243619bb09fd2 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -4,23 +4,24 @@ // to run rust-analyzer as a library. use std::{collections::hash_map::Entry, mem, path::Path, sync}; -use crossbeam_channel::{unbounded, Receiver}; +use crossbeam_channel::{Receiver, unbounded}; use hir_expand::proc_macro::{ ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacroLoadResult, ProcMacrosBuilder, }; use ide_db::{ + ChangeWithProcMacros, FxHashMap, RootDatabase, base_db::{CrateGraphBuilder, Env, SourceRoot, SourceRootId}, - prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase, + prime_caches, }; use itertools::Itertools; use proc_macro_api::{MacroDylib, ProcMacroClient}; use project_model::{CargoConfig, PackageRoot, ProjectManifest, ProjectWorkspace}; use span::Span; use vfs::{ + AbsPath, AbsPathBuf, VfsPath, file_set::FileSetConfig, loader::{Handle, LoadingProgress}, - AbsPath, AbsPathBuf, VfsPath, }; #[derive(Debug)] @@ -626,7 +627,7 @@ mod tests { let fsc = builder.build(); let src = SourceRootConfig { fsc, local_filesets: vec![0, 1, 2, 3] }; let mut vc = src.source_root_parent_map().into_iter().collect::>(); - vc.sort_by(|x, y| x.0 .0.cmp(&y.0 .0)); + vc.sort_by(|x, y| x.0.0.cmp(&y.0.0)); assert_eq!(vc, vec![(SourceRootId(2), SourceRootId(1)), (SourceRootId(3), SourceRootId(1))]) } @@ -641,7 +642,7 @@ mod tests { let fsc = builder.build(); let src = SourceRootConfig { fsc, local_filesets: vec![0, 1, 3] }; let mut vc = src.source_root_parent_map().into_iter().collect::>(); - vc.sort_by(|x, y| x.0 .0.cmp(&y.0 .0)); + vc.sort_by(|x, y| x.0.0.cmp(&y.0.0)); assert_eq!(vc, vec![(SourceRootId(3), SourceRootId(1)),]) } @@ -656,7 +657,7 @@ mod tests { let fsc = builder.build(); let src = SourceRootConfig { fsc, local_filesets: vec![0, 1, 3] }; let mut vc = src.source_root_parent_map().into_iter().collect::>(); - vc.sort_by(|x, y| x.0 .0.cmp(&y.0 .0)); + vc.sort_by(|x, y| x.0.0.cmp(&y.0.0)); assert_eq!(vc, vec![(SourceRootId(3), SourceRootId(1)),]) } @@ -672,7 +673,7 @@ mod tests { let fsc = builder.build(); let src = SourceRootConfig { fsc, local_filesets: vec![0, 1] }; let mut vc = src.source_root_parent_map().into_iter().collect::>(); - vc.sort_by(|x, y| x.0 .0.cmp(&y.0 .0)); + vc.sort_by(|x, y| x.0.0.cmp(&y.0.0)); assert_eq!(vc, vec![(SourceRootId(1), SourceRootId(0)),]) } @@ -688,7 +689,7 @@ mod tests { let fsc = builder.build(); let src = SourceRootConfig { fsc, local_filesets: vec![0, 1] }; let mut vc = src.source_root_parent_map().into_iter().collect::>(); - vc.sort_by(|x, y| x.0 .0.cmp(&y.0 .0)); + vc.sort_by(|x, y| x.0.0.cmp(&y.0.0)); assert_eq!(vc, vec![(SourceRootId(1), SourceRootId(0)),]) } diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs index 89c300300379c..db75dceae1cb9 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs @@ -5,18 +5,19 @@ use rustc_hash::FxHashMap; use span::{Edition, Span}; use stdx::itertools::Itertools; use syntax::{ - ast::{self, HasName}, AstNode, + ast::{self, HasName}, }; use syntax_bridge::{ - dummy_test_span_utils::{DummyTestSpanMap, DUMMY}, - syntax_node_to_token_tree, DocCommentDesugarMode, + DocCommentDesugarMode, + dummy_test_span_utils::{DUMMY, DummyTestSpanMap}, + syntax_node_to_token_tree, }; use test_utils::{bench, bench_fixture, skip_slow_tests}; use crate::{ - parser::{MetaVarKind, Op, RepeatKind, Separator}, DeclarativeMacro, + parser::{MetaVarKind, Op, RepeatKind, Separator}, }; #[test] @@ -53,7 +54,7 @@ fn benchmark_expand_macro_rules() { .map(|(id, tt)| { let res = rules[&id].expand(&tt, |_| (), DUMMY, Edition::CURRENT); assert!(res.err.is_none()); - res.value.0 .0.len() + res.value.0.0.len() }) .sum() }; diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander.rs b/src/tools/rust-analyzer/crates/mbe/src/expander.rs index 5539a88c707d1..f910f9f9d753f 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander.rs @@ -9,7 +9,7 @@ use intern::Symbol; use rustc_hash::FxHashMap; use span::{Edition, Span}; -use crate::{parser::MetaVarKind, ExpandError, ExpandErrorKind, ExpandResult, MatchedArmIndex}; +use crate::{ExpandError, ExpandErrorKind, ExpandResult, MatchedArmIndex, parser::MetaVarKind}; pub(crate) fn expand_rules( rules: &[crate::Rule], diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs index b7f25aa380961..940aaacb02ed5 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs @@ -61,19 +61,19 @@ use std::{rc::Rc, sync::Arc}; -use intern::{sym, Symbol}; -use smallvec::{smallvec, SmallVec}; +use intern::{Symbol, sym}; +use smallvec::{SmallVec, smallvec}; use span::{Edition, Span}; use tt::{ - iter::{TtElement, TtIter}, DelimSpan, + iter::{TtElement, TtIter}, }; use crate::{ + ExpandError, ExpandErrorKind, MetaTemplate, ValueResult, expander::{Binding, Bindings, ExpandResult, Fragment}, expect_fragment, parser::{ExprKind, MetaVarKind, Op, RepeatKind, Separator}, - ExpandError, ExpandErrorKind, MetaTemplate, ValueResult, }; impl<'a> Bindings<'a> { diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs index 7710ea7938951..b1f542eac7cef 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs @@ -1,14 +1,14 @@ //! Transcriber takes a template, like `fn $ident() {}`, a set of bindings like //! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}` -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use span::{Edition, Span}; -use tt::{iter::TtElement, Delimiter, TopSubtreeBuilder}; +use tt::{Delimiter, TopSubtreeBuilder, iter::TtElement}; use crate::{ + ExpandError, ExpandErrorKind, ExpandResult, MetaTemplate, expander::{Binding, Bindings, Fragment}, parser::{ConcatMetaVarExprElem, MetaVarKind, Op, RepeatKind, Separator}, - ExpandError, ExpandErrorKind, ExpandResult, MetaTemplate, }; impl<'t> Bindings<'t> { @@ -331,7 +331,10 @@ fn expand_subtree( } _ => { if err.is_none() { - err = Some(ExpandError::binding_error(var.span, "metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`")) + err = Some(ExpandError::binding_error( + var.span, + "metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`", + )) } continue; } diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs index 6bc019bf333e9..9f9fa36abd46a 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs @@ -23,8 +23,8 @@ mod tests; use span::{Edition, Span, SyntaxContext}; use syntax_bridge::to_parser_input; -use tt::iter::TtIter; use tt::DelimSpan; +use tt::iter::TtIter; use std::fmt; use std::sync::Arc; diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs index 9d91387a07417..7be49cbc7e112 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use arrayvec::ArrayVec; -use intern::{sym, Symbol}; +use intern::{Symbol, sym}; use span::{Edition, Span, SyntaxContext}; use tt::iter::{TtElement, TtIter}; @@ -194,7 +194,7 @@ fn next_op( let mut res = ArrayVec::new(); res.push(*p); Box::new(res) - })) + })); } Some(it) => it, }; @@ -212,13 +212,13 @@ fn next_op( Mode::Pattern => { return Err(ParseError::unexpected( "`${}` metavariable expressions are not allowed in matchers", - )) + )); } }, _ => { return Err(ParseError::expected( "expected `$()` repetition or `${}` expression", - )) + )); } }, TtElement::Leaf(leaf) => match leaf { @@ -246,7 +246,7 @@ fn next_op( Mode::Pattern => { return Err(ParseError::unexpected( "`$$` is not allowed on the pattern side", - )) + )); } Mode::Template => Op::Punct({ let mut res = ArrayVec::new(); @@ -255,7 +255,7 @@ fn next_op( }), }, tt::Leaf::Punct(_) | tt::Leaf::Literal(_) => { - return Err(ParseError::expected("expected ident")) + return Err(ParseError::expected("expected ident")); } }, } @@ -348,7 +348,7 @@ fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option, Repeat }; match tt { tt::Leaf::Ident(_) | tt::Leaf::Literal(_) if has_sep => { - return Err(ParseError::InvalidRepeat) + return Err(ParseError::InvalidRepeat); } tt::Leaf::Ident(ident) => separator = Separator::Ident(ident.clone()), tt::Leaf::Literal(lit) => separator = Separator::Literal(lit.clone()), diff --git a/src/tools/rust-analyzer/crates/parser/src/event.rs b/src/tools/rust-analyzer/crates/parser/src/event.rs index b197b086f377a..5be9cb2a24699 100644 --- a/src/tools/rust-analyzer/crates/parser/src/event.rs +++ b/src/tools/rust-analyzer/crates/parser/src/event.rs @@ -5,8 +5,8 @@ use std::mem; use crate::{ - output::Output, SyntaxKind::{self, *}, + output::Output, }; /// `Parser` produces a flat list of `Event`s. diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs index fe6b904bd889a..8ddf50db043a6 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs @@ -39,9 +39,9 @@ mod patterns; mod types; use crate::{ - parser::{CompletedMarker, Marker, Parser}, SyntaxKind::{self, *}, - TokenSet, T, + T, TokenSet, + parser::{CompletedMarker, Marker, Parser}, }; pub(crate) mod entry { diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs index fe1316c9bfde3..5b0085fc2a0b9 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs @@ -4,8 +4,8 @@ use crate::grammar::attributes::ATTRIBUTE_FIRST; use super::*; +pub(super) use atom::{LITERAL_FIRST, literal}; pub(crate) use atom::{block_expr, match_arm_list}; -pub(super) use atom::{literal, LITERAL_FIRST}; #[derive(PartialEq, Eq)] pub(super) enum Semicolon { diff --git a/src/tools/rust-analyzer/crates/parser/src/parser.rs b/src/tools/rust-analyzer/crates/parser/src/parser.rs index b058686276444..36a363afe93a7 100644 --- a/src/tools/rust-analyzer/crates/parser/src/parser.rs +++ b/src/tools/rust-analyzer/crates/parser/src/parser.rs @@ -5,11 +5,11 @@ use std::cell::Cell; use drop_bomb::DropBomb; use crate::{ - event::Event, - input::Input, Edition, SyntaxKind::{self, EOF, ERROR, TOMBSTONE}, - TokenSet, T, + T, TokenSet, + event::Event, + input::Input, }; /// `Parser` struct provides the low-level API for diff --git a/src/tools/rust-analyzer/crates/paths/src/lib.rs b/src/tools/rust-analyzer/crates/paths/src/lib.rs index 3d722b1ff1155..2c6a82bf0c3fc 100644 --- a/src/tools/rust-analyzer/crates/paths/src/lib.rs +++ b/src/tools/rust-analyzer/crates/paths/src/lib.rs @@ -248,7 +248,9 @@ impl AbsPath { } pub fn canonicalize(&self) -> ! { - panic!("We explicitly do not provide canonicalization API, as that is almost always a wrong solution, see #14430") + panic!( + "We explicitly do not provide canonicalization API, as that is almost always a wrong solution, see #14430" + ) } /// Equivalent of [`Utf8Path::strip_prefix`] for `AbsPath`. diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs index 4178b04767a99..3d84dc8b24da9 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -10,7 +10,7 @@ use serde_derive::{Deserialize, Serialize}; use crate::ProcMacroKind; pub use self::flat::{ - deserialize_span_data_index_map, serialize_span_data_index_map, FlatTree, SpanDataIndexMap, + FlatTree, SpanDataIndexMap, deserialize_span_data_index_map, serialize_span_data_index_map, }; pub use span::TokenId; @@ -158,7 +158,7 @@ type ProtocolWrite = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str) #[cfg(test)] mod tests { - use intern::{sym, Symbol}; + use intern::{Symbol, sym}; use span::{Edition, ErasedFileAstId, Span, SpanAnchor, SyntaxContext, TextRange, TextSize}; use tt::{ Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, TopSubtree, diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs index 571ceaabe62cd..11acbd4e64c24 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs @@ -17,9 +17,9 @@ use std::{fmt, io, sync::Arc, time::SystemTime}; use crate::{ legacy_protocol::msg::{ - deserialize_span_data_index_map, flat::serialize_span_data_index_map, ExpandMacro, - ExpandMacroData, ExpnGlobals, FlatTree, PanicMessage, Request, Response, SpanDataIndexMap, - HAS_GLOBAL_SPANS, RUST_ANALYZER_SPAN_SUPPORT, + ExpandMacro, ExpandMacroData, ExpnGlobals, FlatTree, HAS_GLOBAL_SPANS, PanicMessage, + RUST_ANALYZER_SPAN_SUPPORT, Request, Response, SpanDataIndexMap, + deserialize_span_data_index_map, flat::serialize_span_data_index_map, }, process::ProcMacroServerProcess, }; @@ -102,7 +102,7 @@ impl ProcMacroClient { pub fn spawn( process_path: &AbsPath, env: impl IntoIterator, impl AsRef)> - + Clone, + + Clone, ) -> io::Result { let process = ProcMacroServerProcess::run(process_path, env)?; Ok(ProcMacroClient { process: Arc::new(process), path: process_path.to_owned() }) diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs index d998b23d3bbef..dd1f5a2420c9f 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs @@ -11,14 +11,14 @@ use paths::AbsPath; use stdx::JodChild; use crate::{ + ProcMacroKind, ServerError, legacy_protocol::{ json::{read_json, write_json}, msg::{ - Message, Request, Response, ServerConfig, SpanMode, CURRENT_API_VERSION, - RUST_ANALYZER_SPAN_SUPPORT, + CURRENT_API_VERSION, Message, RUST_ANALYZER_SPAN_SUPPORT, Request, Response, + ServerConfig, SpanMode, }, }, - ProcMacroKind, ServerError, }; #[derive(Debug)] @@ -43,7 +43,7 @@ impl ProcMacroServerProcess { pub(crate) fn run( process_path: &AbsPath, env: impl IntoIterator, impl AsRef)> - + Clone, + + Clone, ) -> io::Result { let create_srv = || { let mut process = Process::run(process_path, env.clone())?; diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs index de59e88aac40c..0e6b18ecaef19 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs @@ -14,7 +14,9 @@ use main_loop::run; fn main() -> std::io::Result<()> { let v = std::env::var("RUST_ANALYZER_INTERNALS_DO_NOT_USE"); if v.is_err() { - eprintln!("This is an IDE implementation detail, you can use this tool by exporting RUST_ANALYZER_INTERNALS_DO_NOT_USE."); + eprintln!( + "This is an IDE implementation detail, you can use this tool by exporting RUST_ANALYZER_INTERNALS_DO_NOT_USE." + ); eprintln!( "Note that this tool's API is highly unstable and may break without prior notice" ); diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs index 569070766f1c6..f54dff1f2d822 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs @@ -4,8 +4,8 @@ use std::io; use proc_macro_api::legacy_protocol::{ json::{read_json, write_json}, msg::{ - self, deserialize_span_data_index_map, serialize_span_data_index_map, ExpandMacroData, - ExpnGlobals, Message, SpanMode, TokenId, CURRENT_API_VERSION, + self, CURRENT_API_VERSION, ExpandMacroData, ExpnGlobals, Message, SpanMode, TokenId, + deserialize_span_data_index_map, serialize_span_data_index_map, }, }; use proc_macro_srv::EnvSnapshot; diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs index cbf7a277bfae6..245b064387e59 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs @@ -9,7 +9,7 @@ use libloading::Library; use object::Object; use paths::{Utf8Path, Utf8PathBuf}; -use crate::{proc_macros::ProcMacros, server_impl::TopSubtree, ProcMacroKind, ProcMacroSrvSpan}; +use crate::{ProcMacroKind, ProcMacroSrvSpan, proc_macros::ProcMacros, server_impl::TopSubtree}; /// Loads dynamic library in platform dependent manner. /// diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index f28821b4afc5c..4f817b6bc0a58 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -30,7 +30,7 @@ mod proc_macros; mod server_impl; use std::{ - collections::{hash_map::Entry, HashMap}, + collections::{HashMap, hash_map::Entry}, env, ffi::OsString, fs, diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs index 58f5e80dc4ea6..a5fa7f6e71a6d 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs @@ -5,7 +5,7 @@ use proc_macro::bridge; use libloading::Library; use crate::{ - dylib::LoadProcMacroDylibError, server_impl::TopSubtree, ProcMacroKind, ProcMacroSrvSpan, + ProcMacroKind, ProcMacroSrvSpan, dylib::LoadProcMacroDylibError, server_impl::TopSubtree, }; #[repr(transparent)] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index f7cb0ab4655fa..62540183cb5e9 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -11,10 +11,10 @@ use std::{ use intern::Symbol; use proc_macro::bridge::{self, server}; -use span::{FileId, Span, FIXUP_ERASED_FILE_AST_ID_MARKER}; +use span::{FIXUP_ERASED_FILE_AST_ID_MARKER, FileId, Span}; use tt::{TextRange, TextSize}; -use crate::server_impl::{literal_kind_to_internal, token_stream::TokenStreamBuilder, TopSubtree}; +use crate::server_impl::{TopSubtree, literal_kind_to_internal, token_stream::TokenStreamBuilder}; mod tt { pub use tt::*; diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs index 409cf3cc78134..d0c7f23a38a04 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs @@ -5,7 +5,7 @@ use std::ops::{Bound, Range}; use intern::Symbol; use proc_macro::bridge::{self, server}; -use crate::server_impl::{literal_kind_to_internal, token_stream::TokenStreamBuilder, TopSubtree}; +use crate::server_impl::{TopSubtree, literal_kind_to_internal, token_stream::TokenStreamBuilder}; mod tt { pub use span::TokenId; diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs index 645f7e7c59a32..a3cf76d37bacf 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs @@ -2,7 +2,7 @@ use proc_macro::bridge; -use crate::server_impl::{delim_to_external, literal_kind_to_external, TopSubtree}; +use crate::server_impl::{TopSubtree, delim_to_external, literal_kind_to_external}; #[derive(Clone)] pub struct TokenStream { diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs index 584a27468f847..a476a70a74095 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs @@ -4,7 +4,7 @@ use expect_test::Expect; use span::{EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContext, TokenId}; use tt::TextRange; -use crate::{dylib, proc_macro_test_dylib_path, EnvSnapshot, ProcMacroSrv}; +use crate::{EnvSnapshot, ProcMacroSrv, dylib, proc_macro_test_dylib_path}; fn parse_string(call_site: TokenId, src: &str) -> crate::server_impl::TokenStream { crate::server_impl::TokenStream::with_subtree(crate::server_impl::TopSubtree( diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs index b0939229f93e2..aa0099d0e57e3 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs @@ -9,7 +9,7 @@ use std::{cell::RefCell, io, mem, process::Command}; use base_db::Env; -use cargo_metadata::{camino::Utf8Path, Message}; +use cargo_metadata::{Message, camino::Utf8Path}; use cfg::CfgAtom; use itertools::Itertools; use la_arena::ArenaMap; @@ -19,8 +19,8 @@ use serde::Deserialize as _; use toolchain::Tool; use crate::{ - utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationStrategy, ManifestPath, - Package, Sysroot, TargetKind, + CargoConfig, CargoFeatures, CargoWorkspace, InvocationStrategy, ManifestPath, Package, Sysroot, + TargetKind, utf8_stdout, }; /// Output of the build script and proc-macro building steps for a workspace. diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 014028a0b63e2..054312835a8cf 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -596,7 +596,7 @@ impl CargoWorkspace { // this pkg is inside this cargo workspace, fallback to workspace root if found { return Some(vec![ - ManifestPath::try_from(self.workspace_root().join("Cargo.toml")).ok()? + ManifestPath::try_from(self.workspace_root().join("Cargo.toml")).ok()?, ]); } diff --git a/src/tools/rust-analyzer/crates/project-model/src/env.rs b/src/tools/rust-analyzer/crates/project-model/src/env.rs index 37fffba295590..08d51c0d0888d 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/env.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/env.rs @@ -4,7 +4,7 @@ use paths::Utf8Path; use rustc_hash::FxHashMap; use toolchain::Tool; -use crate::{utf8_stdout, ManifestPath, PackageData, Sysroot, TargetKind}; +use crate::{ManifestPath, PackageData, Sysroot, TargetKind, utf8_stdout}; /// Recreates the compile-time environment variables that Cargo sets. /// diff --git a/src/tools/rust-analyzer/crates/project-model/src/lib.rs b/src/tools/rust-analyzer/crates/project-model/src/lib.rs index 21a993c5a5ed1..436af64cf1326 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs @@ -48,12 +48,12 @@ mod tests; use std::{ fmt, - fs::{self, read_dir, ReadDir}, + fs::{self, ReadDir, read_dir}, io, process::Command, }; -use anyhow::{bail, format_err, Context}; +use anyhow::{Context, bail, format_err}; use paths::{AbsPath, AbsPathBuf, Utf8PathBuf}; use rustc_hash::FxHashSet; @@ -102,7 +102,9 @@ impl ProjectManifest { if path.extension().unwrap_or_default() == "rs" { return Ok(ProjectManifest::CargoScript(path)); } - bail!("project root must point to a Cargo.toml, rust-project.json or {# #} {# #} From 19c7c46d48dc659de44d85845d53ed594b95c286 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Thu, 20 Mar 2025 11:30:45 +0900 Subject: [PATCH 0200/2248] rename `rust-toolchain` to `rust-toolchain.toml` --- book/src/development/basics.md | 2 +- book/src/development/infrastructure/sync.md | 2 +- clippy_dev/src/main.rs | 2 +- clippy_dev/src/setup/toolchain.rs | 2 +- clippy_dev/src/sync.rs | 2 +- rust-toolchain => rust-toolchain.toml | 0 6 files changed, 5 insertions(+), 5 deletions(-) rename rust-toolchain => rust-toolchain.toml (100%) diff --git a/book/src/development/basics.md b/book/src/development/basics.md index 931e5c3a2942a..4219724ed5df9 100644 --- a/book/src/development/basics.md +++ b/book/src/development/basics.md @@ -147,7 +147,7 @@ following: First, take note of the toolchain [override](https://rust-lang.github.io/rustup/overrides.html) in -`/rust-toolchain`. We will use this override to install Clippy into the right +`/rust-toolchain.toml`. We will use this override to install Clippy into the right toolchain. > Tip: You can view the active toolchain for the current directory with `rustup diff --git a/book/src/development/infrastructure/sync.md b/book/src/development/infrastructure/sync.md index da1ad586607f9..2bbdf47a83581 100644 --- a/book/src/development/infrastructure/sync.md +++ b/book/src/development/infrastructure/sync.md @@ -86,7 +86,7 @@ to be run inside the `rust` directory): 4. Bump the nightly version in the Clippy repository by running these commands: ```bash cargo dev sync update_nightly - git commit -m "Bump nightly version -> YYYY-MM-DD" rust-toolchain clippy_utils/README.md + git commit -m "Bump nightly version -> YYYY-MM-DD" rust-toolchain.toml clippy_utils/README.md ``` 5. Open a PR to `rust-lang/rust-clippy` and wait for it to get merged (to accelerate the process ping the `@rust-lang/clippy` team in your PR and/or diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 074dea4ab77b6..0380b7e6a6dc9 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -334,7 +334,7 @@ struct SyncCommand { #[derive(Subcommand)] enum SyncSubcommand { #[command(name = "update_nightly")] - /// Update nightly version in rust-toolchain and `clippy_utils` + /// Update nightly version in `rust-toolchain.toml` and `clippy_utils` UpdateNightly, } diff --git a/clippy_dev/src/setup/toolchain.rs b/clippy_dev/src/setup/toolchain.rs index 2966629cf70a3..ecd80215f7e8f 100644 --- a/clippy_dev/src/setup/toolchain.rs +++ b/clippy_dev/src/setup/toolchain.rs @@ -62,7 +62,7 @@ pub fn create(standalone: bool, force: bool, release: bool, name: &str) { println!("Created toolchain {name}, use it in other projects with e.g. `cargo +{name} clippy`"); if !standalone { - println!("Note: This will need to be re-run whenever the Clippy `rust-toolchain` changes"); + println!("Note: This will need to be re-run whenever the Clippy `rust-toolchain.toml` changes"); } } diff --git a/clippy_dev/src/sync.rs b/clippy_dev/src/sync.rs index 3522d182e90ac..a6b65e561c223 100644 --- a/clippy_dev/src/sync.rs +++ b/clippy_dev/src/sync.rs @@ -10,7 +10,7 @@ pub fn update_nightly() { let date = Utc::now().format("%Y-%m-%d").to_string(); replace_region_in_file( UpdateMode::Change, - Path::new("rust-toolchain"), + Path::new("rust-toolchain.toml"), "# begin autogenerated nightly\n", "# end autogenerated nightly", |res| { diff --git a/rust-toolchain b/rust-toolchain.toml similarity index 100% rename from rust-toolchain rename to rust-toolchain.toml From aadda467525d6bb6ade388312cb71f20f8c0e2f4 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Thu, 2 Jan 2025 18:03:54 -0500 Subject: [PATCH 0201/2248] Add `ignore_without_reason` lint --- CHANGELOG.md | 1 + clippy_lints/src/attrs/mod.rs | 45 ++++++++++++++++++++++++++- clippy_lints/src/declared_lints.rs | 1 + tests/ui/ignore_without_reason.rs | 14 +++++++++ tests/ui/ignore_without_reason.stderr | 12 +++++++ 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 tests/ui/ignore_without_reason.rs create mode 100644 tests/ui/ignore_without_reason.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bf4b51ff0fe2..0d00638f2ee7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5681,6 +5681,7 @@ Released 2018-09-13 [`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else [`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond +[`ignore_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#ignore_without_reason [`ignored_unit_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns [`impl_hash_borrow_with_str_and_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_hash_borrow_with_str_and_bytes [`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index e04d2ad5d13b7..7ba7b47661766 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -14,8 +14,9 @@ mod useless_attribute; mod utils; use clippy_config::Conf; +use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::msrvs::{self, Msrv, MsrvStack}; -use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind}; +use rustc_ast::{self as ast, AttrArgs, AttrKind, Attribute, MetaItemInner, MetaItemKind}; use rustc_hir::{ImplItem, Item, ItemKind, TraitItem}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::impl_lint_pass; @@ -448,6 +449,31 @@ declare_clippy_lint! { "duplicated attribute" } +declare_clippy_lint! { + /// ### What it does + /// Checks for ignored tests without messages. + /// + /// ### Why is this bad? + /// The reason for ignoring the test may not be obvious. + /// + /// ### Example + /// ```no_run + /// #[test] + /// #[ignore] + /// fn test() {} + /// ``` + /// Use instead: + /// ```no_run + /// #[test] + /// #[ignore = "Some good reason"] + /// fn test() {} + /// ``` + #[clippy::version = "1.85.0"] + pub IGNORE_WITHOUT_REASON, + restriction, + "ignored tests without messages" +} + pub struct Attributes { msrv: Msrv, } @@ -532,6 +558,7 @@ impl_lint_pass!(PostExpansionEarlyAttributes => [ ALLOW_ATTRIBUTES, ALLOW_ATTRIBUTES_WITHOUT_REASON, DEPRECATED_SEMVER, + IGNORE_WITHOUT_REASON, USELESS_ATTRIBUTE, BLANKET_CLIPPY_RESTRICTION_LINTS, SHOULD_PANIC_WITHOUT_EXPECT, @@ -575,6 +602,22 @@ impl EarlyLintPass for PostExpansionEarlyAttributes { if attr.has_name(sym::should_panic) { should_panic_without_expect::check(cx, attr); } + + if attr.has_name(sym::ignore) + && match &attr.kind { + AttrKind::Normal(normal_attr) => !matches!(normal_attr.item.args, AttrArgs::Eq { .. }), + AttrKind::DocComment(..) => true, + } + { + span_lint_and_help( + cx, + IGNORE_WITHOUT_REASON, + attr.span, + "`#[ignore]` without reason", + None, + "add a reason with `= \"..\"`", + ); + } } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &'_ ast::Item) { diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 7fa23dad69817..a9b6b369c4c39 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -52,6 +52,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::attrs::DEPRECATED_CLIPPY_CFG_ATTR_INFO, crate::attrs::DEPRECATED_SEMVER_INFO, crate::attrs::DUPLICATED_ATTRIBUTES_INFO, + crate::attrs::IGNORE_WITHOUT_REASON_INFO, crate::attrs::INLINE_ALWAYS_INFO, crate::attrs::MIXED_ATTRIBUTES_STYLE_INFO, crate::attrs::NON_MINIMAL_CFG_INFO, diff --git a/tests/ui/ignore_without_reason.rs b/tests/ui/ignore_without_reason.rs new file mode 100644 index 0000000000000..eb8aaf179bedd --- /dev/null +++ b/tests/ui/ignore_without_reason.rs @@ -0,0 +1,14 @@ +#![warn(clippy::ignore_without_reason)] + +fn main() {} + +#[test] +fn unignored_test() {} + +#[test] +#[ignore = "Some good reason"] +fn ignored_with_reason() {} + +#[test] +#[ignore] +fn ignored_without_reason() {} diff --git a/tests/ui/ignore_without_reason.stderr b/tests/ui/ignore_without_reason.stderr new file mode 100644 index 0000000000000..4c0210c2bbc08 --- /dev/null +++ b/tests/ui/ignore_without_reason.stderr @@ -0,0 +1,12 @@ +error: `#[ignore]` without reason + --> tests/ui/ignore_without_reason.rs:13:1 + | +LL | #[ignore] + | ^^^^^^^^^ + | + = help: add a reason with `= ".."` + = note: `-D clippy::ignore-without-reason` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::ignore_without_reason)]` + +error: aborting due to 1 previous error + From 475d10d3b05be14263dae9f624887d6eb2f2fa2d Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Mon, 3 Mar 2025 12:54:34 -0500 Subject: [PATCH 0202/2248] Add test annotation --- tests/ui/ignore_without_reason.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/ignore_without_reason.rs b/tests/ui/ignore_without_reason.rs index eb8aaf179bedd..53ac34c27248e 100644 --- a/tests/ui/ignore_without_reason.rs +++ b/tests/ui/ignore_without_reason.rs @@ -10,5 +10,5 @@ fn unignored_test() {} fn ignored_with_reason() {} #[test] -#[ignore] +#[ignore] //~ ignore_without_reason fn ignored_without_reason() {} From 721ac284de4b31ba2e4dd05e6afae08596bbc541 Mon Sep 17 00:00:00 2001 From: yanglsh Date: Fri, 7 Mar 2025 15:05:11 +0800 Subject: [PATCH 0203/2248] fix: `filter_map_bool_then` suggest wrongly when contain return --- .../src/methods/filter_map_bool_then.rs | 27 ++++++---- tests/ui/filter_map_bool_then_unfixable.rs | 52 +++++++++++++++++++ .../ui/filter_map_bool_then_unfixable.stderr | 50 ++++++++++++++++++ 3 files changed, 120 insertions(+), 9 deletions(-) create mode 100644 tests/ui/filter_map_bool_then_unfixable.rs create mode 100644 tests/ui/filter_map_bool_then_unfixable.stderr diff --git a/clippy_lints/src/methods/filter_map_bool_then.rs b/clippy_lints/src/methods/filter_map_bool_then.rs index f7e116c5310ed..3461f539b0986 100644 --- a/clippy_lints/src/methods/filter_map_bool_then.rs +++ b/clippy_lints/src/methods/filter_map_bool_then.rs @@ -1,8 +1,8 @@ use super::FILTER_MAP_BOOL_THEN; -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_copy; -use clippy_utils::{is_from_proc_macro, is_trait_method, peel_blocks}; +use clippy_utils::{contains_return, is_from_proc_macro, is_trait_method, peel_blocks}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LintContext}; @@ -44,17 +44,26 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: & && let Some(filter) = recv.span.get_source_text(cx) && let Some(map) = then_body.span.get_source_text(cx) { - span_lint_and_sugg( + span_lint_and_then( cx, FILTER_MAP_BOOL_THEN, call_span, "usage of `bool::then` in `filter_map`", - "use `filter` then `map` instead", - format!( - "filter(|&{param_snippet}| {derefs}{filter}).map(|{param_snippet}| {map})", - derefs = "*".repeat(needed_derefs) - ), - Applicability::MachineApplicable, + |diag| { + if contains_return(recv) { + diag.help("consider using `filter` then `map` instead"); + } else { + diag.span_suggestion( + call_span, + "use `filter` then `map` instead", + format!( + "filter(|&{param_snippet}| {derefs}{filter}).map(|{param_snippet}| {map})", + derefs = "*".repeat(needed_derefs) + ), + Applicability::MachineApplicable, + ); + } + }, ); } } diff --git a/tests/ui/filter_map_bool_then_unfixable.rs b/tests/ui/filter_map_bool_then_unfixable.rs new file mode 100644 index 0000000000000..f65b0b66f836e --- /dev/null +++ b/tests/ui/filter_map_bool_then_unfixable.rs @@ -0,0 +1,52 @@ +#![allow(clippy::question_mark, unused)] +#![warn(clippy::filter_map_bool_then)] +//@no-rustfix + +mod issue14368 { + + fn do_something(_: ()) -> bool { + true + } + + fn option_with_early_return(x: &[Option]) { + let _ = x.iter().filter_map(|&x| x?.then(|| do_something(()))); + //~^ filter_map_bool_then + let _ = x + .iter() + .filter_map(|&x| if let Some(x) = x { x } else { return None }.then(|| do_something(()))); + //~^ filter_map_bool_then + let _ = x.iter().filter_map(|&x| { + //~^ filter_map_bool_then + match x { + Some(x) => x, + None => return None, + } + .then(|| do_something(())) + }); + } + + #[derive(Copy, Clone)] + enum Foo { + One(bool), + Two, + Three(Option), + } + + fn nested_type_with_early_return(x: &[Foo]) { + let _ = x.iter().filter_map(|&x| { + //~^ filter_map_bool_then + match x { + Foo::One(x) => x, + Foo::Two => return None, + Foo::Three(inner) => { + if inner? == 0 { + return Some(false); + } else { + true + } + }, + } + .then(|| do_something(())) + }); + } +} diff --git a/tests/ui/filter_map_bool_then_unfixable.stderr b/tests/ui/filter_map_bool_then_unfixable.stderr new file mode 100644 index 0000000000000..f72bcac8a7501 --- /dev/null +++ b/tests/ui/filter_map_bool_then_unfixable.stderr @@ -0,0 +1,50 @@ +error: usage of `bool::then` in `filter_map` + --> tests/ui/filter_map_bool_then_unfixable.rs:12:26 + | +LL | let _ = x.iter().filter_map(|&x| x?.then(|| do_something(()))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using `filter` then `map` instead + = note: `-D clippy::filter-map-bool-then` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::filter_map_bool_then)]` + +error: usage of `bool::then` in `filter_map` + --> tests/ui/filter_map_bool_then_unfixable.rs:16:14 + | +LL | .filter_map(|&x| if let Some(x) = x { x } else { return None }.then(|| do_something(()))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using `filter` then `map` instead + +error: usage of `bool::then` in `filter_map` + --> tests/ui/filter_map_bool_then_unfixable.rs:18:26 + | +LL | let _ = x.iter().filter_map(|&x| { + | __________________________^ +LL | | +LL | | match x { +LL | | Some(x) => x, +... | +LL | | .then(|| do_something(())) +LL | | }); + | |__________^ + | + = help: consider using `filter` then `map` instead + +error: usage of `bool::then` in `filter_map` + --> tests/ui/filter_map_bool_then_unfixable.rs:36:26 + | +LL | let _ = x.iter().filter_map(|&x| { + | __________________________^ +LL | | +LL | | match x { +LL | | Foo::One(x) => x, +... | +LL | | .then(|| do_something(())) +LL | | }); + | |__________^ + | + = help: consider using `filter` then `map` instead + +error: aborting due to 4 previous errors + From 3f9ecbe341a7d1975d688946e58929402399189c Mon Sep 17 00:00:00 2001 From: yanglsh Date: Tue, 11 Mar 2025 19:44:30 +0800 Subject: [PATCH 0204/2248] fix: `filter_map_bool_then`: suggests wrongly when mut capture in then --- .../src/methods/filter_map_bool_then.rs | 57 +++++++++++++++++-- tests/ui/filter_map_bool_then_unfixable.rs | 11 ++++ .../ui/filter_map_bool_then_unfixable.stderr | 29 +++++++--- 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/methods/filter_map_bool_then.rs b/clippy_lints/src/methods/filter_map_bool_then.rs index 3461f539b0986..965993808f6b5 100644 --- a/clippy_lints/src/methods/filter_map_bool_then.rs +++ b/clippy_lints/src/methods/filter_map_bool_then.rs @@ -2,9 +2,13 @@ use super::FILTER_MAP_BOOL_THEN; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_copy; -use clippy_utils::{contains_return, is_from_proc_macro, is_trait_method, peel_blocks}; +use clippy_utils::{ + CaptureKind, can_move_expr_to_closure, contains_return, is_from_proc_macro, is_trait_method, peel_blocks, +}; +use rustc_ast::Mutability; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{Expr, ExprKind, HirId, Param, Pat}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::Binder; use rustc_middle::ty::adjustment::Adjust; @@ -50,9 +54,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: & call_span, "usage of `bool::then` in `filter_map`", |diag| { - if contains_return(recv) { - diag.help("consider using `filter` then `map` instead"); - } else { + if can_filter_and_then_move_to_closure(cx, ¶m, recv, then_body) { diag.span_suggestion( call_span, "use `filter` then `map` instead", @@ -62,8 +64,53 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: & ), Applicability::MachineApplicable, ); + } else { + diag.help("consider using `filter` then `map` instead"); } }, ); } } + +/// Returns a set of all bindings found in the given pattern. +fn find_bindings_from_pat(pat: &Pat<'_>) -> FxHashSet { + let mut bindings = FxHashSet::default(); + pat.walk(|p| { + if let rustc_hir::PatKind::Binding(_, hir_id, _, _) = p.kind { + bindings.insert(hir_id); + } + true + }); + bindings +} + +/// Returns true if we can take a closure parameter and have it in both the `filter` function and +/// the`map` function. This is not the case if: +/// +/// - The `filter` would contain an early return, +/// - `filter` and `then` contain captures, and any of those are &mut +fn can_filter_and_then_move_to_closure<'tcx>( + cx: &LateContext<'tcx>, + param: &Param<'tcx>, + filter: &'tcx Expr<'tcx>, + then: &'tcx Expr<'tcx>, +) -> bool { + if contains_return(filter) { + return false; + } + + let Some(filter_captures) = can_move_expr_to_closure(cx, filter) else { + return true; + }; + let Some(then_captures) = can_move_expr_to_closure(cx, then) else { + return true; + }; + + let param_bindings = find_bindings_from_pat(param.pat); + filter_captures.iter().all(|(hir_id, filter_cap)| { + param_bindings.contains(hir_id) + || !then_captures + .get(hir_id) + .is_some_and(|then_cap| matches!(*filter_cap | *then_cap, CaptureKind::Ref(Mutability::Mut))) + }) +} diff --git a/tests/ui/filter_map_bool_then_unfixable.rs b/tests/ui/filter_map_bool_then_unfixable.rs index f65b0b66f836e..68294292502ac 100644 --- a/tests/ui/filter_map_bool_then_unfixable.rs +++ b/tests/ui/filter_map_bool_then_unfixable.rs @@ -2,6 +2,17 @@ #![warn(clippy::filter_map_bool_then)] //@no-rustfix +fn issue11617() { + let mut x: Vec = vec![0; 10]; + let _ = (0..x.len()).zip(x.clone().iter()).filter_map(|(i, v)| { + //~^ filter_map_bool_then + (x[i] != *v).then(|| { + x[i] = i; + i + }) + }); +} + mod issue14368 { fn do_something(_: ()) -> bool { diff --git a/tests/ui/filter_map_bool_then_unfixable.stderr b/tests/ui/filter_map_bool_then_unfixable.stderr index f72bcac8a7501..2025958136ba6 100644 --- a/tests/ui/filter_map_bool_then_unfixable.stderr +++ b/tests/ui/filter_map_bool_then_unfixable.stderr @@ -1,15 +1,30 @@ error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then_unfixable.rs:12:26 + --> tests/ui/filter_map_bool_then_unfixable.rs:7:48 | -LL | let _ = x.iter().filter_map(|&x| x?.then(|| do_something(()))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _ = (0..x.len()).zip(x.clone().iter()).filter_map(|(i, v)| { + | ________________________________________________^ +LL | | +LL | | (x[i] != *v).then(|| { +LL | | x[i] = i; +LL | | i +LL | | }) +LL | | }); + | |______^ | = help: consider using `filter` then `map` instead = note: `-D clippy::filter-map-bool-then` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::filter_map_bool_then)]` error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then_unfixable.rs:16:14 + --> tests/ui/filter_map_bool_then_unfixable.rs:23:26 + | +LL | let _ = x.iter().filter_map(|&x| x?.then(|| do_something(()))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using `filter` then `map` instead + +error: usage of `bool::then` in `filter_map` + --> tests/ui/filter_map_bool_then_unfixable.rs:27:14 | LL | .filter_map(|&x| if let Some(x) = x { x } else { return None }.then(|| do_something(()))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +32,7 @@ LL | .filter_map(|&x| if let Some(x) = x { x } else { return None }. = help: consider using `filter` then `map` instead error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then_unfixable.rs:18:26 + --> tests/ui/filter_map_bool_then_unfixable.rs:29:26 | LL | let _ = x.iter().filter_map(|&x| { | __________________________^ @@ -32,7 +47,7 @@ LL | | }); = help: consider using `filter` then `map` instead error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then_unfixable.rs:36:26 + --> tests/ui/filter_map_bool_then_unfixable.rs:47:26 | LL | let _ = x.iter().filter_map(|&x| { | __________________________^ @@ -46,5 +61,5 @@ LL | | }); | = help: consider using `filter` then `map` instead -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors From d4b8fa9e4c04f3afb7daad03d6719605a8c4bb90 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 14 Mar 2025 12:47:08 +0100 Subject: [PATCH 0205/2248] 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 0206/2248] 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 0207/2248] 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 6c8400e342609de052ec287fecaf67cef04da1d2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 14 Mar 2025 12:47:08 +0100 Subject: [PATCH 0208/2248] remove `feature(inline_const_pat)` --- clippy_lints/src/matches/redundant_guards.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/matches/redundant_guards.rs b/clippy_lints/src/matches/redundant_guards.rs index ab53ad98572e4..9bbef8da0a466 100644 --- a/clippy_lints/src/matches/redundant_guards.rs +++ b/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(..), ..)) From a3b7990b9a3c42a4bf479ea27604927c45fd7172 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 21 Mar 2025 09:35:22 +0100 Subject: [PATCH 0209/2248] 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 0210/2248] 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 0211/2248] 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 93d62b543daa185c2cb2025dbec92225cde49fd4 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 21 Mar 2025 10:13:43 +0100 Subject: [PATCH 0212/2248] minor: Trigger LRU eviction after cache priming finishes --- src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index 7caf18e926dc6..9cc990eec06a2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -10,7 +10,7 @@ use std::{ use always_assert::always; use crossbeam_channel::{Receiver, select}; -use ide_db::base_db::{SourceDatabase, VfsPath}; +use ide_db::base_db::{SourceDatabase, VfsPath, salsa::Database as _}; use lsp_server::{Connection, Notification, Request}; use lsp_types::{TextDocumentIdentifier, notification::Notification as _}; use stdx::thread::ThreadIntent; @@ -364,6 +364,7 @@ impl GlobalState { fraction = 1.0; title = "Indexing"; + self.analysis_host.raw_database_mut().trigger_lru_eviction(); self.prime_caches_queue.op_completed(()); if cancelled { self.prime_caches_queue From eddcda303089d30494ce5268149bd2529d9a35bf Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 21 Mar 2025 11:35:09 +0100 Subject: [PATCH 0213/2248] minor: Don't query the database in workspace switching --- .../crates/rust-analyzer/src/reload.rs | 77 ++++++++++--------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index ce9e5c3f248f3..283b8f37130bf 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -18,7 +18,7 @@ use std::{iter, mem}; use hir::{ChangeWithProcMacros, ProcMacrosBuilder, db::DefDatabase}; use ide_db::{ FxHashMap, - base_db::{CrateGraphBuilder, ProcMacroPaths, RootQueryDb, salsa::Durability}, + base_db::{CrateGraphBuilder, ProcMacroPaths, salsa::Durability}, }; use itertools::Itertools; use load_cargo::{ProjectFolders, load_proc_macro}; @@ -408,11 +408,11 @@ impl GlobalState { }; let mut builder = ProcMacrosBuilder::default(); - let chain = proc_macro_clients + let proc_macro_clients = proc_macro_clients .iter() .map(|res| res.as_ref().map_err(|e| e.to_string())) .chain(iter::repeat_with(|| Err("proc-macro-srv is not running".into()))); - for (client, paths) in chain.zip(paths) { + for (client, paths) in proc_macro_clients.zip(paths) { paths .into_iter() .map(move |(crate_id, res)| { @@ -458,11 +458,12 @@ impl GlobalState { else { return; }; + let switching_from_empty_workspace = self.workspaces.is_empty(); - info!(%cause, ?force_crate_graph_reload); - if self.fetch_workspace_error().is_err() && !self.workspaces.is_empty() { + info!(%cause, ?force_crate_graph_reload, %switching_from_empty_workspace); + if self.fetch_workspace_error().is_err() && !switching_from_empty_workspace { if *force_crate_graph_reload { - self.recreate_crate_graph(cause); + self.recreate_crate_graph(cause, false); } // It only makes sense to switch to a partially broken workspace // if we don't have any workspace at all yet. @@ -479,36 +480,44 @@ impl GlobalState { .all(|(l, r)| l.eq_ignore_build_data(r)); if same_workspaces { - let (workspaces, build_scripts) = match self.fetch_build_data_queue.last_op_result() { - Some(FetchBuildDataResponse { workspaces, build_scripts }) => { - (workspaces.clone(), build_scripts.as_slice()) - } - None => (Default::default(), Default::default()), - }; + if switching_from_empty_workspace { + // Switching from empty to empty is a no-op + return; + } + if let Some(FetchBuildDataResponse { workspaces, build_scripts }) = + self.fetch_build_data_queue.last_op_result() + { + if Arc::ptr_eq(workspaces, &self.workspaces) { + info!("set build scripts to workspaces"); - if Arc::ptr_eq(&workspaces, &self.workspaces) { - info!("set build scripts to workspaces"); + let workspaces = workspaces + .iter() + .cloned() + .zip(build_scripts) + .map(|(mut ws, bs)| { + ws.set_build_scripts(bs.as_ref().ok().cloned().unwrap_or_default()); + ws + }) + .collect::>(); + // Workspaces are the same, but we've updated build data. + info!("same workspace, but new build data"); + self.workspaces = Arc::new(workspaces); + } else { + info!("build scripts do not match the version of the active workspace"); + if *force_crate_graph_reload { + self.recreate_crate_graph(cause, switching_from_empty_workspace); + } - let workspaces = workspaces - .iter() - .cloned() - .zip(build_scripts) - .map(|(mut ws, bs)| { - ws.set_build_scripts(bs.as_ref().ok().cloned().unwrap_or_default()); - ws - }) - .collect::>(); - // Workspaces are the same, but we've updated build data. - info!("same workspace, but new build data"); - self.workspaces = Arc::new(workspaces); + // Current build scripts do not match the version of the active + // workspace, so there's nothing for us to update. + return; + } } else { - info!("build scripts do not match the version of the active workspace"); if *force_crate_graph_reload { - self.recreate_crate_graph(cause); + self.recreate_crate_graph(cause, switching_from_empty_workspace); } - // Current build scripts do not match the version of the active - // workspace, so there's nothing for us to update. + // No build scripts but unchanged workspaces, nothing to do here return; } } else { @@ -528,8 +537,7 @@ impl GlobalState { self.build_deps_changed = false; self.fetch_build_data_queue.request_op("workspace updated".to_owned(), ()); - let initial_build = self.analysis_host.raw_database().all_crates().is_empty(); - if !initial_build { + if !switching_from_empty_workspace { // `switch_workspaces()` will be called again when build scripts already run, which should // take a short time. If we update the workspace now we will invalidate proc macros and cfgs, // and then when build scripts complete we will invalidate them again. @@ -691,12 +699,12 @@ impl GlobalState { self.local_roots_parent_map = Arc::new(self.source_root_config.source_root_parent_map()); info!(?cause, "recreating the crate graph"); - self.recreate_crate_graph(cause); + self.recreate_crate_graph(cause, switching_from_empty_workspace); info!("did switch workspaces"); } - fn recreate_crate_graph(&mut self, cause: String) { + fn recreate_crate_graph(&mut self, cause: String, initial_build: bool) { info!(?cause, "Building Crate Graph"); self.report_progress( "Building CrateGraph", @@ -732,7 +740,6 @@ impl GlobalState { ws_to_crate_graph(&self.workspaces, self.config.extra_env(None), load) }; let mut change = ChangeWithProcMacros::new(); - let initial_build = self.analysis_host.raw_database().all_crates().is_empty(); if initial_build || !self.config.expand_proc_macros() { if self.config.expand_proc_macros() { change.set_proc_macros( From 3f7fc4dff24d0cb2af26f632f51d5702c508fad0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 21 Mar 2025 10:26:36 +0100 Subject: [PATCH 0214/2248] refactor: Reduce codegen burden for `SyntaxKind` --- .../ide/src/syntax_highlighting/highlight.rs | 2 +- .../rust-analyzer/crates/parser/src/lib.rs | 2 + .../parser/src/syntax_kind/generated.rs | 59 +++++++++---------- src/tools/rust-analyzer/xtask/src/codegen.rs | 2 +- .../xtask/src/codegen/grammar.rs | 37 +++++++++++- .../xtask/src/codegen/grammar/ast_src.rs | 12 +++- 6 files changed, 76 insertions(+), 38 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index fb25f0015585e..0d3d99994f602 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -852,7 +852,7 @@ fn highlight_name_ref_by_syntax( } } ASSOC_TYPE_ARG => SymbolKind::TypeAlias.into(), - USE_BOUND_GENERIC_ARG => SymbolKind::TypeParam.into(), + USE_BOUND_GENERIC_ARGS => SymbolKind::TypeParam.into(), _ => default.into(), } } diff --git a/src/tools/rust-analyzer/crates/parser/src/lib.rs b/src/tools/rust-analyzer/crates/parser/src/lib.rs index 398ad7cf66ce6..7963f00bb25ce 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lib.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lib.rs @@ -35,6 +35,8 @@ mod shortcuts; mod syntax_kind; mod token_set; +pub use T_ as T; + #[cfg(test)] mod tests; diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs index 1ff0bbea8b1db..8836bddc9bb75 100644 --- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs +++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs @@ -3,7 +3,7 @@ #![allow(bad_style, missing_docs, unreachable_pub)] use crate::Edition; #[doc = r" The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`."] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Debug)] #[repr(u16)] pub enum SyntaxKind { #[doc(hidden)] @@ -156,7 +156,6 @@ pub enum SyntaxKind { SHEBANG, WHITESPACE, ABI, - ADT, ARG_LIST, ARRAY_EXPR, ARRAY_TYPE, @@ -165,16 +164,13 @@ pub enum SyntaxKind { ASM_DIR_SPEC, ASM_EXPR, ASM_LABEL, - ASM_OPERAND, ASM_OPERAND_EXPR, ASM_OPERAND_NAMED, ASM_OPTION, ASM_OPTIONS, - ASM_PIECE, ASM_REG_OPERAND, ASM_REG_SPEC, ASM_SYM, - ASSOC_ITEM, ASSOC_ITEM_LIST, ASSOC_TYPE_ARG, ATTR, @@ -195,23 +191,18 @@ pub enum SyntaxKind { CONTINUE_EXPR, DYN_TRAIT_TYPE, ENUM, - EXPR, EXPR_STMT, EXTERN_BLOCK, EXTERN_CRATE, - EXTERN_ITEM, EXTERN_ITEM_LIST, FIELD_EXPR, - FIELD_LIST, FN, FN_PTR_TYPE, FORMAT_ARGS_ARG, FORMAT_ARGS_EXPR, FOR_EXPR, FOR_TYPE, - GENERIC_ARG, GENERIC_ARG_LIST, - GENERIC_PARAM, GENERIC_PARAM_LIST, IDENT_PAT, IF_EXPR, @@ -219,7 +210,6 @@ pub enum SyntaxKind { IMPL_TRAIT_TYPE, INDEX_EXPR, INFER_TYPE, - ITEM, ITEM_LIST, LABEL, LET_ELSE, @@ -257,7 +247,6 @@ pub enum SyntaxKind { PAREN_EXPR, PAREN_PAT, PAREN_TYPE, - PAT, PATH, PATH_EXPR, PATH_PAT, @@ -288,7 +277,6 @@ pub enum SyntaxKind { SLICE_TYPE, SOURCE_FILE, STATIC, - STMT, STMT_LIST, STRUCT, TOKEN_TREE, @@ -301,7 +289,6 @@ pub enum SyntaxKind { TUPLE_PAT, TUPLE_STRUCT_PAT, TUPLE_TYPE, - TYPE, TYPE_ALIAS, TYPE_ARG, TYPE_BOUND, @@ -310,12 +297,10 @@ pub enum SyntaxKind { UNDERSCORE_EXPR, UNION, USE, - USE_BOUND_GENERIC_ARG, USE_BOUND_GENERIC_ARGS, USE_TREE, USE_TREE_LIST, VARIANT, - VARIANT_DEF, VARIANT_LIST, VISIBILITY, WHERE_CLAUSE, @@ -343,7 +328,6 @@ impl SyntaxKind { | INT_NUMBER | STRING | ABI - | ADT | ARG_LIST | ARRAY_EXPR | ARRAY_TYPE @@ -352,16 +336,13 @@ impl SyntaxKind { | ASM_DIR_SPEC | ASM_EXPR | ASM_LABEL - | ASM_OPERAND | ASM_OPERAND_EXPR | ASM_OPERAND_NAMED | ASM_OPTION | ASM_OPTIONS - | ASM_PIECE | ASM_REG_OPERAND | ASM_REG_SPEC | ASM_SYM - | ASSOC_ITEM | ASSOC_ITEM_LIST | ASSOC_TYPE_ARG | ATTR @@ -382,23 +363,18 @@ impl SyntaxKind { | CONTINUE_EXPR | DYN_TRAIT_TYPE | ENUM - | EXPR | EXPR_STMT | EXTERN_BLOCK | EXTERN_CRATE - | EXTERN_ITEM | EXTERN_ITEM_LIST | FIELD_EXPR - | FIELD_LIST | FN | FN_PTR_TYPE | FORMAT_ARGS_ARG | FORMAT_ARGS_EXPR | FOR_EXPR | FOR_TYPE - | GENERIC_ARG | GENERIC_ARG_LIST - | GENERIC_PARAM | GENERIC_PARAM_LIST | IDENT_PAT | IF_EXPR @@ -406,7 +382,6 @@ impl SyntaxKind { | IMPL_TRAIT_TYPE | INDEX_EXPR | INFER_TYPE - | ITEM | ITEM_LIST | LABEL | LET_ELSE @@ -444,7 +419,6 @@ impl SyntaxKind { | PAREN_EXPR | PAREN_PAT | PAREN_TYPE - | PAT | PATH | PATH_EXPR | PATH_PAT @@ -475,7 +449,6 @@ impl SyntaxKind { | SLICE_TYPE | SOURCE_FILE | STATIC - | STMT | STMT_LIST | STRUCT | TOKEN_TREE @@ -488,7 +461,6 @@ impl SyntaxKind { | TUPLE_PAT | TUPLE_STRUCT_PAT | TUPLE_TYPE - | TYPE | TYPE_ALIAS | TYPE_ARG | TYPE_BOUND @@ -497,12 +469,10 @@ impl SyntaxKind { | UNDERSCORE_EXPR | UNION | USE - | USE_BOUND_GENERIC_ARG | USE_BOUND_GENERIC_ARGS | USE_TREE | USE_TREE_LIST | VARIANT - | VARIANT_DEF | VARIANT_LIST | VISIBILITY | WHERE_CLAUSE @@ -1024,4 +994,29 @@ impl SyntaxKind { } } #[macro_export] -macro_rules ! T { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [inlateout] => { $ crate :: SyntaxKind :: INLATEOUT_KW } ; [inout] => { $ crate :: SyntaxKind :: INOUT_KW } ; [label] => { $ crate :: SyntaxKind :: LABEL_KW } ; [lateout] => { $ crate :: SyntaxKind :: LATEOUT_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [may_unwind] => { $ crate :: SyntaxKind :: MAY_UNWIND_KW } ; [nomem] => { $ crate :: SyntaxKind :: NOMEM_KW } ; [noreturn] => { $ crate :: SyntaxKind :: NORETURN_KW } ; [nostack] => { $ crate :: SyntaxKind :: NOSTACK_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [options] => { $ crate :: SyntaxKind :: OPTIONS_KW } ; [out] => { $ crate :: SyntaxKind :: OUT_KW } ; [preserves_flags] => { $ crate :: SyntaxKind :: PRESERVES_FLAGS_KW } ; [pure] => { $ crate :: SyntaxKind :: PURE_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [readonly] => { $ crate :: SyntaxKind :: READONLY_KW } ; [safe] => { $ crate :: SyntaxKind :: SAFE_KW } ; [sym] => { $ crate :: SyntaxKind :: SYM_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; } +macro_rules ! T_ { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [inlateout] => { $ crate :: SyntaxKind :: INLATEOUT_KW } ; [inout] => { $ crate :: SyntaxKind :: INOUT_KW } ; [label] => { $ crate :: SyntaxKind :: LABEL_KW } ; [lateout] => { $ crate :: SyntaxKind :: LATEOUT_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [may_unwind] => { $ crate :: SyntaxKind :: MAY_UNWIND_KW } ; [nomem] => { $ crate :: SyntaxKind :: NOMEM_KW } ; [noreturn] => { $ crate :: SyntaxKind :: NORETURN_KW } ; [nostack] => { $ crate :: SyntaxKind :: NOSTACK_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [options] => { $ crate :: SyntaxKind :: OPTIONS_KW } ; [out] => { $ crate :: SyntaxKind :: OUT_KW } ; [preserves_flags] => { $ crate :: SyntaxKind :: PRESERVES_FLAGS_KW } ; [pure] => { $ crate :: SyntaxKind :: PURE_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [readonly] => { $ crate :: SyntaxKind :: READONLY_KW } ; [safe] => { $ crate :: SyntaxKind :: SAFE_KW } ; [sym] => { $ crate :: SyntaxKind :: SYM_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; } +impl ::core::marker::Copy for SyntaxKind {} +impl ::core::clone::Clone for SyntaxKind { + #[inline] + fn clone(&self) -> Self { *self } +} +impl ::core::cmp::PartialEq for SyntaxKind { + #[inline] + fn eq(&self, other: &Self) -> bool { (*self as u16) == (*other as u16) } +} +impl ::core::cmp::Eq for SyntaxKind {} +impl ::core::cmp::PartialOrd for SyntaxKind { + #[inline] + fn partial_cmp(&self, other: &Self) -> core::option::Option { + (*self as u16).partial_cmp(&(*other as u16)) + } +} +impl ::core::cmp::Ord for SyntaxKind { + #[inline] + fn cmp(&self, other: &Self) -> core::cmp::Ordering { (*self as u16).cmp(&(*other as u16)) } +} +impl ::core::hash::Hash for SyntaxKind { + fn hash(&self, state: &mut H) { + ::core::mem::discriminant(self).hash(state); + } +} diff --git a/src/tools/rust-analyzer/xtask/src/codegen.rs b/src/tools/rust-analyzer/xtask/src/codegen.rs index 2aff97b6a4e8a..bba7ad73f3895 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen.rs @@ -21,7 +21,7 @@ impl flags::Codegen { pub(crate) fn run(self, _sh: &Shell) -> anyhow::Result<()> { match self.codegen_type.unwrap_or_default() { flags::CodegenType::All => { - diagnostics_docs::generate(self.check); + grammar::generate(self.check); assists_doc_tests::generate(self.check); parser_inline_tests::generate(self.check); feature_docs::generate(self.check) diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs index 839a6f2028728..e9f38715852c9 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs @@ -476,7 +476,6 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String { let tokens = grammar.tokens.iter().map(|name| format_ident!("{}", name)).collect::>(); - // FIXME: This generates enum kinds? let nodes = grammar.nodes.iter().map(|name| format_ident!("{}", name)).collect::>(); let ast = quote! { @@ -484,7 +483,7 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String { use crate::Edition; /// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`. - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + #[derive(Debug)] #[repr(u16)] pub enum SyntaxKind { // Technical SyntaxKinds: they appear temporally during parsing, @@ -585,7 +584,7 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String { } #[macro_export] - macro_rules! T { + macro_rules! T_ { #([#punctuation_values] => { $crate::SyntaxKind::#punctuation };)* #([#strict_keywords_tokens] => { $crate::SyntaxKind::#strict_keywords_variants };)* #([#contextual_keywords_tokens] => { $crate::SyntaxKind::#contextual_keywords_variants };)* @@ -596,6 +595,38 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String { [string] => { $crate::SyntaxKind::STRING }; [shebang] => { $crate::SyntaxKind::SHEBANG }; } + + impl ::core::marker::Copy for SyntaxKind {} + impl ::core::clone::Clone for SyntaxKind { + #[inline] + fn clone(&self) -> Self { + *self + } + } + impl ::core::cmp::PartialEq for SyntaxKind { + #[inline] + fn eq(&self, other: &Self) -> bool { + (*self as u16) == (*other as u16) + } + } + impl ::core::cmp::Eq for SyntaxKind {} + impl ::core::cmp::PartialOrd for SyntaxKind { + #[inline] + fn partial_cmp(&self, other: &Self) -> core::option::Option { + (*self as u16).partial_cmp(&(*other as u16)) + } + } + impl ::core::cmp::Ord for SyntaxKind { + #[inline] + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + (*self as u16).cmp(&(*other as u16)) + } + } + impl ::core::hash::Hash for SyntaxKind { + fn hash(&self, state: &mut H) { + ::core::mem::discriminant(self).hash(state); + } + } }; add_preamble(crate::flags::CodegenType::Grammar, reformat(ast.to_string())) diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs index 9269d15423534..d8cbf894520ac 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs @@ -12,6 +12,7 @@ pub(crate) struct KindsSrc { pub(crate) literals: &'static [&'static str], pub(crate) tokens: &'static [&'static str], pub(crate) nodes: &'static [&'static str], + pub(crate) _enums: &'static [&'static str], pub(crate) edition_dependent_keywords: &'static [(&'static str, Edition)], } @@ -206,13 +207,21 @@ pub(crate) fn generate_kind_src( let nodes = nodes .iter() .map(|it| &it.name) - .chain(enums.iter().map(|it| &it.name)) .map(|it| to_upper_snake_case(it)) .map(String::leak) .map(|it| &*it) .collect(); let nodes = Vec::leak(nodes); nodes.sort(); + let enums = enums + .iter() + .map(|it| &it.name) + .map(|it| to_upper_snake_case(it)) + .map(String::leak) + .map(|it| &*it) + .collect(); + let enums = Vec::leak(enums); + enums.sort(); let keywords = Vec::leak(keywords); let contextual_keywords = Vec::leak(contextual_keywords); let edition_dependent_keywords = Vec::leak(edition_dependent_keywords); @@ -224,6 +233,7 @@ pub(crate) fn generate_kind_src( KindsSrc { punct: PUNCT, nodes, + _enums: enums, keywords, contextual_keywords, edition_dependent_keywords, From c9355c69bddc39e2c81e895f34ff5ce1a330a14a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 21 Mar 2025 10:54:38 +0100 Subject: [PATCH 0215/2248] refactor: Reduce codegen burden for `SyntaxNode` and `SyntaxToken` --- .../parser/src/syntax_kind/generated.rs | 2 +- .../crates/syntax/src/ast/generated/nodes.rs | 2937 ++++++++++++++--- .../crates/syntax/src/ast/generated/tokens.rs | 171 +- .../xtask/src/codegen/grammar.rs | 91 +- 4 files changed, 2771 insertions(+), 430 deletions(-) diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs index 8836bddc9bb75..e6f93a1fbda57 100644 --- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs +++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs @@ -1008,7 +1008,7 @@ impl ::core::cmp::Eq for SyntaxKind {} impl ::core::cmp::PartialOrd for SyntaxKind { #[inline] fn partial_cmp(&self, other: &Self) -> core::option::Option { - (*self as u16).partial_cmp(&(*other as u16)) + Some(self.cmp(other)) } } impl ::core::cmp::Ord for SyntaxKind { diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs index ebee5e9af2c4d..638b9615ea335 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs @@ -6,8 +6,7 @@ use crate::{ SyntaxKind::{self, *}, SyntaxNode, SyntaxToken, T, }; - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +use std::{fmt, hash}; pub struct Abi { pub(crate) syntax: SyntaxNode, } @@ -17,8 +16,6 @@ impl Abi { #[inline] pub fn string_token(&self) -> Option { support::token(&self.syntax, T![string]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ArgList { pub(crate) syntax: SyntaxNode, } @@ -28,8 +25,6 @@ impl ArgList { #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ArrayExpr { pub(crate) syntax: SyntaxNode, } @@ -46,8 +41,6 @@ impl ArrayExpr { #[inline] pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ArrayType { pub(crate) syntax: SyntaxNode, } @@ -63,8 +56,6 @@ impl ArrayType { #[inline] pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmClobberAbi { pub(crate) syntax: SyntaxNode, } @@ -80,8 +71,6 @@ impl AsmClobberAbi { #[inline] pub fn string_token(&self) -> Option { support::token(&self.syntax, T![string]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmConst { pub(crate) syntax: SyntaxNode, } @@ -91,8 +80,6 @@ impl AsmConst { #[inline] pub fn const_token(&self) -> Option { support::token(&self.syntax, T![const]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmDirSpec { pub(crate) syntax: SyntaxNode, } @@ -110,8 +97,6 @@ impl AsmDirSpec { #[inline] pub fn out_token(&self) -> Option { support::token(&self.syntax, T![out]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmExpr { pub(crate) syntax: SyntaxNode, } @@ -134,8 +119,6 @@ impl AsmExpr { #[inline] pub fn builtin_token(&self) -> Option { support::token(&self.syntax, T![builtin]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmLabel { pub(crate) syntax: SyntaxNode, } @@ -145,8 +128,6 @@ impl AsmLabel { #[inline] pub fn label_token(&self) -> Option { support::token(&self.syntax, T![label]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmOperandExpr { pub(crate) syntax: SyntaxNode, } @@ -158,8 +139,6 @@ impl AsmOperandExpr { #[inline] pub fn fat_arrow_token(&self) -> Option { support::token(&self.syntax, T![=>]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmOperandNamed { pub(crate) syntax: SyntaxNode, } @@ -170,8 +149,6 @@ impl AsmOperandNamed { #[inline] pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmOption { pub(crate) syntax: SyntaxNode, } @@ -205,8 +182,6 @@ impl AsmOption { support::token(&self.syntax, T![readonly]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmOptions { pub(crate) syntax: SyntaxNode, } @@ -222,8 +197,6 @@ impl AsmOptions { #[inline] pub fn options_token(&self) -> Option { support::token(&self.syntax, T![options]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmRegOperand { pub(crate) syntax: SyntaxNode, } @@ -239,8 +212,6 @@ impl AsmRegOperand { #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmRegSpec { pub(crate) syntax: SyntaxNode, } @@ -250,8 +221,6 @@ impl AsmRegSpec { #[inline] pub fn string_token(&self) -> Option { support::token(&self.syntax, T![string]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmSym { pub(crate) syntax: SyntaxNode, } @@ -261,8 +230,6 @@ impl AsmSym { #[inline] pub fn sym_token(&self) -> Option { support::token(&self.syntax, T![sym]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AssocItemList { pub(crate) syntax: SyntaxNode, } @@ -275,8 +242,6 @@ impl AssocItemList { #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AssocTypeArg { pub(crate) syntax: SyntaxNode, } @@ -298,8 +263,6 @@ impl AssocTypeArg { #[inline] pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Attr { pub(crate) syntax: SyntaxNode, } @@ -315,8 +278,6 @@ impl Attr { #[inline] pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AwaitExpr { pub(crate) syntax: SyntaxNode, } @@ -329,8 +290,6 @@ impl AwaitExpr { #[inline] pub fn await_token(&self) -> Option { support::token(&self.syntax, T![await]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct BecomeExpr { pub(crate) syntax: SyntaxNode, } @@ -341,15 +300,11 @@ impl BecomeExpr { #[inline] pub fn become_token(&self) -> Option { support::token(&self.syntax, T![become]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct BinExpr { pub(crate) syntax: SyntaxNode, } impl ast::HasAttrs for BinExpr {} impl BinExpr {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct BlockExpr { pub(crate) syntax: SyntaxNode, } @@ -372,8 +327,6 @@ impl BlockExpr { #[inline] pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct BoxPat { pub(crate) syntax: SyntaxNode, } @@ -383,8 +336,6 @@ impl BoxPat { #[inline] pub fn box_token(&self) -> Option { support::token(&self.syntax, T![box]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct BreakExpr { pub(crate) syntax: SyntaxNode, } @@ -397,8 +348,6 @@ impl BreakExpr { #[inline] pub fn break_token(&self) -> Option { support::token(&self.syntax, T![break]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CallExpr { pub(crate) syntax: SyntaxNode, } @@ -408,8 +357,6 @@ impl CallExpr { #[inline] pub fn expr(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CastExpr { pub(crate) syntax: SyntaxNode, } @@ -422,8 +369,6 @@ impl CastExpr { #[inline] pub fn as_token(&self) -> Option { support::token(&self.syntax, T![as]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ClosureBinder { pub(crate) syntax: SyntaxNode, } @@ -433,8 +378,6 @@ impl ClosureBinder { #[inline] pub fn for_token(&self) -> Option { support::token(&self.syntax, T![for]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ClosureExpr { pub(crate) syntax: SyntaxNode, } @@ -457,8 +400,6 @@ impl ClosureExpr { #[inline] pub fn static_token(&self) -> Option { support::token(&self.syntax, T![static]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Const { pub(crate) syntax: SyntaxNode, } @@ -482,8 +423,6 @@ impl Const { #[inline] pub fn default_token(&self) -> Option { support::token(&self.syntax, T![default]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ConstArg { pub(crate) syntax: SyntaxNode, } @@ -491,8 +430,6 @@ impl ConstArg { #[inline] pub fn expr(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ConstBlockPat { pub(crate) syntax: SyntaxNode, } @@ -502,8 +439,6 @@ impl ConstBlockPat { #[inline] pub fn const_token(&self) -> Option { support::token(&self.syntax, T![const]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ConstParam { pub(crate) syntax: SyntaxNode, } @@ -521,8 +456,6 @@ impl ConstParam { #[inline] pub fn const_token(&self) -> Option { support::token(&self.syntax, T![const]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ContinueExpr { pub(crate) syntax: SyntaxNode, } @@ -535,8 +468,6 @@ impl ContinueExpr { support::token(&self.syntax, T![continue]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct DynTraitType { pub(crate) syntax: SyntaxNode, } @@ -546,8 +477,6 @@ impl DynTraitType { #[inline] pub fn dyn_token(&self) -> Option { support::token(&self.syntax, T![dyn]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Enum { pub(crate) syntax: SyntaxNode, } @@ -562,8 +491,6 @@ impl Enum { #[inline] pub fn enum_token(&self) -> Option { support::token(&self.syntax, T![enum]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ExprStmt { pub(crate) syntax: SyntaxNode, } @@ -573,8 +500,6 @@ impl ExprStmt { #[inline] pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ExternBlock { pub(crate) syntax: SyntaxNode, } @@ -588,8 +513,6 @@ impl ExternBlock { #[inline] pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ExternCrate { pub(crate) syntax: SyntaxNode, } @@ -608,8 +531,6 @@ impl ExternCrate { #[inline] pub fn extern_token(&self) -> Option { support::token(&self.syntax, T![extern]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ExternItemList { pub(crate) syntax: SyntaxNode, } @@ -622,8 +543,6 @@ impl ExternItemList { #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FieldExpr { pub(crate) syntax: SyntaxNode, } @@ -636,8 +555,6 @@ impl FieldExpr { #[inline] pub fn dot_token(&self) -> Option { support::token(&self.syntax, T![.]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Fn { pub(crate) syntax: SyntaxNode, } @@ -670,8 +587,6 @@ impl Fn { #[inline] pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FnPtrType { pub(crate) syntax: SyntaxNode, } @@ -691,8 +606,6 @@ impl FnPtrType { #[inline] pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ForExpr { pub(crate) syntax: SyntaxNode, } @@ -705,8 +618,6 @@ impl ForExpr { #[inline] pub fn in_token(&self) -> Option { support::token(&self.syntax, T![in]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ForType { pub(crate) syntax: SyntaxNode, } @@ -718,8 +629,6 @@ impl ForType { #[inline] pub fn for_token(&self) -> Option { support::token(&self.syntax, T![for]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FormatArgsArg { pub(crate) syntax: SyntaxNode, } @@ -730,8 +639,6 @@ impl FormatArgsArg { #[inline] pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FormatArgsExpr { pub(crate) syntax: SyntaxNode, } @@ -754,8 +661,6 @@ impl FormatArgsExpr { support::token(&self.syntax, T![format_args]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct GenericArgList { pub(crate) syntax: SyntaxNode, } @@ -769,8 +674,6 @@ impl GenericArgList { #[inline] pub fn r_angle_token(&self) -> Option { support::token(&self.syntax, T![>]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct GenericParamList { pub(crate) syntax: SyntaxNode, } @@ -782,8 +685,6 @@ impl GenericParamList { #[inline] pub fn r_angle_token(&self) -> Option { support::token(&self.syntax, T![>]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IdentPat { pub(crate) syntax: SyntaxNode, } @@ -799,8 +700,6 @@ impl IdentPat { #[inline] pub fn ref_token(&self) -> Option { support::token(&self.syntax, T![ref]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IfExpr { pub(crate) syntax: SyntaxNode, } @@ -811,8 +710,6 @@ impl IfExpr { #[inline] pub fn if_token(&self) -> Option { support::token(&self.syntax, T![if]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Impl { pub(crate) syntax: SyntaxNode, } @@ -836,8 +733,6 @@ impl Impl { #[inline] pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ImplTraitType { pub(crate) syntax: SyntaxNode, } @@ -847,8 +742,6 @@ impl ImplTraitType { #[inline] pub fn impl_token(&self) -> Option { support::token(&self.syntax, T![impl]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IndexExpr { pub(crate) syntax: SyntaxNode, } @@ -859,8 +752,6 @@ impl IndexExpr { #[inline] pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct InferType { pub(crate) syntax: SyntaxNode, } @@ -868,8 +759,6 @@ impl InferType { #[inline] pub fn underscore_token(&self) -> Option { support::token(&self.syntax, T![_]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ItemList { pub(crate) syntax: SyntaxNode, } @@ -881,8 +770,6 @@ impl ItemList { #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Label { pub(crate) syntax: SyntaxNode, } @@ -892,8 +779,6 @@ impl Label { #[inline] pub fn colon_token(&self) -> Option { support::token(&self.syntax, T![:]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct LetElse { pub(crate) syntax: SyntaxNode, } @@ -903,8 +788,6 @@ impl LetElse { #[inline] pub fn else_token(&self) -> Option { support::token(&self.syntax, T![else]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct LetExpr { pub(crate) syntax: SyntaxNode, } @@ -919,8 +802,6 @@ impl LetExpr { #[inline] pub fn let_token(&self) -> Option { support::token(&self.syntax, T![let]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct LetStmt { pub(crate) syntax: SyntaxNode, } @@ -943,8 +824,6 @@ impl LetStmt { #[inline] pub fn let_token(&self) -> Option { support::token(&self.syntax, T![let]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Lifetime { pub(crate) syntax: SyntaxNode, } @@ -954,8 +833,6 @@ impl Lifetime { support::token(&self.syntax, T![lifetime_ident]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct LifetimeArg { pub(crate) syntax: SyntaxNode, } @@ -963,8 +840,6 @@ impl LifetimeArg { #[inline] pub fn lifetime(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct LifetimeParam { pub(crate) syntax: SyntaxNode, } @@ -974,15 +849,11 @@ impl LifetimeParam { #[inline] pub fn lifetime(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Literal { pub(crate) syntax: SyntaxNode, } impl ast::HasAttrs for Literal {} impl Literal {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct LiteralPat { pub(crate) syntax: SyntaxNode, } @@ -992,8 +863,6 @@ impl LiteralPat { #[inline] pub fn minus_token(&self) -> Option { support::token(&self.syntax, T![-]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct LoopExpr { pub(crate) syntax: SyntaxNode, } @@ -1003,8 +872,6 @@ impl LoopExpr { #[inline] pub fn loop_token(&self) -> Option { support::token(&self.syntax, T![loop]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroCall { pub(crate) syntax: SyntaxNode, } @@ -1020,8 +887,6 @@ impl MacroCall { #[inline] pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroDef { pub(crate) syntax: SyntaxNode, } @@ -1033,8 +898,6 @@ impl MacroDef { #[inline] pub fn macro_token(&self) -> Option { support::token(&self.syntax, T![macro]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroExpr { pub(crate) syntax: SyntaxNode, } @@ -1042,15 +905,11 @@ impl MacroExpr { #[inline] pub fn macro_call(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroItems { pub(crate) syntax: SyntaxNode, } impl ast::HasModuleItem for MacroItems {} impl MacroItems {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroPat { pub(crate) syntax: SyntaxNode, } @@ -1058,8 +917,6 @@ impl MacroPat { #[inline] pub fn macro_call(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroRules { pub(crate) syntax: SyntaxNode, } @@ -1077,8 +934,6 @@ impl MacroRules { support::token(&self.syntax, T![macro_rules]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroStmts { pub(crate) syntax: SyntaxNode, } @@ -1088,8 +943,6 @@ impl MacroStmts { #[inline] pub fn statements(&self) -> AstChildren { support::children(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroType { pub(crate) syntax: SyntaxNode, } @@ -1097,8 +950,6 @@ impl MacroType { #[inline] pub fn macro_call(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MatchArm { pub(crate) syntax: SyntaxNode, } @@ -1115,8 +966,6 @@ impl MatchArm { #[inline] pub fn fat_arrow_token(&self) -> Option { support::token(&self.syntax, T![=>]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MatchArmList { pub(crate) syntax: SyntaxNode, } @@ -1129,8 +978,6 @@ impl MatchArmList { #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MatchExpr { pub(crate) syntax: SyntaxNode, } @@ -1143,8 +990,6 @@ impl MatchExpr { #[inline] pub fn match_token(&self) -> Option { support::token(&self.syntax, T![match]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MatchGuard { pub(crate) syntax: SyntaxNode, } @@ -1152,8 +997,6 @@ impl MatchGuard { #[inline] pub fn if_token(&self) -> Option { support::token(&self.syntax, T![if]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Meta { pub(crate) syntax: SyntaxNode, } @@ -1173,8 +1016,6 @@ impl Meta { #[inline] pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MethodCallExpr { pub(crate) syntax: SyntaxNode, } @@ -1189,8 +1030,6 @@ impl MethodCallExpr { #[inline] pub fn dot_token(&self) -> Option { support::token(&self.syntax, T![.]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Module { pub(crate) syntax: SyntaxNode, } @@ -1206,8 +1045,6 @@ impl Module { #[inline] pub fn mod_token(&self) -> Option { support::token(&self.syntax, T![mod]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Name { pub(crate) syntax: SyntaxNode, } @@ -1217,8 +1054,6 @@ impl Name { #[inline] pub fn self_token(&self) -> Option { support::token(&self.syntax, T![self]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct NameRef { pub(crate) syntax: SyntaxNode, } @@ -1238,8 +1073,6 @@ impl NameRef { #[inline] pub fn super_token(&self) -> Option { support::token(&self.syntax, T![super]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct NeverType { pub(crate) syntax: SyntaxNode, } @@ -1247,8 +1080,6 @@ impl NeverType { #[inline] pub fn excl_token(&self) -> Option { support::token(&self.syntax, T![!]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct OffsetOfExpr { pub(crate) syntax: SyntaxNode, } @@ -1273,8 +1104,6 @@ impl OffsetOfExpr { support::token(&self.syntax, T![offset_of]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct OrPat { pub(crate) syntax: SyntaxNode, } @@ -1284,8 +1113,6 @@ impl OrPat { #[inline] pub fn pipe_token(&self) -> Option { support::token(&self.syntax, T![|]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Param { pub(crate) syntax: SyntaxNode, } @@ -1300,8 +1127,6 @@ impl Param { #[inline] pub fn colon_token(&self) -> Option { support::token(&self.syntax, T![:]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ParamList { pub(crate) syntax: SyntaxNode, } @@ -1319,8 +1144,6 @@ impl ParamList { #[inline] pub fn pipe_token(&self) -> Option { support::token(&self.syntax, T![|]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ParenExpr { pub(crate) syntax: SyntaxNode, } @@ -1333,8 +1156,6 @@ impl ParenExpr { #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ParenPat { pub(crate) syntax: SyntaxNode, } @@ -1346,8 +1167,6 @@ impl ParenPat { #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ParenType { pub(crate) syntax: SyntaxNode, } @@ -1359,8 +1178,6 @@ impl ParenType { #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ParenthesizedArgList { pub(crate) syntax: SyntaxNode, } @@ -1374,8 +1191,6 @@ impl ParenthesizedArgList { #[inline] pub fn coloncolon_token(&self) -> Option { support::token(&self.syntax, T![::]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { pub(crate) syntax: SyntaxNode, } @@ -1387,8 +1202,6 @@ impl Path { #[inline] pub fn coloncolon_token(&self) -> Option { support::token(&self.syntax, T![::]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PathExpr { pub(crate) syntax: SyntaxNode, } @@ -1397,8 +1210,6 @@ impl PathExpr { #[inline] pub fn path(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PathPat { pub(crate) syntax: SyntaxNode, } @@ -1406,8 +1217,6 @@ impl PathPat { #[inline] pub fn path(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PathSegment { pub(crate) syntax: SyntaxNode, } @@ -1436,8 +1245,6 @@ impl PathSegment { #[inline] pub fn as_token(&self) -> Option { support::token(&self.syntax, T![as]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PathType { pub(crate) syntax: SyntaxNode, } @@ -1445,8 +1252,6 @@ impl PathType { #[inline] pub fn path(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PrefixExpr { pub(crate) syntax: SyntaxNode, } @@ -1455,8 +1260,6 @@ impl PrefixExpr { #[inline] pub fn expr(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PtrType { pub(crate) syntax: SyntaxNode, } @@ -1470,21 +1273,15 @@ impl PtrType { #[inline] pub fn mut_token(&self) -> Option { support::token(&self.syntax, T![mut]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RangeExpr { pub(crate) syntax: SyntaxNode, } impl ast::HasAttrs for RangeExpr {} impl RangeExpr {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RangePat { pub(crate) syntax: SyntaxNode, } impl RangePat {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordExpr { pub(crate) syntax: SyntaxNode, } @@ -1496,8 +1293,6 @@ impl RecordExpr { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordExprField { pub(crate) syntax: SyntaxNode, } @@ -1510,8 +1305,6 @@ impl RecordExprField { #[inline] pub fn colon_token(&self) -> Option { support::token(&self.syntax, T![:]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordExprFieldList { pub(crate) syntax: SyntaxNode, } @@ -1528,8 +1321,6 @@ impl RecordExprFieldList { #[inline] pub fn dotdot_token(&self) -> Option { support::token(&self.syntax, T![..]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordField { pub(crate) syntax: SyntaxNode, } @@ -1547,8 +1338,6 @@ impl RecordField { #[inline] pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordFieldList { pub(crate) syntax: SyntaxNode, } @@ -1560,8 +1349,6 @@ impl RecordFieldList { #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordPat { pub(crate) syntax: SyntaxNode, } @@ -1573,8 +1360,6 @@ impl RecordPat { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordPatField { pub(crate) syntax: SyntaxNode, } @@ -1587,8 +1372,6 @@ impl RecordPatField { #[inline] pub fn colon_token(&self) -> Option { support::token(&self.syntax, T![:]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordPatFieldList { pub(crate) syntax: SyntaxNode, } @@ -1602,8 +1385,6 @@ impl RecordPatFieldList { #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RefExpr { pub(crate) syntax: SyntaxNode, } @@ -1620,8 +1401,6 @@ impl RefExpr { #[inline] pub fn raw_token(&self) -> Option { support::token(&self.syntax, T![raw]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RefPat { pub(crate) syntax: SyntaxNode, } @@ -1633,8 +1412,6 @@ impl RefPat { #[inline] pub fn mut_token(&self) -> Option { support::token(&self.syntax, T![mut]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RefType { pub(crate) syntax: SyntaxNode, } @@ -1648,8 +1425,6 @@ impl RefType { #[inline] pub fn mut_token(&self) -> Option { support::token(&self.syntax, T![mut]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Rename { pub(crate) syntax: SyntaxNode, } @@ -1660,8 +1435,6 @@ impl Rename { #[inline] pub fn as_token(&self) -> Option { support::token(&self.syntax, T![as]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RestPat { pub(crate) syntax: SyntaxNode, } @@ -1670,8 +1443,6 @@ impl RestPat { #[inline] pub fn dotdot_token(&self) -> Option { support::token(&self.syntax, T![..]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RetType { pub(crate) syntax: SyntaxNode, } @@ -1681,8 +1452,6 @@ impl RetType { #[inline] pub fn thin_arrow_token(&self) -> Option { support::token(&self.syntax, T![->]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ReturnExpr { pub(crate) syntax: SyntaxNode, } @@ -1693,8 +1462,6 @@ impl ReturnExpr { #[inline] pub fn return_token(&self) -> Option { support::token(&self.syntax, T![return]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ReturnTypeSyntax { pub(crate) syntax: SyntaxNode, } @@ -1706,8 +1473,6 @@ impl ReturnTypeSyntax { #[inline] pub fn dotdot_token(&self) -> Option { support::token(&self.syntax, T![..]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SelfParam { pub(crate) syntax: SyntaxNode, } @@ -1725,8 +1490,6 @@ impl SelfParam { #[inline] pub fn mut_token(&self) -> Option { support::token(&self.syntax, T![mut]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SlicePat { pub(crate) syntax: SyntaxNode, } @@ -1738,8 +1501,6 @@ impl SlicePat { #[inline] pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SliceType { pub(crate) syntax: SyntaxNode, } @@ -1751,8 +1512,6 @@ impl SliceType { #[inline] pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SourceFile { pub(crate) syntax: SyntaxNode, } @@ -1763,8 +1522,6 @@ impl SourceFile { #[inline] pub fn shebang_token(&self) -> Option { support::token(&self.syntax, T![shebang]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Static { pub(crate) syntax: SyntaxNode, } @@ -1790,8 +1547,6 @@ impl Static { #[inline] pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct StmtList { pub(crate) syntax: SyntaxNode, } @@ -1806,8 +1561,6 @@ impl StmtList { #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Struct { pub(crate) syntax: SyntaxNode, } @@ -1824,8 +1577,6 @@ impl Struct { #[inline] pub fn struct_token(&self) -> Option { support::token(&self.syntax, T![struct]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TokenTree { pub(crate) syntax: SyntaxNode, } @@ -1843,8 +1594,6 @@ impl TokenTree { #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Trait { pub(crate) syntax: SyntaxNode, } @@ -1864,8 +1613,6 @@ impl Trait { #[inline] pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TraitAlias { pub(crate) syntax: SyntaxNode, } @@ -1884,8 +1631,6 @@ impl TraitAlias { #[inline] pub fn trait_token(&self) -> Option { support::token(&self.syntax, T![trait]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TryExpr { pub(crate) syntax: SyntaxNode, } @@ -1896,8 +1641,6 @@ impl TryExpr { #[inline] pub fn question_mark_token(&self) -> Option { support::token(&self.syntax, T![?]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TupleExpr { pub(crate) syntax: SyntaxNode, } @@ -1910,8 +1653,6 @@ impl TupleExpr { #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TupleField { pub(crate) syntax: SyntaxNode, } @@ -1922,8 +1663,6 @@ impl TupleField { #[inline] pub fn ty(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TupleFieldList { pub(crate) syntax: SyntaxNode, } @@ -1935,8 +1674,6 @@ impl TupleFieldList { #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TuplePat { pub(crate) syntax: SyntaxNode, } @@ -1948,8 +1685,6 @@ impl TuplePat { #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TupleStructPat { pub(crate) syntax: SyntaxNode, } @@ -1963,8 +1698,6 @@ impl TupleStructPat { #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TupleType { pub(crate) syntax: SyntaxNode, } @@ -1976,8 +1709,6 @@ impl TupleType { #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TypeAlias { pub(crate) syntax: SyntaxNode, } @@ -1999,8 +1730,6 @@ impl TypeAlias { #[inline] pub fn type_token(&self) -> Option { support::token(&self.syntax, T![type]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TypeArg { pub(crate) syntax: SyntaxNode, } @@ -2008,8 +1737,6 @@ impl TypeArg { #[inline] pub fn ty(&self) -> Option { support::child(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TypeBound { pub(crate) syntax: SyntaxNode, } @@ -2033,8 +1760,6 @@ impl TypeBound { #[inline] pub fn tilde_token(&self) -> Option { support::token(&self.syntax, T![~]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TypeBoundList { pub(crate) syntax: SyntaxNode, } @@ -2042,8 +1767,6 @@ impl TypeBoundList { #[inline] pub fn bounds(&self) -> AstChildren { support::children(&self.syntax) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TypeParam { pub(crate) syntax: SyntaxNode, } @@ -2056,8 +1779,6 @@ impl TypeParam { #[inline] pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UnderscoreExpr { pub(crate) syntax: SyntaxNode, } @@ -2066,8 +1787,6 @@ impl UnderscoreExpr { #[inline] pub fn underscore_token(&self) -> Option { support::token(&self.syntax, T![_]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Union { pub(crate) syntax: SyntaxNode, } @@ -2082,8 +1801,6 @@ impl Union { #[inline] pub fn union_token(&self) -> Option { support::token(&self.syntax, T![union]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Use { pub(crate) syntax: SyntaxNode, } @@ -2098,8 +1815,6 @@ impl Use { #[inline] pub fn use_token(&self) -> Option { support::token(&self.syntax, T![use]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UseBoundGenericArgs { pub(crate) syntax: SyntaxNode, } @@ -2113,8 +1828,6 @@ impl UseBoundGenericArgs { #[inline] pub fn r_angle_token(&self) -> Option { support::token(&self.syntax, T![>]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UseTree { pub(crate) syntax: SyntaxNode, } @@ -2130,8 +1843,6 @@ impl UseTree { #[inline] pub fn coloncolon_token(&self) -> Option { support::token(&self.syntax, T![::]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UseTreeList { pub(crate) syntax: SyntaxNode, } @@ -2143,8 +1854,6 @@ impl UseTreeList { #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Variant { pub(crate) syntax: SyntaxNode, } @@ -2160,8 +1869,6 @@ impl Variant { #[inline] pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct VariantList { pub(crate) syntax: SyntaxNode, } @@ -2173,8 +1880,6 @@ impl VariantList { #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Visibility { pub(crate) syntax: SyntaxNode, } @@ -2190,8 +1895,6 @@ impl Visibility { #[inline] pub fn pub_token(&self) -> Option { support::token(&self.syntax, T![pub]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct WhereClause { pub(crate) syntax: SyntaxNode, } @@ -2201,8 +1904,6 @@ impl WhereClause { #[inline] pub fn where_token(&self) -> Option { support::token(&self.syntax, T![where]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct WherePred { pub(crate) syntax: SyntaxNode, } @@ -2217,8 +1918,6 @@ impl WherePred { #[inline] pub fn for_token(&self) -> Option { support::token(&self.syntax, T![for]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct WhileExpr { pub(crate) syntax: SyntaxNode, } @@ -2227,8 +1926,6 @@ impl WhileExpr { #[inline] pub fn while_token(&self) -> Option { support::token(&self.syntax, T![while]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct WildcardPat { pub(crate) syntax: SyntaxNode, } @@ -2236,8 +1933,6 @@ impl WildcardPat { #[inline] pub fn underscore_token(&self) -> Option { support::token(&self.syntax, T![_]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct YeetExpr { pub(crate) syntax: SyntaxNode, } @@ -2250,8 +1945,6 @@ impl YeetExpr { #[inline] pub fn yeet_token(&self) -> Option { support::token(&self.syntax, T![yeet]) } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct YieldExpr { pub(crate) syntax: SyntaxNode, } @@ -2456,66 +2149,96 @@ impl ast::HasAttrs for VariantDef {} impl ast::HasDocComments for VariantDef {} impl ast::HasName for VariantDef {} impl ast::HasVisibility for VariantDef {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AnyHasArgList { pub(crate) syntax: SyntaxNode, } -impl ast::HasArgList for AnyHasArgList {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl AnyHasArgList { + #[inline] + pub fn new(node: T) -> AnyHasArgList { + AnyHasArgList { syntax: node.syntax().clone() } + } +} pub struct AnyHasAttrs { pub(crate) syntax: SyntaxNode, } -impl ast::HasAttrs for AnyHasAttrs {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl AnyHasAttrs { + #[inline] + pub fn new(node: T) -> AnyHasAttrs { + AnyHasAttrs { syntax: node.syntax().clone() } + } +} pub struct AnyHasDocComments { pub(crate) syntax: SyntaxNode, } -impl ast::HasDocComments for AnyHasDocComments {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl AnyHasDocComments { + #[inline] + pub fn new(node: T) -> AnyHasDocComments { + AnyHasDocComments { syntax: node.syntax().clone() } + } +} pub struct AnyHasGenericArgs { pub(crate) syntax: SyntaxNode, } -impl ast::HasGenericArgs for AnyHasGenericArgs {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl AnyHasGenericArgs { + #[inline] + pub fn new(node: T) -> AnyHasGenericArgs { + AnyHasGenericArgs { syntax: node.syntax().clone() } + } +} pub struct AnyHasGenericParams { pub(crate) syntax: SyntaxNode, } -impl ast::HasGenericParams for AnyHasGenericParams {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl AnyHasGenericParams { + #[inline] + pub fn new(node: T) -> AnyHasGenericParams { + AnyHasGenericParams { syntax: node.syntax().clone() } + } +} pub struct AnyHasLoopBody { pub(crate) syntax: SyntaxNode, } -impl ast::HasLoopBody for AnyHasLoopBody {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl AnyHasLoopBody { + #[inline] + pub fn new(node: T) -> AnyHasLoopBody { + AnyHasLoopBody { syntax: node.syntax().clone() } + } +} pub struct AnyHasModuleItem { pub(crate) syntax: SyntaxNode, } -impl ast::HasModuleItem for AnyHasModuleItem {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl AnyHasModuleItem { + #[inline] + pub fn new(node: T) -> AnyHasModuleItem { + AnyHasModuleItem { syntax: node.syntax().clone() } + } +} pub struct AnyHasName { pub(crate) syntax: SyntaxNode, } -impl ast::HasName for AnyHasName {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl AnyHasName { + #[inline] + pub fn new(node: T) -> AnyHasName { + AnyHasName { syntax: node.syntax().clone() } + } +} pub struct AnyHasTypeBounds { pub(crate) syntax: SyntaxNode, } -impl ast::HasTypeBounds for AnyHasTypeBounds {} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl AnyHasTypeBounds { + #[inline] + pub fn new(node: T) -> AnyHasTypeBounds { + AnyHasTypeBounds { syntax: node.syntax().clone() } + } +} pub struct AnyHasVisibility { pub(crate) syntax: SyntaxNode, } -impl ast::HasVisibility for AnyHasVisibility {} +impl AnyHasVisibility { + #[inline] + pub fn new(node: T) -> AnyHasVisibility { + AnyHasVisibility { syntax: node.syntax().clone() } + } +} impl AstNode for Abi { #[inline] fn kind() -> SyntaxKind @@ -2537,6 +2260,21 @@ impl AstNode for Abi { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Abi { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Abi {} +impl PartialEq for Abi { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Abi { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Abi { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Abi").field("syntax", &self.syntax).finish() + } +} impl AstNode for ArgList { #[inline] fn kind() -> SyntaxKind @@ -2558,6 +2296,21 @@ impl AstNode for ArgList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ArgList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ArgList {} +impl PartialEq for ArgList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ArgList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ArgList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ArgList").field("syntax", &self.syntax).finish() + } +} impl AstNode for ArrayExpr { #[inline] fn kind() -> SyntaxKind @@ -2579,6 +2332,21 @@ impl AstNode for ArrayExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ArrayExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ArrayExpr {} +impl PartialEq for ArrayExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ArrayExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ArrayExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ArrayExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for ArrayType { #[inline] fn kind() -> SyntaxKind @@ -2600,6 +2368,21 @@ impl AstNode for ArrayType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ArrayType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ArrayType {} +impl PartialEq for ArrayType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ArrayType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ArrayType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ArrayType").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmClobberAbi { #[inline] fn kind() -> SyntaxKind @@ -2621,6 +2404,21 @@ impl AstNode for AsmClobberAbi { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmClobberAbi { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmClobberAbi {} +impl PartialEq for AsmClobberAbi { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmClobberAbi { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmClobberAbi { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmClobberAbi").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmConst { #[inline] fn kind() -> SyntaxKind @@ -2642,6 +2440,21 @@ impl AstNode for AsmConst { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmConst { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmConst {} +impl PartialEq for AsmConst { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmConst { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmConst { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmConst").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmDirSpec { #[inline] fn kind() -> SyntaxKind @@ -2663,6 +2476,21 @@ impl AstNode for AsmDirSpec { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmDirSpec { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmDirSpec {} +impl PartialEq for AsmDirSpec { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmDirSpec { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmDirSpec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmDirSpec").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmExpr { #[inline] fn kind() -> SyntaxKind @@ -2684,6 +2512,21 @@ impl AstNode for AsmExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmExpr {} +impl PartialEq for AsmExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmLabel { #[inline] fn kind() -> SyntaxKind @@ -2705,6 +2548,21 @@ impl AstNode for AsmLabel { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmLabel { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmLabel {} +impl PartialEq for AsmLabel { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmLabel { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmLabel { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmLabel").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmOperandExpr { #[inline] fn kind() -> SyntaxKind @@ -2726,6 +2584,21 @@ impl AstNode for AsmOperandExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmOperandExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmOperandExpr {} +impl PartialEq for AsmOperandExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmOperandExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmOperandExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmOperandExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmOperandNamed { #[inline] fn kind() -> SyntaxKind @@ -2747,6 +2620,21 @@ impl AstNode for AsmOperandNamed { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmOperandNamed { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmOperandNamed {} +impl PartialEq for AsmOperandNamed { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmOperandNamed { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmOperandNamed { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmOperandNamed").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmOption { #[inline] fn kind() -> SyntaxKind @@ -2768,6 +2656,21 @@ impl AstNode for AsmOption { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmOption { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmOption {} +impl PartialEq for AsmOption { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmOption { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmOption { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmOption").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmOptions { #[inline] fn kind() -> SyntaxKind @@ -2789,6 +2692,21 @@ impl AstNode for AsmOptions { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmOptions { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmOptions {} +impl PartialEq for AsmOptions { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmOptions { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmOptions { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmOptions").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmRegOperand { #[inline] fn kind() -> SyntaxKind @@ -2810,6 +2728,21 @@ impl AstNode for AsmRegOperand { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmRegOperand { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmRegOperand {} +impl PartialEq for AsmRegOperand { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmRegOperand { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmRegOperand { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmRegOperand").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmRegSpec { #[inline] fn kind() -> SyntaxKind @@ -2831,6 +2764,21 @@ impl AstNode for AsmRegSpec { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmRegSpec { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmRegSpec {} +impl PartialEq for AsmRegSpec { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmRegSpec { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmRegSpec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmRegSpec").field("syntax", &self.syntax).finish() + } +} impl AstNode for AsmSym { #[inline] fn kind() -> SyntaxKind @@ -2852,6 +2800,21 @@ impl AstNode for AsmSym { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AsmSym { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AsmSym {} +impl PartialEq for AsmSym { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AsmSym { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AsmSym { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsmSym").field("syntax", &self.syntax).finish() + } +} impl AstNode for AssocItemList { #[inline] fn kind() -> SyntaxKind @@ -2873,6 +2836,21 @@ impl AstNode for AssocItemList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AssocItemList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AssocItemList {} +impl PartialEq for AssocItemList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AssocItemList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AssocItemList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AssocItemList").field("syntax", &self.syntax).finish() + } +} impl AstNode for AssocTypeArg { #[inline] fn kind() -> SyntaxKind @@ -2894,6 +2872,21 @@ impl AstNode for AssocTypeArg { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AssocTypeArg { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AssocTypeArg {} +impl PartialEq for AssocTypeArg { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AssocTypeArg { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AssocTypeArg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AssocTypeArg").field("syntax", &self.syntax).finish() + } +} impl AstNode for Attr { #[inline] fn kind() -> SyntaxKind @@ -2915,6 +2908,21 @@ impl AstNode for Attr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Attr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Attr {} +impl PartialEq for Attr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Attr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Attr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Attr").field("syntax", &self.syntax).finish() + } +} impl AstNode for AwaitExpr { #[inline] fn kind() -> SyntaxKind @@ -2936,6 +2944,21 @@ impl AstNode for AwaitExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AwaitExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AwaitExpr {} +impl PartialEq for AwaitExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AwaitExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AwaitExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AwaitExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for BecomeExpr { #[inline] fn kind() -> SyntaxKind @@ -2957,6 +2980,21 @@ impl AstNode for BecomeExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for BecomeExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for BecomeExpr {} +impl PartialEq for BecomeExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for BecomeExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for BecomeExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BecomeExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for BinExpr { #[inline] fn kind() -> SyntaxKind @@ -2978,6 +3016,21 @@ impl AstNode for BinExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for BinExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for BinExpr {} +impl PartialEq for BinExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for BinExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for BinExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BinExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for BlockExpr { #[inline] fn kind() -> SyntaxKind @@ -2999,6 +3052,21 @@ impl AstNode for BlockExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for BlockExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for BlockExpr {} +impl PartialEq for BlockExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for BlockExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for BlockExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BlockExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for BoxPat { #[inline] fn kind() -> SyntaxKind @@ -3020,6 +3088,21 @@ impl AstNode for BoxPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for BoxPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for BoxPat {} +impl PartialEq for BoxPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for BoxPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for BoxPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BoxPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for BreakExpr { #[inline] fn kind() -> SyntaxKind @@ -3041,6 +3124,21 @@ impl AstNode for BreakExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for BreakExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for BreakExpr {} +impl PartialEq for BreakExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for BreakExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for BreakExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BreakExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for CallExpr { #[inline] fn kind() -> SyntaxKind @@ -3059,8 +3157,23 @@ impl AstNode for CallExpr { None } } - #[inline] - fn syntax(&self) -> &SyntaxNode { &self.syntax } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl hash::Hash for CallExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for CallExpr {} +impl PartialEq for CallExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for CallExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for CallExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CallExpr").field("syntax", &self.syntax).finish() + } } impl AstNode for CastExpr { #[inline] @@ -3083,6 +3196,21 @@ impl AstNode for CastExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for CastExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for CastExpr {} +impl PartialEq for CastExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for CastExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for CastExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CastExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for ClosureBinder { #[inline] fn kind() -> SyntaxKind @@ -3104,6 +3232,21 @@ impl AstNode for ClosureBinder { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ClosureBinder { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ClosureBinder {} +impl PartialEq for ClosureBinder { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ClosureBinder { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ClosureBinder { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ClosureBinder").field("syntax", &self.syntax).finish() + } +} impl AstNode for ClosureExpr { #[inline] fn kind() -> SyntaxKind @@ -3125,6 +3268,21 @@ impl AstNode for ClosureExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ClosureExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ClosureExpr {} +impl PartialEq for ClosureExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ClosureExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ClosureExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ClosureExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for Const { #[inline] fn kind() -> SyntaxKind @@ -3146,6 +3304,21 @@ impl AstNode for Const { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Const { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Const {} +impl PartialEq for Const { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Const { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Const { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Const").field("syntax", &self.syntax).finish() + } +} impl AstNode for ConstArg { #[inline] fn kind() -> SyntaxKind @@ -3167,6 +3340,21 @@ impl AstNode for ConstArg { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ConstArg { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ConstArg {} +impl PartialEq for ConstArg { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ConstArg { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ConstArg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ConstArg").field("syntax", &self.syntax).finish() + } +} impl AstNode for ConstBlockPat { #[inline] fn kind() -> SyntaxKind @@ -3188,6 +3376,21 @@ impl AstNode for ConstBlockPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ConstBlockPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ConstBlockPat {} +impl PartialEq for ConstBlockPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ConstBlockPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ConstBlockPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ConstBlockPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for ConstParam { #[inline] fn kind() -> SyntaxKind @@ -3209,6 +3412,21 @@ impl AstNode for ConstParam { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ConstParam { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ConstParam {} +impl PartialEq for ConstParam { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ConstParam { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ConstParam { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ConstParam").field("syntax", &self.syntax).finish() + } +} impl AstNode for ContinueExpr { #[inline] fn kind() -> SyntaxKind @@ -3230,6 +3448,21 @@ impl AstNode for ContinueExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ContinueExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ContinueExpr {} +impl PartialEq for ContinueExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ContinueExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ContinueExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ContinueExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for DynTraitType { #[inline] fn kind() -> SyntaxKind @@ -3251,6 +3484,21 @@ impl AstNode for DynTraitType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for DynTraitType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for DynTraitType {} +impl PartialEq for DynTraitType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for DynTraitType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for DynTraitType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("DynTraitType").field("syntax", &self.syntax).finish() + } +} impl AstNode for Enum { #[inline] fn kind() -> SyntaxKind @@ -3272,6 +3520,21 @@ impl AstNode for Enum { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Enum { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Enum {} +impl PartialEq for Enum { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Enum { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Enum { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Enum").field("syntax", &self.syntax).finish() + } +} impl AstNode for ExprStmt { #[inline] fn kind() -> SyntaxKind @@ -3293,6 +3556,21 @@ impl AstNode for ExprStmt { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ExprStmt { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ExprStmt {} +impl PartialEq for ExprStmt { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ExprStmt { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ExprStmt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ExprStmt").field("syntax", &self.syntax).finish() + } +} impl AstNode for ExternBlock { #[inline] fn kind() -> SyntaxKind @@ -3314,6 +3592,21 @@ impl AstNode for ExternBlock { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ExternBlock { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ExternBlock {} +impl PartialEq for ExternBlock { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ExternBlock { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ExternBlock { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ExternBlock").field("syntax", &self.syntax).finish() + } +} impl AstNode for ExternCrate { #[inline] fn kind() -> SyntaxKind @@ -3335,6 +3628,21 @@ impl AstNode for ExternCrate { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ExternCrate { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ExternCrate {} +impl PartialEq for ExternCrate { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ExternCrate { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ExternCrate { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ExternCrate").field("syntax", &self.syntax).finish() + } +} impl AstNode for ExternItemList { #[inline] fn kind() -> SyntaxKind @@ -3356,6 +3664,21 @@ impl AstNode for ExternItemList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ExternItemList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ExternItemList {} +impl PartialEq for ExternItemList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ExternItemList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ExternItemList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ExternItemList").field("syntax", &self.syntax).finish() + } +} impl AstNode for FieldExpr { #[inline] fn kind() -> SyntaxKind @@ -3377,6 +3700,21 @@ impl AstNode for FieldExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for FieldExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for FieldExpr {} +impl PartialEq for FieldExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for FieldExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for FieldExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FieldExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for Fn { #[inline] fn kind() -> SyntaxKind @@ -3398,6 +3736,21 @@ impl AstNode for Fn { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Fn { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Fn {} +impl PartialEq for Fn { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Fn { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Fn { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Fn").field("syntax", &self.syntax).finish() + } +} impl AstNode for FnPtrType { #[inline] fn kind() -> SyntaxKind @@ -3419,6 +3772,21 @@ impl AstNode for FnPtrType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for FnPtrType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for FnPtrType {} +impl PartialEq for FnPtrType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for FnPtrType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for FnPtrType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FnPtrType").field("syntax", &self.syntax).finish() + } +} impl AstNode for ForExpr { #[inline] fn kind() -> SyntaxKind @@ -3440,6 +3808,21 @@ impl AstNode for ForExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ForExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ForExpr {} +impl PartialEq for ForExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ForExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ForExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ForExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for ForType { #[inline] fn kind() -> SyntaxKind @@ -3461,6 +3844,21 @@ impl AstNode for ForType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ForType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ForType {} +impl PartialEq for ForType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ForType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ForType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ForType").field("syntax", &self.syntax).finish() + } +} impl AstNode for FormatArgsArg { #[inline] fn kind() -> SyntaxKind @@ -3482,6 +3880,21 @@ impl AstNode for FormatArgsArg { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for FormatArgsArg { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for FormatArgsArg {} +impl PartialEq for FormatArgsArg { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for FormatArgsArg { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for FormatArgsArg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FormatArgsArg").field("syntax", &self.syntax).finish() + } +} impl AstNode for FormatArgsExpr { #[inline] fn kind() -> SyntaxKind @@ -3503,6 +3916,21 @@ impl AstNode for FormatArgsExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for FormatArgsExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for FormatArgsExpr {} +impl PartialEq for FormatArgsExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for FormatArgsExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for FormatArgsExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FormatArgsExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for GenericArgList { #[inline] fn kind() -> SyntaxKind @@ -3524,6 +3952,21 @@ impl AstNode for GenericArgList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for GenericArgList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for GenericArgList {} +impl PartialEq for GenericArgList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for GenericArgList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for GenericArgList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("GenericArgList").field("syntax", &self.syntax).finish() + } +} impl AstNode for GenericParamList { #[inline] fn kind() -> SyntaxKind @@ -3545,6 +3988,21 @@ impl AstNode for GenericParamList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for GenericParamList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for GenericParamList {} +impl PartialEq for GenericParamList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for GenericParamList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for GenericParamList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("GenericParamList").field("syntax", &self.syntax).finish() + } +} impl AstNode for IdentPat { #[inline] fn kind() -> SyntaxKind @@ -3566,6 +4024,21 @@ impl AstNode for IdentPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for IdentPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for IdentPat {} +impl PartialEq for IdentPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for IdentPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for IdentPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("IdentPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for IfExpr { #[inline] fn kind() -> SyntaxKind @@ -3587,6 +4060,21 @@ impl AstNode for IfExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for IfExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for IfExpr {} +impl PartialEq for IfExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for IfExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for IfExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("IfExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for Impl { #[inline] fn kind() -> SyntaxKind @@ -3608,6 +4096,21 @@ impl AstNode for Impl { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Impl { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Impl {} +impl PartialEq for Impl { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Impl { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Impl { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Impl").field("syntax", &self.syntax).finish() + } +} impl AstNode for ImplTraitType { #[inline] fn kind() -> SyntaxKind @@ -3629,6 +4132,21 @@ impl AstNode for ImplTraitType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ImplTraitType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ImplTraitType {} +impl PartialEq for ImplTraitType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ImplTraitType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ImplTraitType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ImplTraitType").field("syntax", &self.syntax).finish() + } +} impl AstNode for IndexExpr { #[inline] fn kind() -> SyntaxKind @@ -3650,6 +4168,21 @@ impl AstNode for IndexExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for IndexExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for IndexExpr {} +impl PartialEq for IndexExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for IndexExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for IndexExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("IndexExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for InferType { #[inline] fn kind() -> SyntaxKind @@ -3671,6 +4204,21 @@ impl AstNode for InferType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for InferType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for InferType {} +impl PartialEq for InferType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for InferType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for InferType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("InferType").field("syntax", &self.syntax).finish() + } +} impl AstNode for ItemList { #[inline] fn kind() -> SyntaxKind @@ -3692,6 +4240,21 @@ impl AstNode for ItemList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ItemList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ItemList {} +impl PartialEq for ItemList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ItemList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ItemList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ItemList").field("syntax", &self.syntax).finish() + } +} impl AstNode for Label { #[inline] fn kind() -> SyntaxKind @@ -3713,6 +4276,21 @@ impl AstNode for Label { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Label { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Label {} +impl PartialEq for Label { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Label { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Label { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Label").field("syntax", &self.syntax).finish() + } +} impl AstNode for LetElse { #[inline] fn kind() -> SyntaxKind @@ -3734,6 +4312,21 @@ impl AstNode for LetElse { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for LetElse { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for LetElse {} +impl PartialEq for LetElse { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for LetElse { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for LetElse { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("LetElse").field("syntax", &self.syntax).finish() + } +} impl AstNode for LetExpr { #[inline] fn kind() -> SyntaxKind @@ -3755,6 +4348,21 @@ impl AstNode for LetExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for LetExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for LetExpr {} +impl PartialEq for LetExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for LetExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for LetExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("LetExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for LetStmt { #[inline] fn kind() -> SyntaxKind @@ -3776,6 +4384,21 @@ impl AstNode for LetStmt { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for LetStmt { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for LetStmt {} +impl PartialEq for LetStmt { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for LetStmt { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for LetStmt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("LetStmt").field("syntax", &self.syntax).finish() + } +} impl AstNode for Lifetime { #[inline] fn kind() -> SyntaxKind @@ -3797,6 +4420,21 @@ impl AstNode for Lifetime { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Lifetime { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Lifetime {} +impl PartialEq for Lifetime { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Lifetime { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Lifetime { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Lifetime").field("syntax", &self.syntax).finish() + } +} impl AstNode for LifetimeArg { #[inline] fn kind() -> SyntaxKind @@ -3818,6 +4456,21 @@ impl AstNode for LifetimeArg { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for LifetimeArg { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for LifetimeArg {} +impl PartialEq for LifetimeArg { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for LifetimeArg { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for LifetimeArg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("LifetimeArg").field("syntax", &self.syntax).finish() + } +} impl AstNode for LifetimeParam { #[inline] fn kind() -> SyntaxKind @@ -3839,6 +4492,21 @@ impl AstNode for LifetimeParam { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for LifetimeParam { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for LifetimeParam {} +impl PartialEq for LifetimeParam { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for LifetimeParam { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for LifetimeParam { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("LifetimeParam").field("syntax", &self.syntax).finish() + } +} impl AstNode for Literal { #[inline] fn kind() -> SyntaxKind @@ -3860,6 +4528,21 @@ impl AstNode for Literal { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Literal { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Literal {} +impl PartialEq for Literal { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Literal { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Literal { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Literal").field("syntax", &self.syntax).finish() + } +} impl AstNode for LiteralPat { #[inline] fn kind() -> SyntaxKind @@ -3881,6 +4564,21 @@ impl AstNode for LiteralPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for LiteralPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for LiteralPat {} +impl PartialEq for LiteralPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for LiteralPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for LiteralPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("LiteralPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for LoopExpr { #[inline] fn kind() -> SyntaxKind @@ -3902,6 +4600,21 @@ impl AstNode for LoopExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for LoopExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for LoopExpr {} +impl PartialEq for LoopExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for LoopExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for LoopExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("LoopExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for MacroCall { #[inline] fn kind() -> SyntaxKind @@ -3923,6 +4636,21 @@ impl AstNode for MacroCall { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MacroCall { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MacroCall {} +impl PartialEq for MacroCall { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MacroCall { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MacroCall { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MacroCall").field("syntax", &self.syntax).finish() + } +} impl AstNode for MacroDef { #[inline] fn kind() -> SyntaxKind @@ -3944,6 +4672,21 @@ impl AstNode for MacroDef { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MacroDef { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MacroDef {} +impl PartialEq for MacroDef { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MacroDef { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MacroDef { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MacroDef").field("syntax", &self.syntax).finish() + } +} impl AstNode for MacroExpr { #[inline] fn kind() -> SyntaxKind @@ -3965,6 +4708,21 @@ impl AstNode for MacroExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MacroExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MacroExpr {} +impl PartialEq for MacroExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MacroExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MacroExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MacroExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for MacroItems { #[inline] fn kind() -> SyntaxKind @@ -3986,6 +4744,21 @@ impl AstNode for MacroItems { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MacroItems { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MacroItems {} +impl PartialEq for MacroItems { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MacroItems { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MacroItems { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MacroItems").field("syntax", &self.syntax).finish() + } +} impl AstNode for MacroPat { #[inline] fn kind() -> SyntaxKind @@ -4007,6 +4780,21 @@ impl AstNode for MacroPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MacroPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MacroPat {} +impl PartialEq for MacroPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MacroPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MacroPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MacroPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for MacroRules { #[inline] fn kind() -> SyntaxKind @@ -4028,6 +4816,21 @@ impl AstNode for MacroRules { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MacroRules { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MacroRules {} +impl PartialEq for MacroRules { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MacroRules { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MacroRules { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MacroRules").field("syntax", &self.syntax).finish() + } +} impl AstNode for MacroStmts { #[inline] fn kind() -> SyntaxKind @@ -4049,6 +4852,21 @@ impl AstNode for MacroStmts { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MacroStmts { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MacroStmts {} +impl PartialEq for MacroStmts { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MacroStmts { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MacroStmts { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MacroStmts").field("syntax", &self.syntax).finish() + } +} impl AstNode for MacroType { #[inline] fn kind() -> SyntaxKind @@ -4070,6 +4888,21 @@ impl AstNode for MacroType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MacroType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MacroType {} +impl PartialEq for MacroType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MacroType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MacroType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MacroType").field("syntax", &self.syntax).finish() + } +} impl AstNode for MatchArm { #[inline] fn kind() -> SyntaxKind @@ -4091,6 +4924,21 @@ impl AstNode for MatchArm { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MatchArm { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MatchArm {} +impl PartialEq for MatchArm { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MatchArm { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MatchArm { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MatchArm").field("syntax", &self.syntax).finish() + } +} impl AstNode for MatchArmList { #[inline] fn kind() -> SyntaxKind @@ -4109,8 +4957,23 @@ impl AstNode for MatchArmList { None } } - #[inline] - fn syntax(&self) -> &SyntaxNode { &self.syntax } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl hash::Hash for MatchArmList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MatchArmList {} +impl PartialEq for MatchArmList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MatchArmList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MatchArmList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MatchArmList").field("syntax", &self.syntax).finish() + } } impl AstNode for MatchExpr { #[inline] @@ -4133,6 +4996,21 @@ impl AstNode for MatchExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MatchExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MatchExpr {} +impl PartialEq for MatchExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MatchExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MatchExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MatchExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for MatchGuard { #[inline] fn kind() -> SyntaxKind @@ -4154,6 +5032,21 @@ impl AstNode for MatchGuard { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MatchGuard { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MatchGuard {} +impl PartialEq for MatchGuard { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MatchGuard { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MatchGuard { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MatchGuard").field("syntax", &self.syntax).finish() + } +} impl AstNode for Meta { #[inline] fn kind() -> SyntaxKind @@ -4175,6 +5068,21 @@ impl AstNode for Meta { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Meta { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Meta {} +impl PartialEq for Meta { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Meta { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Meta { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Meta").field("syntax", &self.syntax).finish() + } +} impl AstNode for MethodCallExpr { #[inline] fn kind() -> SyntaxKind @@ -4196,6 +5104,21 @@ impl AstNode for MethodCallExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for MethodCallExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for MethodCallExpr {} +impl PartialEq for MethodCallExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for MethodCallExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for MethodCallExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MethodCallExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for Module { #[inline] fn kind() -> SyntaxKind @@ -4217,6 +5140,21 @@ impl AstNode for Module { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Module { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Module {} +impl PartialEq for Module { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Module { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Module { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Module").field("syntax", &self.syntax).finish() + } +} impl AstNode for Name { #[inline] fn kind() -> SyntaxKind @@ -4238,6 +5176,21 @@ impl AstNode for Name { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Name { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Name {} +impl PartialEq for Name { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Name { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Name").field("syntax", &self.syntax).finish() + } +} impl AstNode for NameRef { #[inline] fn kind() -> SyntaxKind @@ -4259,6 +5212,21 @@ impl AstNode for NameRef { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for NameRef { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for NameRef {} +impl PartialEq for NameRef { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for NameRef { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for NameRef { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("NameRef").field("syntax", &self.syntax).finish() + } +} impl AstNode for NeverType { #[inline] fn kind() -> SyntaxKind @@ -4280,6 +5248,21 @@ impl AstNode for NeverType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for NeverType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for NeverType {} +impl PartialEq for NeverType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for NeverType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for NeverType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("NeverType").field("syntax", &self.syntax).finish() + } +} impl AstNode for OffsetOfExpr { #[inline] fn kind() -> SyntaxKind @@ -4301,6 +5284,21 @@ impl AstNode for OffsetOfExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for OffsetOfExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for OffsetOfExpr {} +impl PartialEq for OffsetOfExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for OffsetOfExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for OffsetOfExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OffsetOfExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for OrPat { #[inline] fn kind() -> SyntaxKind @@ -4322,6 +5320,21 @@ impl AstNode for OrPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for OrPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for OrPat {} +impl PartialEq for OrPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for OrPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for OrPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OrPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for Param { #[inline] fn kind() -> SyntaxKind @@ -4343,6 +5356,21 @@ impl AstNode for Param { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Param { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Param {} +impl PartialEq for Param { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Param { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Param { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Param").field("syntax", &self.syntax).finish() + } +} impl AstNode for ParamList { #[inline] fn kind() -> SyntaxKind @@ -4364,6 +5392,21 @@ impl AstNode for ParamList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ParamList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ParamList {} +impl PartialEq for ParamList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ParamList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ParamList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ParamList").field("syntax", &self.syntax).finish() + } +} impl AstNode for ParenExpr { #[inline] fn kind() -> SyntaxKind @@ -4385,6 +5428,21 @@ impl AstNode for ParenExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ParenExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ParenExpr {} +impl PartialEq for ParenExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ParenExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ParenExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ParenExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for ParenPat { #[inline] fn kind() -> SyntaxKind @@ -4406,6 +5464,21 @@ impl AstNode for ParenPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ParenPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ParenPat {} +impl PartialEq for ParenPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ParenPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ParenPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ParenPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for ParenType { #[inline] fn kind() -> SyntaxKind @@ -4427,6 +5500,21 @@ impl AstNode for ParenType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ParenType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ParenType {} +impl PartialEq for ParenType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ParenType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ParenType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ParenType").field("syntax", &self.syntax).finish() + } +} impl AstNode for ParenthesizedArgList { #[inline] fn kind() -> SyntaxKind @@ -4448,6 +5536,21 @@ impl AstNode for ParenthesizedArgList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ParenthesizedArgList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ParenthesizedArgList {} +impl PartialEq for ParenthesizedArgList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ParenthesizedArgList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ParenthesizedArgList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ParenthesizedArgList").field("syntax", &self.syntax).finish() + } +} impl AstNode for Path { #[inline] fn kind() -> SyntaxKind @@ -4469,6 +5572,21 @@ impl AstNode for Path { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Path { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Path {} +impl PartialEq for Path { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Path { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Path { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Path").field("syntax", &self.syntax).finish() + } +} impl AstNode for PathExpr { #[inline] fn kind() -> SyntaxKind @@ -4490,6 +5608,21 @@ impl AstNode for PathExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for PathExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for PathExpr {} +impl PartialEq for PathExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for PathExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for PathExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PathExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for PathPat { #[inline] fn kind() -> SyntaxKind @@ -4511,6 +5644,21 @@ impl AstNode for PathPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for PathPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for PathPat {} +impl PartialEq for PathPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for PathPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for PathPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PathPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for PathSegment { #[inline] fn kind() -> SyntaxKind @@ -4532,6 +5680,21 @@ impl AstNode for PathSegment { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for PathSegment { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for PathSegment {} +impl PartialEq for PathSegment { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for PathSegment { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for PathSegment { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PathSegment").field("syntax", &self.syntax).finish() + } +} impl AstNode for PathType { #[inline] fn kind() -> SyntaxKind @@ -4553,6 +5716,21 @@ impl AstNode for PathType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for PathType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for PathType {} +impl PartialEq for PathType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for PathType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for PathType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PathType").field("syntax", &self.syntax).finish() + } +} impl AstNode for PrefixExpr { #[inline] fn kind() -> SyntaxKind @@ -4574,6 +5752,21 @@ impl AstNode for PrefixExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for PrefixExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for PrefixExpr {} +impl PartialEq for PrefixExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for PrefixExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for PrefixExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PrefixExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for PtrType { #[inline] fn kind() -> SyntaxKind @@ -4595,6 +5788,21 @@ impl AstNode for PtrType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for PtrType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for PtrType {} +impl PartialEq for PtrType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for PtrType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for PtrType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PtrType").field("syntax", &self.syntax).finish() + } +} impl AstNode for RangeExpr { #[inline] fn kind() -> SyntaxKind @@ -4616,6 +5824,21 @@ impl AstNode for RangeExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RangeExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RangeExpr {} +impl PartialEq for RangeExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RangeExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RangeExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RangeExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for RangePat { #[inline] fn kind() -> SyntaxKind @@ -4637,6 +5860,21 @@ impl AstNode for RangePat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RangePat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RangePat {} +impl PartialEq for RangePat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RangePat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RangePat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RangePat").field("syntax", &self.syntax).finish() + } +} impl AstNode for RecordExpr { #[inline] fn kind() -> SyntaxKind @@ -4658,6 +5896,21 @@ impl AstNode for RecordExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RecordExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RecordExpr {} +impl PartialEq for RecordExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RecordExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RecordExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RecordExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for RecordExprField { #[inline] fn kind() -> SyntaxKind @@ -4679,6 +5932,21 @@ impl AstNode for RecordExprField { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RecordExprField { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RecordExprField {} +impl PartialEq for RecordExprField { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RecordExprField { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RecordExprField { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RecordExprField").field("syntax", &self.syntax).finish() + } +} impl AstNode for RecordExprFieldList { #[inline] fn kind() -> SyntaxKind @@ -4700,6 +5968,21 @@ impl AstNode for RecordExprFieldList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RecordExprFieldList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RecordExprFieldList {} +impl PartialEq for RecordExprFieldList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RecordExprFieldList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RecordExprFieldList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RecordExprFieldList").field("syntax", &self.syntax).finish() + } +} impl AstNode for RecordField { #[inline] fn kind() -> SyntaxKind @@ -4721,6 +6004,21 @@ impl AstNode for RecordField { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RecordField { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RecordField {} +impl PartialEq for RecordField { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RecordField { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RecordField { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RecordField").field("syntax", &self.syntax).finish() + } +} impl AstNode for RecordFieldList { #[inline] fn kind() -> SyntaxKind @@ -4742,6 +6040,21 @@ impl AstNode for RecordFieldList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RecordFieldList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RecordFieldList {} +impl PartialEq for RecordFieldList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RecordFieldList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RecordFieldList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RecordFieldList").field("syntax", &self.syntax).finish() + } +} impl AstNode for RecordPat { #[inline] fn kind() -> SyntaxKind @@ -4763,6 +6076,21 @@ impl AstNode for RecordPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RecordPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RecordPat {} +impl PartialEq for RecordPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RecordPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RecordPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RecordPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for RecordPatField { #[inline] fn kind() -> SyntaxKind @@ -4784,6 +6112,21 @@ impl AstNode for RecordPatField { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RecordPatField { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RecordPatField {} +impl PartialEq for RecordPatField { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RecordPatField { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RecordPatField { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RecordPatField").field("syntax", &self.syntax).finish() + } +} impl AstNode for RecordPatFieldList { #[inline] fn kind() -> SyntaxKind @@ -4805,6 +6148,21 @@ impl AstNode for RecordPatFieldList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RecordPatFieldList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RecordPatFieldList {} +impl PartialEq for RecordPatFieldList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RecordPatFieldList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RecordPatFieldList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RecordPatFieldList").field("syntax", &self.syntax).finish() + } +} impl AstNode for RefExpr { #[inline] fn kind() -> SyntaxKind @@ -4826,6 +6184,21 @@ impl AstNode for RefExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RefExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RefExpr {} +impl PartialEq for RefExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RefExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RefExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RefExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for RefPat { #[inline] fn kind() -> SyntaxKind @@ -4847,6 +6220,21 @@ impl AstNode for RefPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RefPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RefPat {} +impl PartialEq for RefPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RefPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RefPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RefPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for RefType { #[inline] fn kind() -> SyntaxKind @@ -4868,6 +6256,21 @@ impl AstNode for RefType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RefType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RefType {} +impl PartialEq for RefType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RefType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RefType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RefType").field("syntax", &self.syntax).finish() + } +} impl AstNode for Rename { #[inline] fn kind() -> SyntaxKind @@ -4889,6 +6292,21 @@ impl AstNode for Rename { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Rename { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Rename {} +impl PartialEq for Rename { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Rename { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Rename { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Rename").field("syntax", &self.syntax).finish() + } +} impl AstNode for RestPat { #[inline] fn kind() -> SyntaxKind @@ -4910,6 +6328,21 @@ impl AstNode for RestPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RestPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RestPat {} +impl PartialEq for RestPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RestPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RestPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RestPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for RetType { #[inline] fn kind() -> SyntaxKind @@ -4931,6 +6364,21 @@ impl AstNode for RetType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for RetType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for RetType {} +impl PartialEq for RetType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for RetType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for RetType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RetType").field("syntax", &self.syntax).finish() + } +} impl AstNode for ReturnExpr { #[inline] fn kind() -> SyntaxKind @@ -4952,6 +6400,21 @@ impl AstNode for ReturnExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ReturnExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ReturnExpr {} +impl PartialEq for ReturnExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ReturnExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ReturnExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ReturnExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for ReturnTypeSyntax { #[inline] fn kind() -> SyntaxKind @@ -4973,6 +6436,21 @@ impl AstNode for ReturnTypeSyntax { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for ReturnTypeSyntax { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ReturnTypeSyntax {} +impl PartialEq for ReturnTypeSyntax { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for ReturnTypeSyntax { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for ReturnTypeSyntax { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ReturnTypeSyntax").field("syntax", &self.syntax).finish() + } +} impl AstNode for SelfParam { #[inline] fn kind() -> SyntaxKind @@ -4994,6 +6472,21 @@ impl AstNode for SelfParam { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for SelfParam { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for SelfParam {} +impl PartialEq for SelfParam { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for SelfParam { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for SelfParam { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SelfParam").field("syntax", &self.syntax).finish() + } +} impl AstNode for SlicePat { #[inline] fn kind() -> SyntaxKind @@ -5015,6 +6508,21 @@ impl AstNode for SlicePat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for SlicePat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for SlicePat {} +impl PartialEq for SlicePat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for SlicePat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for SlicePat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SlicePat").field("syntax", &self.syntax).finish() + } +} impl AstNode for SliceType { #[inline] fn kind() -> SyntaxKind @@ -5036,6 +6544,21 @@ impl AstNode for SliceType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for SliceType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for SliceType {} +impl PartialEq for SliceType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for SliceType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for SliceType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SliceType").field("syntax", &self.syntax).finish() + } +} impl AstNode for SourceFile { #[inline] fn kind() -> SyntaxKind @@ -5057,6 +6580,21 @@ impl AstNode for SourceFile { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for SourceFile { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for SourceFile {} +impl PartialEq for SourceFile { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for SourceFile { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for SourceFile { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SourceFile").field("syntax", &self.syntax).finish() + } +} impl AstNode for Static { #[inline] fn kind() -> SyntaxKind @@ -5078,6 +6616,21 @@ impl AstNode for Static { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Static { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Static {} +impl PartialEq for Static { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Static { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Static { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Static").field("syntax", &self.syntax).finish() + } +} impl AstNode for StmtList { #[inline] fn kind() -> SyntaxKind @@ -5099,6 +6652,21 @@ impl AstNode for StmtList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for StmtList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for StmtList {} +impl PartialEq for StmtList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for StmtList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for StmtList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("StmtList").field("syntax", &self.syntax).finish() + } +} impl AstNode for Struct { #[inline] fn kind() -> SyntaxKind @@ -5120,6 +6688,21 @@ impl AstNode for Struct { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Struct { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Struct {} +impl PartialEq for Struct { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Struct { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Struct { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Struct").field("syntax", &self.syntax).finish() + } +} impl AstNode for TokenTree { #[inline] fn kind() -> SyntaxKind @@ -5141,6 +6724,21 @@ impl AstNode for TokenTree { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TokenTree { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TokenTree {} +impl PartialEq for TokenTree { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TokenTree { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TokenTree { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TokenTree").field("syntax", &self.syntax).finish() + } +} impl AstNode for Trait { #[inline] fn kind() -> SyntaxKind @@ -5162,6 +6760,21 @@ impl AstNode for Trait { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Trait { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Trait {} +impl PartialEq for Trait { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Trait { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Trait { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Trait").field("syntax", &self.syntax).finish() + } +} impl AstNode for TraitAlias { #[inline] fn kind() -> SyntaxKind @@ -5183,6 +6796,21 @@ impl AstNode for TraitAlias { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TraitAlias { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TraitAlias {} +impl PartialEq for TraitAlias { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TraitAlias { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TraitAlias { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TraitAlias").field("syntax", &self.syntax).finish() + } +} impl AstNode for TryExpr { #[inline] fn kind() -> SyntaxKind @@ -5204,6 +6832,21 @@ impl AstNode for TryExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TryExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TryExpr {} +impl PartialEq for TryExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TryExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TryExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TryExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for TupleExpr { #[inline] fn kind() -> SyntaxKind @@ -5225,6 +6868,21 @@ impl AstNode for TupleExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TupleExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TupleExpr {} +impl PartialEq for TupleExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TupleExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TupleExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TupleExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for TupleField { #[inline] fn kind() -> SyntaxKind @@ -5246,6 +6904,21 @@ impl AstNode for TupleField { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TupleField { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TupleField {} +impl PartialEq for TupleField { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TupleField { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TupleField { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TupleField").field("syntax", &self.syntax).finish() + } +} impl AstNode for TupleFieldList { #[inline] fn kind() -> SyntaxKind @@ -5267,6 +6940,21 @@ impl AstNode for TupleFieldList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TupleFieldList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TupleFieldList {} +impl PartialEq for TupleFieldList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TupleFieldList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TupleFieldList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TupleFieldList").field("syntax", &self.syntax).finish() + } +} impl AstNode for TuplePat { #[inline] fn kind() -> SyntaxKind @@ -5288,6 +6976,21 @@ impl AstNode for TuplePat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TuplePat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TuplePat {} +impl PartialEq for TuplePat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TuplePat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TuplePat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TuplePat").field("syntax", &self.syntax).finish() + } +} impl AstNode for TupleStructPat { #[inline] fn kind() -> SyntaxKind @@ -5309,6 +7012,21 @@ impl AstNode for TupleStructPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TupleStructPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TupleStructPat {} +impl PartialEq for TupleStructPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TupleStructPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TupleStructPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TupleStructPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for TupleType { #[inline] fn kind() -> SyntaxKind @@ -5330,6 +7048,21 @@ impl AstNode for TupleType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TupleType { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TupleType {} +impl PartialEq for TupleType { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TupleType { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TupleType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TupleType").field("syntax", &self.syntax).finish() + } +} impl AstNode for TypeAlias { #[inline] fn kind() -> SyntaxKind @@ -5351,6 +7084,21 @@ impl AstNode for TypeAlias { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TypeAlias { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TypeAlias {} +impl PartialEq for TypeAlias { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TypeAlias { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TypeAlias { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TypeAlias").field("syntax", &self.syntax).finish() + } +} impl AstNode for TypeArg { #[inline] fn kind() -> SyntaxKind @@ -5372,6 +7120,21 @@ impl AstNode for TypeArg { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TypeArg { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TypeArg {} +impl PartialEq for TypeArg { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TypeArg { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TypeArg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TypeArg").field("syntax", &self.syntax).finish() + } +} impl AstNode for TypeBound { #[inline] fn kind() -> SyntaxKind @@ -5393,6 +7156,21 @@ impl AstNode for TypeBound { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TypeBound { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TypeBound {} +impl PartialEq for TypeBound { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TypeBound { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TypeBound { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TypeBound").field("syntax", &self.syntax).finish() + } +} impl AstNode for TypeBoundList { #[inline] fn kind() -> SyntaxKind @@ -5414,6 +7192,21 @@ impl AstNode for TypeBoundList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TypeBoundList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TypeBoundList {} +impl PartialEq for TypeBoundList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TypeBoundList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TypeBoundList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TypeBoundList").field("syntax", &self.syntax).finish() + } +} impl AstNode for TypeParam { #[inline] fn kind() -> SyntaxKind @@ -5435,6 +7228,21 @@ impl AstNode for TypeParam { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for TypeParam { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TypeParam {} +impl PartialEq for TypeParam { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TypeParam { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TypeParam { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TypeParam").field("syntax", &self.syntax).finish() + } +} impl AstNode for UnderscoreExpr { #[inline] fn kind() -> SyntaxKind @@ -5456,6 +7264,21 @@ impl AstNode for UnderscoreExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for UnderscoreExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for UnderscoreExpr {} +impl PartialEq for UnderscoreExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for UnderscoreExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for UnderscoreExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("UnderscoreExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for Union { #[inline] fn kind() -> SyntaxKind @@ -5477,6 +7300,21 @@ impl AstNode for Union { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Union { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Union {} +impl PartialEq for Union { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Union { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Union { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Union").field("syntax", &self.syntax).finish() + } +} impl AstNode for Use { #[inline] fn kind() -> SyntaxKind @@ -5498,6 +7336,21 @@ impl AstNode for Use { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Use { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Use {} +impl PartialEq for Use { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Use { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Use { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Use").field("syntax", &self.syntax).finish() + } +} impl AstNode for UseBoundGenericArgs { #[inline] fn kind() -> SyntaxKind @@ -5519,6 +7372,21 @@ impl AstNode for UseBoundGenericArgs { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for UseBoundGenericArgs { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for UseBoundGenericArgs {} +impl PartialEq for UseBoundGenericArgs { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for UseBoundGenericArgs { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for UseBoundGenericArgs { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("UseBoundGenericArgs").field("syntax", &self.syntax).finish() + } +} impl AstNode for UseTree { #[inline] fn kind() -> SyntaxKind @@ -5540,6 +7408,21 @@ impl AstNode for UseTree { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for UseTree { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for UseTree {} +impl PartialEq for UseTree { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for UseTree { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for UseTree { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("UseTree").field("syntax", &self.syntax).finish() + } +} impl AstNode for UseTreeList { #[inline] fn kind() -> SyntaxKind @@ -5561,6 +7444,21 @@ impl AstNode for UseTreeList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for UseTreeList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for UseTreeList {} +impl PartialEq for UseTreeList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for UseTreeList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for UseTreeList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("UseTreeList").field("syntax", &self.syntax).finish() + } +} impl AstNode for Variant { #[inline] fn kind() -> SyntaxKind @@ -5582,6 +7480,21 @@ impl AstNode for Variant { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Variant { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Variant {} +impl PartialEq for Variant { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Variant { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Variant { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Variant").field("syntax", &self.syntax).finish() + } +} impl AstNode for VariantList { #[inline] fn kind() -> SyntaxKind @@ -5603,6 +7516,21 @@ impl AstNode for VariantList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for VariantList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for VariantList {} +impl PartialEq for VariantList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for VariantList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for VariantList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("VariantList").field("syntax", &self.syntax).finish() + } +} impl AstNode for Visibility { #[inline] fn kind() -> SyntaxKind @@ -5624,6 +7552,21 @@ impl AstNode for Visibility { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for Visibility { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Visibility {} +impl PartialEq for Visibility { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for Visibility { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for Visibility { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Visibility").field("syntax", &self.syntax).finish() + } +} impl AstNode for WhereClause { #[inline] fn kind() -> SyntaxKind @@ -5645,6 +7588,21 @@ impl AstNode for WhereClause { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for WhereClause { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for WhereClause {} +impl PartialEq for WhereClause { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for WhereClause { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for WhereClause { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WhereClause").field("syntax", &self.syntax).finish() + } +} impl AstNode for WherePred { #[inline] fn kind() -> SyntaxKind @@ -5666,6 +7624,21 @@ impl AstNode for WherePred { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for WherePred { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for WherePred {} +impl PartialEq for WherePred { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for WherePred { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for WherePred { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WherePred").field("syntax", &self.syntax).finish() + } +} impl AstNode for WhileExpr { #[inline] fn kind() -> SyntaxKind @@ -5687,6 +7660,21 @@ impl AstNode for WhileExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for WhileExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for WhileExpr {} +impl PartialEq for WhileExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for WhileExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for WhileExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WhileExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for WildcardPat { #[inline] fn kind() -> SyntaxKind @@ -5708,6 +7696,21 @@ impl AstNode for WildcardPat { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for WildcardPat { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for WildcardPat {} +impl PartialEq for WildcardPat { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for WildcardPat { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for WildcardPat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WildcardPat").field("syntax", &self.syntax).finish() + } +} impl AstNode for YeetExpr { #[inline] fn kind() -> SyntaxKind @@ -5729,6 +7732,21 @@ impl AstNode for YeetExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for YeetExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for YeetExpr {} +impl PartialEq for YeetExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for YeetExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for YeetExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("YeetExpr").field("syntax", &self.syntax).finish() + } +} impl AstNode for YieldExpr { #[inline] fn kind() -> SyntaxKind @@ -5750,6 +7768,21 @@ impl AstNode for YieldExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for YieldExpr { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for YieldExpr {} +impl PartialEq for YieldExpr { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for YieldExpr { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for YieldExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("YieldExpr").field("syntax", &self.syntax).finish() + } +} impl From for Adt { #[inline] fn from(node: Enum) -> Adt { Adt::Enum(node) } @@ -6783,12 +8816,7 @@ impl AstNode for VariantDef { } } } -impl AnyHasArgList { - #[inline] - pub fn new(node: T) -> AnyHasArgList { - AnyHasArgList { syntax: node.syntax().clone() } - } -} +impl ast::HasArgList for AnyHasArgList {} impl AstNode for AnyHasArgList { #[inline] fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, CALL_EXPR | METHOD_CALL_EXPR) } @@ -6799,6 +8827,21 @@ impl AstNode for AnyHasArgList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AnyHasArgList { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AnyHasArgList {} +impl PartialEq for AnyHasArgList { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AnyHasArgList { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AnyHasArgList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyHasArgList").field("syntax", &self.syntax).finish() + } +} impl From for AnyHasArgList { #[inline] fn from(node: CallExpr) -> AnyHasArgList { AnyHasArgList { syntax: node.syntax } } @@ -6807,12 +8850,7 @@ impl From for AnyHasArgList { #[inline] fn from(node: MethodCallExpr) -> AnyHasArgList { AnyHasArgList { syntax: node.syntax } } } -impl AnyHasAttrs { - #[inline] - pub fn new(node: T) -> AnyHasAttrs { - AnyHasAttrs { syntax: node.syntax().clone() } - } -} +impl ast::HasAttrs for AnyHasAttrs {} impl AstNode for AnyHasAttrs { #[inline] fn can_cast(kind: SyntaxKind) -> bool { @@ -6899,6 +8937,21 @@ impl AstNode for AnyHasAttrs { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AnyHasAttrs { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AnyHasAttrs {} +impl PartialEq for AnyHasAttrs { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AnyHasAttrs { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AnyHasAttrs { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyHasAttrs").field("syntax", &self.syntax).finish() + } +} impl From for AnyHasAttrs { #[inline] fn from(node: ArrayExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } @@ -7187,12 +9240,7 @@ impl From for AnyHasAttrs { #[inline] fn from(node: YieldExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } } -impl AnyHasDocComments { - #[inline] - pub fn new(node: T) -> AnyHasDocComments { - AnyHasDocComments { syntax: node.syntax().clone() } - } -} +impl ast::HasDocComments for AnyHasDocComments {} impl AstNode for AnyHasDocComments { #[inline] fn can_cast(kind: SyntaxKind) -> bool { @@ -7228,6 +9276,21 @@ impl AstNode for AnyHasDocComments { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AnyHasDocComments { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AnyHasDocComments {} +impl PartialEq for AnyHasDocComments { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AnyHasDocComments { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AnyHasDocComments { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyHasDocComments").field("syntax", &self.syntax).finish() + } +} impl From for AnyHasDocComments { #[inline] fn from(node: Const) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } @@ -7312,12 +9375,7 @@ impl From for AnyHasDocComments { #[inline] fn from(node: Variant) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } } -impl AnyHasGenericArgs { - #[inline] - pub fn new(node: T) -> AnyHasGenericArgs { - AnyHasGenericArgs { syntax: node.syntax().clone() } - } -} +impl ast::HasGenericArgs for AnyHasGenericArgs {} impl AstNode for AnyHasGenericArgs { #[inline] fn can_cast(kind: SyntaxKind) -> bool { @@ -7330,6 +9388,21 @@ impl AstNode for AnyHasGenericArgs { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AnyHasGenericArgs { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AnyHasGenericArgs {} +impl PartialEq for AnyHasGenericArgs { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AnyHasGenericArgs { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AnyHasGenericArgs { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyHasGenericArgs").field("syntax", &self.syntax).finish() + } +} impl From for AnyHasGenericArgs { #[inline] fn from(node: AssocTypeArg) -> AnyHasGenericArgs { AnyHasGenericArgs { syntax: node.syntax } } @@ -7342,12 +9415,7 @@ impl From for AnyHasGenericArgs { #[inline] fn from(node: PathSegment) -> AnyHasGenericArgs { AnyHasGenericArgs { syntax: node.syntax } } } -impl AnyHasGenericParams { - #[inline] - pub fn new(node: T) -> AnyHasGenericParams { - AnyHasGenericParams { syntax: node.syntax().clone() } - } -} +impl ast::HasGenericParams for AnyHasGenericParams {} impl AstNode for AnyHasGenericParams { #[inline] fn can_cast(kind: SyntaxKind) -> bool { @@ -7360,6 +9428,21 @@ impl AstNode for AnyHasGenericParams { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AnyHasGenericParams { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AnyHasGenericParams {} +impl PartialEq for AnyHasGenericParams { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AnyHasGenericParams { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AnyHasGenericParams { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyHasGenericParams").field("syntax", &self.syntax).finish() + } +} impl From for AnyHasGenericParams { #[inline] fn from(node: Enum) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } } @@ -7392,12 +9475,7 @@ impl From for AnyHasGenericParams { #[inline] fn from(node: Union) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } } } -impl AnyHasLoopBody { - #[inline] - pub fn new(node: T) -> AnyHasLoopBody { - AnyHasLoopBody { syntax: node.syntax().clone() } - } -} +impl ast::HasLoopBody for AnyHasLoopBody {} impl AstNode for AnyHasLoopBody { #[inline] fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, FOR_EXPR | LOOP_EXPR | WHILE_EXPR) } @@ -7408,6 +9486,21 @@ impl AstNode for AnyHasLoopBody { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AnyHasLoopBody { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AnyHasLoopBody {} +impl PartialEq for AnyHasLoopBody { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AnyHasLoopBody { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AnyHasLoopBody { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyHasLoopBody").field("syntax", &self.syntax).finish() + } +} impl From for AnyHasLoopBody { #[inline] fn from(node: ForExpr) -> AnyHasLoopBody { AnyHasLoopBody { syntax: node.syntax } } @@ -7420,12 +9513,7 @@ impl From for AnyHasLoopBody { #[inline] fn from(node: WhileExpr) -> AnyHasLoopBody { AnyHasLoopBody { syntax: node.syntax } } } -impl AnyHasModuleItem { - #[inline] - pub fn new(node: T) -> AnyHasModuleItem { - AnyHasModuleItem { syntax: node.syntax().clone() } - } -} +impl ast::HasModuleItem for AnyHasModuleItem {} impl AstNode for AnyHasModuleItem { #[inline] fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, ITEM_LIST | MACRO_ITEMS | SOURCE_FILE) } @@ -7436,6 +9524,21 @@ impl AstNode for AnyHasModuleItem { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AnyHasModuleItem { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AnyHasModuleItem {} +impl PartialEq for AnyHasModuleItem { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AnyHasModuleItem { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AnyHasModuleItem { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyHasModuleItem").field("syntax", &self.syntax).finish() + } +} impl From for AnyHasModuleItem { #[inline] fn from(node: ItemList) -> AnyHasModuleItem { AnyHasModuleItem { syntax: node.syntax } } @@ -7448,12 +9551,7 @@ impl From for AnyHasModuleItem { #[inline] fn from(node: SourceFile) -> AnyHasModuleItem { AnyHasModuleItem { syntax: node.syntax } } } -impl AnyHasName { - #[inline] - pub fn new(node: T) -> AnyHasName { - AnyHasName { syntax: node.syntax().clone() } - } -} +impl ast::HasName for AnyHasName {} impl AstNode for AnyHasName { #[inline] fn can_cast(kind: SyntaxKind) -> bool { @@ -7489,6 +9587,21 @@ impl AstNode for AnyHasName { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AnyHasName { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AnyHasName {} +impl PartialEq for AnyHasName { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AnyHasName { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AnyHasName { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyHasName").field("syntax", &self.syntax).finish() + } +} impl From for AnyHasName { #[inline] fn from(node: AsmOperandNamed) -> AnyHasName { AnyHasName { syntax: node.syntax } } @@ -7573,12 +9686,7 @@ impl From for AnyHasName { #[inline] fn from(node: Variant) -> AnyHasName { AnyHasName { syntax: node.syntax } } } -impl AnyHasTypeBounds { - #[inline] - pub fn new(node: T) -> AnyHasTypeBounds { - AnyHasTypeBounds { syntax: node.syntax().clone() } - } -} +impl ast::HasTypeBounds for AnyHasTypeBounds {} impl AstNode for AnyHasTypeBounds { #[inline] fn can_cast(kind: SyntaxKind) -> bool { @@ -7594,6 +9702,21 @@ impl AstNode for AnyHasTypeBounds { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AnyHasTypeBounds { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AnyHasTypeBounds {} +impl PartialEq for AnyHasTypeBounds { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AnyHasTypeBounds { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AnyHasTypeBounds { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyHasTypeBounds").field("syntax", &self.syntax).finish() + } +} impl From for AnyHasTypeBounds { #[inline] fn from(node: AssocTypeArg) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } } @@ -7618,12 +9741,7 @@ impl From for AnyHasTypeBounds { #[inline] fn from(node: WherePred) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } } } -impl AnyHasVisibility { - #[inline] - pub fn new(node: T) -> AnyHasVisibility { - AnyHasVisibility { syntax: node.syntax().clone() } - } -} +impl ast::HasVisibility for AnyHasVisibility {} impl AstNode for AnyHasVisibility { #[inline] fn can_cast(kind: SyntaxKind) -> bool { @@ -7656,6 +9774,21 @@ impl AstNode for AnyHasVisibility { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl hash::Hash for AnyHasVisibility { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for AnyHasVisibility {} +impl PartialEq for AnyHasVisibility { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for AnyHasVisibility { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for AnyHasVisibility { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyHasVisibility").field("syntax", &self.syntax).finish() + } +} impl From for AnyHasVisibility { #[inline] fn from(node: Const) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/tokens.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/tokens.rs index df2e9619db1c3..b2f56c0b1dbf2 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/tokens.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/tokens.rs @@ -5,8 +5,7 @@ use crate::{ SyntaxKind::{self, *}, SyntaxToken, }; - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +use std::{fmt, hash}; pub struct Byte { pub(crate) syntax: SyntaxToken, } @@ -26,8 +25,21 @@ impl AstToken for Byte { } fn syntax(&self) -> &SyntaxToken { &self.syntax } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl fmt::Debug for Byte { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Byte").field("syntax", &self.syntax).finish() + } +} +impl Clone for Byte { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl hash::Hash for Byte { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Byte {} +impl PartialEq for Byte { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} pub struct ByteString { pub(crate) syntax: SyntaxToken, } @@ -47,8 +59,21 @@ impl AstToken for ByteString { } fn syntax(&self) -> &SyntaxToken { &self.syntax } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl fmt::Debug for ByteString { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ByteString").field("syntax", &self.syntax).finish() + } +} +impl Clone for ByteString { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl hash::Hash for ByteString { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for ByteString {} +impl PartialEq for ByteString { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} pub struct CString { pub(crate) syntax: SyntaxToken, } @@ -68,8 +93,21 @@ impl AstToken for CString { } fn syntax(&self) -> &SyntaxToken { &self.syntax } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl fmt::Debug for CString { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CString").field("syntax", &self.syntax).finish() + } +} +impl Clone for CString { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl hash::Hash for CString { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for CString {} +impl PartialEq for CString { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} pub struct Char { pub(crate) syntax: SyntaxToken, } @@ -89,8 +127,21 @@ impl AstToken for Char { } fn syntax(&self) -> &SyntaxToken { &self.syntax } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl fmt::Debug for Char { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Char").field("syntax", &self.syntax).finish() + } +} +impl Clone for Char { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl hash::Hash for Char { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Char {} +impl PartialEq for Char { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} pub struct Comment { pub(crate) syntax: SyntaxToken, } @@ -110,8 +161,21 @@ impl AstToken for Comment { } fn syntax(&self) -> &SyntaxToken { &self.syntax } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl fmt::Debug for Comment { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Comment").field("syntax", &self.syntax).finish() + } +} +impl Clone for Comment { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl hash::Hash for Comment { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Comment {} +impl PartialEq for Comment { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} pub struct FloatNumber { pub(crate) syntax: SyntaxToken, } @@ -131,8 +195,21 @@ impl AstToken for FloatNumber { } fn syntax(&self) -> &SyntaxToken { &self.syntax } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl fmt::Debug for FloatNumber { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FloatNumber").field("syntax", &self.syntax).finish() + } +} +impl Clone for FloatNumber { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl hash::Hash for FloatNumber { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for FloatNumber {} +impl PartialEq for FloatNumber { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} pub struct Ident { pub(crate) syntax: SyntaxToken, } @@ -152,8 +229,21 @@ impl AstToken for Ident { } fn syntax(&self) -> &SyntaxToken { &self.syntax } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl fmt::Debug for Ident { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Ident").field("syntax", &self.syntax).finish() + } +} +impl Clone for Ident { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl hash::Hash for Ident { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Ident {} +impl PartialEq for Ident { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} pub struct IntNumber { pub(crate) syntax: SyntaxToken, } @@ -173,8 +263,21 @@ impl AstToken for IntNumber { } fn syntax(&self) -> &SyntaxToken { &self.syntax } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl fmt::Debug for IntNumber { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("IntNumber").field("syntax", &self.syntax).finish() + } +} +impl Clone for IntNumber { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl hash::Hash for IntNumber { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for IntNumber {} +impl PartialEq for IntNumber { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} pub struct String { pub(crate) syntax: SyntaxToken, } @@ -194,8 +297,21 @@ impl AstToken for String { } fn syntax(&self) -> &SyntaxToken { &self.syntax } } - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +impl fmt::Debug for String { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("String").field("syntax", &self.syntax).finish() + } +} +impl Clone for String { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl hash::Hash for String { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for String {} +impl PartialEq for String { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} pub struct Whitespace { pub(crate) syntax: SyntaxToken, } @@ -215,3 +331,18 @@ impl AstToken for Whitespace { } fn syntax(&self) -> &SyntaxToken { &self.syntax } } +impl fmt::Debug for Whitespace { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Whitespace").field("syntax", &self.syntax).finish() + } +} +impl Clone for Whitespace { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl hash::Hash for Whitespace { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for Whitespace {} +impl PartialEq for Whitespace { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs index e9f38715852c9..bdba1b348d91b 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs @@ -67,7 +67,6 @@ fn generate_tokens(grammar: &AstSrc) -> String { let name = format_ident!("{}", token); let kind = format_ident!("{}", to_upper_snake_case(token)); quote! { - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct #name { pub(crate) syntax: SyntaxToken, } @@ -83,6 +82,29 @@ fn generate_tokens(grammar: &AstSrc) -> String { } fn syntax(&self) -> &SyntaxToken { &self.syntax } } + + impl fmt::Debug for #name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct(#token).field("syntax", &self.syntax).finish() + } + } + impl Clone for #name { + fn clone(&self) -> Self { + Self { syntax: self.syntax.clone() } + } + } + impl hash::Hash for #name { + fn hash(&self, state: &mut H) { + self.syntax.hash(state); + } + } + + impl Eq for #name {} + impl PartialEq for #name { + fn eq(&self, other: &Self) -> bool { + self.syntax == other.syntax + } + } } }); @@ -90,7 +112,10 @@ fn generate_tokens(grammar: &AstSrc) -> String { crate::flags::CodegenType::Grammar, reformat( quote! { + use std::{fmt, hash}; + use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken}; + #(#tokens)* } .to_string(), @@ -104,6 +129,7 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { .nodes .iter() .map(|node| { + let node_str_name = &node.name; let name = format_ident!("{}", node.name); let kind = format_ident!("{}", to_upper_snake_case(&node.name)); let traits = node @@ -149,7 +175,6 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { ( quote! { #[pretty_doc_comment_placeholder_workaround] - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct #name { pub(crate) syntax: SyntaxNode, } @@ -180,6 +205,31 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } + + impl hash::Hash for #name { + fn hash(&self, state: &mut H) { + self.syntax.hash(state); + } + } + + impl Eq for #name {} + impl PartialEq for #name { + fn eq(&self, other: &Self) -> bool { + self.syntax == other.syntax + } + } + + impl Clone for #name { + fn clone(&self) -> Self { + Self { syntax: self.syntax.clone() } + } + } + + impl fmt::Debug for #name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct(#node_str_name).field("syntax", &self.syntax).finish() + } + } }, ) }) @@ -265,6 +315,7 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { .sorted_by_key(|(name, _)| *name) .map(|(trait_name, nodes)| { let name = format_ident!("Any{}", trait_name); + let node_str_name = name.to_string(); let trait_name = format_ident!("{}", trait_name); let kinds: Vec<_> = nodes .iter() @@ -274,13 +325,9 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { ( quote! { #[pretty_doc_comment_placeholder_workaround] - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct #name { pub(crate) syntax: SyntaxNode, } - impl ast::#trait_name for #name {} - }, - quote! { impl #name { #[inline] pub fn new(node: T) -> #name { @@ -289,6 +336,9 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { } } } + }, + quote! { + impl ast::#trait_name for #name {} impl AstNode for #name { #[inline] fn can_cast(kind: SyntaxKind) -> bool { @@ -304,6 +354,31 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { } } + impl hash::Hash for #name { + fn hash(&self, state: &mut H) { + self.syntax.hash(state); + } + } + + impl Eq for #name {} + impl PartialEq for #name { + fn eq(&self, other: &Self) -> bool { + self.syntax == other.syntax + } + } + + impl Clone for #name { + fn clone(&self) -> Self { + Self { syntax: self.syntax.clone() } + } + } + + impl fmt::Debug for #name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct(#node_str_name).field("syntax", &self.syntax).finish() + } + } + #( impl From<#nodes> for #name { #[inline] @@ -346,6 +421,8 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { let ast = quote! { #![allow(non_snake_case)] + use std::{fmt, hash}; + use crate::{ SyntaxNode, SyntaxToken, SyntaxKind::{self, *}, ast::{self, AstNode, AstChildren, support}, @@ -613,7 +690,7 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String { impl ::core::cmp::PartialOrd for SyntaxKind { #[inline] fn partial_cmp(&self, other: &Self) -> core::option::Option { - (*self as u16).partial_cmp(&(*other as u16)) + Some(self.cmp(other)) } } impl ::core::cmp::Ord for SyntaxKind { From ed4a749f528e31746dfa64f44dd97309c808e20f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 21 Mar 2025 10:26:55 +0100 Subject: [PATCH 0216/2248] fix: Fix incorrect expansion of builtin `PartialOrd` derive --- .../hir-def/src/macro_expansion_tests/builtin_derive_macro.rs | 2 +- .../rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs | 2 +- src/tools/rust-analyzer/crates/parser/src/syntax_kind.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs index c31d322132897..777953d3f212b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs @@ -336,7 +336,7 @@ enum Command { } impl <> $crate::cmp::PartialOrd for Command< > where { - fn partial_cmp(&self , other: &Self ) -> $crate::option::Option::Option<$crate::cmp::Ordering> { + fn partial_cmp(&self , other: &Self ) -> $crate::option::Option<$crate::cmp::Ordering> { match $crate::intrinsics::discriminant_value(self ).partial_cmp(&$crate::intrinsics::discriminant_value(other)) { $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> { match (self , other) { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs index b6181e8ce8c90..2ad8cd8377d54 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs @@ -969,7 +969,7 @@ fn partial_ord_expand( span, ); quote! {span => - fn partial_cmp(&self, other: &Self) -> #krate::option::Option::Option<#krate::cmp::Ordering> { + fn partial_cmp(&self, other: &Self) -> #krate::option::Option<#krate::cmp::Ordering> { #body } } diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind.rs index 6a8cca9ccc79d..7311947525ed9 100644 --- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind.rs +++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind.rs @@ -1,6 +1,7 @@ //! Defines [`SyntaxKind`] -- a fieldless enum of all possible syntactic //! constructs of the Rust language. +#[rustfmt::skip] mod generated; use crate::Edition; From da4f5a58a929145127b5cf82ed271ca7279244b0 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Fri, 21 Mar 2025 21:20:39 +0900 Subject: [PATCH 0217/2248] expand `neg_multiply` to lint float numbers as well --- clippy_lints/src/neg_multiply.rs | 10 +++---- tests/ui/neg_multiply.fixed | 29 ++++++++++++++++++ tests/ui/neg_multiply.rs | 29 ++++++++++++++++++ tests/ui/neg_multiply.stderr | 50 +++++++++++++++++++++++++++++++- 4 files changed, 112 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 429afff9b6642..86eb833becc20 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -16,9 +16,6 @@ declare_clippy_lint! { /// ### Why is this bad? /// It's more readable to just negate. /// - /// ### Known problems - /// This only catches integers (for now). - /// /// ### Example /// ```rust,ignore /// let a = x * -1; @@ -53,8 +50,11 @@ impl<'tcx> LateLintPass<'tcx> for NegMultiply { fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { if let ExprKind::Lit(l) = lit.kind - && consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1) - && cx.typeck_results().expr_ty(exp).is_integral() + && matches!( + consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)), + Constant::Int(1) | Constant::F16(1.0) | Constant::F32(1.0) | Constant::F64(1.0) | Constant::F128(1.0) + ) + && cx.typeck_results().expr_ty(exp).is_numeric() { let mut applicability = Applicability::MachineApplicable; let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability); diff --git a/tests/ui/neg_multiply.fixed b/tests/ui/neg_multiply.fixed index 995470493bfb7..ff6e08300e298 100644 --- a/tests/ui/neg_multiply.fixed +++ b/tests/ui/neg_multiply.fixed @@ -53,3 +53,32 @@ fn main() { X * -1; // should be ok -1 * X; // should also be ok } + +fn float() { + let x = 0.0; + + -x; + //~^ neg_multiply + + -x; + //~^ neg_multiply + + 100.0 + -x; + //~^ neg_multiply + + -(100.0 + x); + //~^ neg_multiply + + -17.0; + //~^ neg_multiply + + 0.0 + -0.0; + //~^ neg_multiply + + -(3.0_f32 as f64); + //~^ neg_multiply + -(3.0_f32 as f64); + //~^ neg_multiply + + -1.0 * -1.0; // should be ok +} diff --git a/tests/ui/neg_multiply.rs b/tests/ui/neg_multiply.rs index 95b94e29517fa..b0f4e85c78e5d 100644 --- a/tests/ui/neg_multiply.rs +++ b/tests/ui/neg_multiply.rs @@ -53,3 +53,32 @@ fn main() { X * -1; // should be ok -1 * X; // should also be ok } + +fn float() { + let x = 0.0; + + x * -1.0; + //~^ neg_multiply + + -1.0 * x; + //~^ neg_multiply + + 100.0 + x * -1.0; + //~^ neg_multiply + + (100.0 + x) * -1.0; + //~^ neg_multiply + + -1.0 * 17.0; + //~^ neg_multiply + + 0.0 + 0.0 * -1.0; + //~^ neg_multiply + + 3.0_f32 as f64 * -1.0; + //~^ neg_multiply + (3.0_f32 as f64) * -1.0; + //~^ neg_multiply + + -1.0 * -1.0; // should be ok +} diff --git a/tests/ui/neg_multiply.stderr b/tests/ui/neg_multiply.stderr index 9efa5d3ba1f1d..2ef7e32ce05e1 100644 --- a/tests/ui/neg_multiply.stderr +++ b/tests/ui/neg_multiply.stderr @@ -49,5 +49,53 @@ error: this multiplication by -1 can be written more succinctly LL | (3_usize as i32) * -1; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `-(3_usize as i32)` -error: aborting due to 8 previous errors +error: this multiplication by -1 can be written more succinctly + --> tests/ui/neg_multiply.rs:60:5 + | +LL | x * -1.0; + | ^^^^^^^^ help: consider using: `-x` + +error: this multiplication by -1 can be written more succinctly + --> tests/ui/neg_multiply.rs:63:5 + | +LL | -1.0 * x; + | ^^^^^^^^ help: consider using: `-x` + +error: this multiplication by -1 can be written more succinctly + --> tests/ui/neg_multiply.rs:66:13 + | +LL | 100.0 + x * -1.0; + | ^^^^^^^^ help: consider using: `-x` + +error: this multiplication by -1 can be written more succinctly + --> tests/ui/neg_multiply.rs:69:5 + | +LL | (100.0 + x) * -1.0; + | ^^^^^^^^^^^^^^^^^^ help: consider using: `-(100.0 + x)` + +error: this multiplication by -1 can be written more succinctly + --> tests/ui/neg_multiply.rs:72:5 + | +LL | -1.0 * 17.0; + | ^^^^^^^^^^^ help: consider using: `-17.0` + +error: this multiplication by -1 can be written more succinctly + --> tests/ui/neg_multiply.rs:75:11 + | +LL | 0.0 + 0.0 * -1.0; + | ^^^^^^^^^^ help: consider using: `-0.0` + +error: this multiplication by -1 can be written more succinctly + --> tests/ui/neg_multiply.rs:78:5 + | +LL | 3.0_f32 as f64 * -1.0; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `-(3.0_f32 as f64)` + +error: this multiplication by -1 can be written more succinctly + --> tests/ui/neg_multiply.rs:80:5 + | +LL | (3.0_f32 as f64) * -1.0; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `-(3.0_f32 as f64)` + +error: aborting due to 16 previous errors From d71e7780c2514a6e082992e9de233f13c8c968c5 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 13 Mar 2025 12:30:13 +0530 Subject: [PATCH 0218/2248] validate_impl_object_ty: Add diagnostics for and ambiguous . --- .../crates/syntax/src/validation.rs | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index 14df485a9d40c..12894a2bda8f7 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -363,11 +363,40 @@ fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option { } fn validate_impl_object_ty(ty: ast::ImplTraitType, errors: &mut Vec) { - if ty.type_bound_list().map_or(0, |tbl| tbl.bounds().count()) == 0 { + let Some(bound_list) = ty.type_bound_list() else { errors.push(SyntaxError::new( "At least one trait must be specified", ty.syntax().text_range(), )); + return; + }; + + let bounds: Vec<_> = bound_list.bounds().collect(); + + if !bounds.iter().any(|b| !matches!(b.kind(), ast::TypeBoundKind::Lifetime(_))) { + errors.push(SyntaxError::new( + "At least one trait must be specified", + ty.syntax().text_range(), + )); + return; + } + + if bounds.len() == 1 { + return; + } + + let Some(preceding_token) = ty + .impl_token() + .and_then(|token| token.prev_token()) + .and_then(|prev| algo::skip_trivia_token(prev, Direction::Prev)) + else { + return; + }; + + if !matches!(preceding_token.kind(), T!['('] | T![<] | T![=]) + && matches!(preceding_token.kind(), T![&]) + { + errors.push(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())); } } From 289a87a64fd973551a8cca304bdfea9c7dcdd392 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 13 Mar 2025 12:30:51 +0530 Subject: [PATCH 0219/2248] add syntax validation test for ambiguous + --- ...261_dangling_impl_undeclared_lifetime.rast | 38 +++++++++++++++++++ .../0261_dangling_impl_undeclared_lifetime.rs | 1 + 2 files changed, 39 insertions(+) create mode 100644 src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rast create mode 100644 src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rast new file mode 100644 index 0000000000000..bd71c61cadaea --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rast @@ -0,0 +1,38 @@ +SOURCE_FILE@0..28 + FN@0..28 + FN_KW@0..2 "fn" + WHITESPACE@2..3 " " + NAME@3..4 + IDENT@3..4 "f" + PARAM_LIST@4..25 + L_PAREN@4..5 "(" + PARAM@5..24 + WILDCARD_PAT@5..6 + UNDERSCORE@5..6 "_" + COLON@6..7 ":" + WHITESPACE@7..8 " " + REF_TYPE@8..24 + AMP@8..9 "&" + IMPL_TRAIT_TYPE@9..24 + IMPL_KW@9..13 "impl" + WHITESPACE@13..14 " " + TYPE_BOUND_LIST@14..24 + TYPE_BOUND@14..16 + LIFETIME@14..16 + LIFETIME_IDENT@14..16 "'a" + WHITESPACE@16..17 " " + PLUS@17..18 "+" + WHITESPACE@18..19 " " + TYPE_BOUND@19..24 + PATH_TYPE@19..24 + PATH@19..24 + PATH_SEGMENT@19..24 + NAME_REF@19..24 + IDENT@19..24 "Sized" + R_PAREN@24..25 ")" + WHITESPACE@25..26 " " + BLOCK_EXPR@26..28 + STMT_LIST@26..28 + L_CURLY@26..27 "{" + R_CURLY@27..28 "}" +error 9..24: ambiguous `+` in a type diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs new file mode 100644 index 0000000000000..670a6f0ea7c4d --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs @@ -0,0 +1 @@ +fn f(_: &impl 'a + Sized) {} \ No newline at end of file From d59743101d06c026cee1edeac2683558dd6484c3 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 13 Mar 2025 12:31:08 +0530 Subject: [PATCH 0220/2248] add syntax validation test for &impl 'a --- .../validation/impl_trait_lifetime_only.rast | 29 +++++++++++++++++++ .../validation/impl_trait_lifetime_only.rs | 1 + 2 files changed, 30 insertions(+) create mode 100644 src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast create mode 100644 src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast new file mode 100644 index 0000000000000..98aa862bc889c --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast @@ -0,0 +1,29 @@ +SOURCE_FILE@0..20 + FN@0..20 + FN_KW@0..2 "fn" + WHITESPACE@2..3 " " + NAME@3..4 + IDENT@3..4 "f" + PARAM_LIST@4..17 + L_PAREN@4..5 "(" + PARAM@5..16 + WILDCARD_PAT@5..6 + UNDERSCORE@5..6 "_" + COLON@6..7 ":" + WHITESPACE@7..8 " " + REF_TYPE@8..16 + AMP@8..9 "&" + IMPL_TRAIT_TYPE@9..16 + IMPL_KW@9..13 "impl" + WHITESPACE@13..14 " " + TYPE_BOUND_LIST@14..16 + TYPE_BOUND@14..16 + LIFETIME@14..16 + LIFETIME_IDENT@14..16 "'a" + R_PAREN@16..17 ")" + WHITESPACE@17..18 " " + BLOCK_EXPR@18..20 + STMT_LIST@18..20 + L_CURLY@18..19 "{" + R_CURLY@19..20 "}" +error 9..16: At least one trait must be specified diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs new file mode 100644 index 0000000000000..5b18a54ef5a07 --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs @@ -0,0 +1 @@ +fn f(_: &impl 'a) {} \ No newline at end of file From 5b234c965d0bd3122b253933f0d2acf3ef74ae5d Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Fri, 21 Mar 2025 11:10:49 -0400 Subject: [PATCH 0221/2248] Change category to pedantic --- clippy_lints/src/attrs/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 7ba7b47661766..6f8a9a6ecbe3d 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -470,7 +470,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.85.0"] pub IGNORE_WITHOUT_REASON, - restriction, + pedantic, "ignored tests without messages" } From 8b5dd6747429ecbe7392b1b9e4993dfb0b3bf495 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Fri, 21 Mar 2025 20:56:53 +0530 Subject: [PATCH 0222/2248] change from krate to Option in syntax highlighting to incorporate modules which are not part of any crate --- .../crates/ide/src/syntax_highlighting.rs | 9 +++----- .../ide/src/syntax_highlighting/format.rs | 2 +- .../ide/src/syntax_highlighting/highlight.rs | 23 ++++++++++--------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs index 79e5baf4a77d3..ea0e01e536e42 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs @@ -222,10 +222,7 @@ pub(crate) fn highlight( }; let mut hl = highlights::Highlights::new(root.text_range()); - let krate = match sema.scope(&root) { - Some(it) => it.krate(), - None => return hl.to_vec(), - }; + let krate = sema.scope(&root).map(|it| it.krate()); traverse(&mut hl, &sema, config, InRealFile::new(file_id, &root), krate, range_to_highlight); hl.to_vec() } @@ -235,7 +232,7 @@ fn traverse( sema: &Semantics<'_, RootDatabase>, config: HighlightConfig, InRealFile { file_id, value: root }: InRealFile<&SyntaxNode>, - krate: hir::Crate, + krate: Option, range_to_highlight: TextRange, ) { let is_unlinked = sema.file_to_module_def(file_id).is_none(); @@ -498,7 +495,7 @@ fn string_injections( sema: &Semantics<'_, RootDatabase>, config: HighlightConfig, file_id: EditionedFileId, - krate: hir::Crate, + krate: Option, token: SyntaxToken, descended_token: &SyntaxToken, ) -> ControlFlow<()> { diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs index 00f5b3264cbac..3716dcfed006e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs @@ -15,7 +15,7 @@ use crate::{ pub(super) fn highlight_format_string( stack: &mut Highlights, sema: &hir::Semantics<'_, ide_db::RootDatabase>, - krate: hir::Crate, + krate: Option, string: &ast::String, expanded_string: &ast::String, edition: Edition, diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index fb25f0015585e..ef9fe93164a96 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -63,7 +63,7 @@ pub(super) fn token( pub(super) fn name_like( sema: &Semantics<'_, RootDatabase>, - krate: hir::Crate, + krate: Option, bindings_shadow_count: Option<&mut FxHashMap>, is_unsafe_node: &impl Fn(AstPtr>) -> bool, syntactic_name_ref_highlighting: bool, @@ -272,7 +272,7 @@ fn keyword(token: SyntaxToken, kind: SyntaxKind) -> Highlight { fn highlight_name_ref( sema: &Semantics<'_, RootDatabase>, - krate: hir::Crate, + krate: Option, bindings_shadow_count: Option<&mut FxHashMap>, binding_hash: &mut Option, is_unsafe_node: &impl Fn(AstPtr>) -> bool, @@ -401,9 +401,10 @@ fn highlight_name_ref( NameRefClass::ExternCrateShorthand { decl, krate: resolved_krate } => { let mut h = HlTag::Symbol(SymbolKind::Module).into(); - if resolved_krate != krate { - h |= HlMod::Library + if krate.as_ref().is_some_and(|krate| resolved_krate != *krate) { + h |= HlMod::Library; } + let is_public = decl.visibility(db) == hir::Visibility::Public; if is_public { h |= HlMod::Public @@ -431,7 +432,7 @@ fn highlight_name( bindings_shadow_count: Option<&mut FxHashMap>, binding_hash: &mut Option, is_unsafe_node: &impl Fn(AstPtr>) -> bool, - krate: hir::Crate, + krate: Option, name: ast::Name, edition: Edition, ) -> Highlight { @@ -476,7 +477,7 @@ fn calc_binding_hash(name: &hir::Name, shadow_count: u32) -> u64 { pub(super) fn highlight_def( sema: &Semantics<'_, RootDatabase>, - krate: hir::Crate, + krate: Option, def: Definition, edition: Edition, is_ref: bool, @@ -660,7 +661,7 @@ pub(super) fn highlight_def( }; let def_crate = def.krate(db); - let is_from_other_crate = def_crate != Some(krate); + let is_from_other_crate = def_crate != krate; let is_from_builtin_crate = def_crate.is_some_and(|def_crate| def_crate.is_builtin(db)); let is_builtin = matches!( def, @@ -681,7 +682,7 @@ pub(super) fn highlight_def( fn highlight_method_call_by_name_ref( sema: &Semantics<'_, RootDatabase>, - krate: hir::Crate, + krate: Option, name_ref: &ast::NameRef, is_unsafe_node: &impl Fn(AstPtr>) -> bool, ) -> Option { @@ -691,7 +692,7 @@ fn highlight_method_call_by_name_ref( fn highlight_method_call( sema: &Semantics<'_, RootDatabase>, - krate: hir::Crate, + krate: Option, method_call: &ast::MethodCallExpr, is_unsafe_node: &impl Fn(AstPtr>) -> bool, ) -> Option { @@ -718,7 +719,7 @@ fn highlight_method_call( } let def_crate = func.module(sema.db).krate(); - let is_from_other_crate = def_crate != krate; + let is_from_other_crate = krate.as_ref().map_or(false, |krate| def_crate != *krate); let is_from_builtin_crate = def_crate.is_builtin(sema.db); let is_public = func.visibility(sema.db) == hir::Visibility::Public; @@ -791,7 +792,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight { fn highlight_name_ref_by_syntax( name: ast::NameRef, sema: &Semantics<'_, RootDatabase>, - krate: hir::Crate, + krate: Option, is_unsafe_node: &impl Fn(AstPtr>) -> bool, ) -> Highlight { let default = HlTag::UnresolvedReference; From b1d9f0cc98de7c4cc052d3212a087dbb90ec7c5e Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Fri, 21 Mar 2025 20:57:21 +0530 Subject: [PATCH 0223/2248] add test for &raw const/&raw mut is not syntax-highlighted in all files --- .../test_data/highlight_issue_19357.html | 46 +++++++++++++++++++ .../ide/src/syntax_highlighting/tests.rs | 15 ++++++ 2 files changed, 61 insertions(+) create mode 100644 src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_19357.html diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_19357.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_19357.html new file mode 100644 index 0000000000000..36ed8c594f7e2 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_19357.html @@ -0,0 +1,46 @@ + + +
fn main() {
+    let x = &raw mut 5;
+}
+
\ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index 4b3fec1d2f7c9..59f2b90333d3a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -1420,3 +1420,18 @@ fn template() {} false, ); } + +#[test] +fn issue_19357() { + check_highlighting( + r#" +//- /foo.rs +fn main() { + let x = &raw mut 5; +} +//- /main.rs +"#, + expect_file!["./test_data/highlight_issue_19357.html"], + false, + ); +} From 993287b34960bfe7534d11e50c9f37cd0fdaadd5 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 21 Mar 2025 20:09:03 +0100 Subject: [PATCH 0224/2248] chore: Remove some unnecessary usage of `Semantics` --- src/tools/rust-analyzer/crates/hir/src/lib.rs | 12 ++++++ .../rust-analyzer/crates/hir/src/semantics.rs | 12 ------ .../replace_derive_with_manual_impl.rs | 2 +- .../crates/ide-completion/src/context.rs | 1 + .../ide-db/src/imports/import_assets.rs | 43 +++++++++---------- .../crates/ide-db/src/items_locator.rs | 23 +++++----- 6 files changed, 46 insertions(+), 47 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index ed0743def6bb2..1e58c076f225d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -599,6 +599,18 @@ impl Module { .collect() } + pub fn resolve_mod_path( + &self, + db: &dyn HirDatabase, + segments: impl IntoIterator, + ) -> Option> { + let items = self.id.resolver(db.upcast()).resolve_module_path_in_items( + db.upcast(), + &ModPath::from_segments(hir_def::path::PathKind::Plain, segments), + ); + Some(items.iter_items().map(|(item, _)| item.into())) + } + /// Fills `acc` with the module's diagnostics. pub fn diagnostics( self, diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 526fcd6e06c52..e5df574199f55 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -1651,18 +1651,6 @@ impl<'db> SemanticsImpl<'db> { Some(items.iter_items().map(|(item, _)| item.into())) } - pub fn resolve_mod_path_relative( - &self, - to: Module, - segments: impl IntoIterator, - ) -> Option> { - let items = to.id.resolver(self.db.upcast()).resolve_module_path_in_items( - self.db.upcast(), - &ModPath::from_segments(hir_def::path::PathKind::Plain, segments), - ); - Some(items.iter_items().map(|(item, _)| item.into())) - } - fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option { self.analyze(record_lit.syntax())?.resolve_variant(record_lit) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index e0693a7d5b67f..c5faf6d3e0126 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -73,7 +73,7 @@ pub(crate) fn replace_derive_with_manual_impl( let current_edition = current_crate.edition(ctx.db()); let found_traits = items_locator::items_with_name( - &ctx.sema, + ctx.db(), current_crate, NameToImport::exact_case_sensitive(path.segments().last()?.to_string()), items_locator::AssocSearchMode::Exclude, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index aa0b6060f6f1d..304379603199d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -823,6 +823,7 @@ impl<'a> CompletionContext<'a> { exclude_flyimport .extend(exclude_traits.iter().map(|&t| (t.into(), AutoImportExclusionType::Always))); + // FIXME: This should be part of `CompletionAnalysis` / `expand_and_analyze` let complete_semicolon = if config.add_semicolon_to_unit { let inside_closure_ret = token.parent_ancestors().try_for_each(|ancestor| { match_ast! { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index 0fc287c57e7c3..650c957ca4581 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -273,12 +273,13 @@ impl ImportAssets { Some(it) => it, None => return >::default().into_iter(), }; + let db = sema.db; let krate = self.module_with_candidate.krate(); let scope_definitions = self.scope_definitions(sema); let mod_path = |item| { get_mod_path( - sema.db, - item_for_path_search(sema.db, item)?, + db, + item_for_path_search(db, item)?, &self.module_with_candidate, prefixed, cfg, @@ -288,7 +289,7 @@ impl ImportAssets { match &self.import_candidate { ImportCandidate::Path(path_candidate) => path_applicable_imports( - sema, + db, &scope, krate, path_candidate, @@ -297,7 +298,7 @@ impl ImportAssets { ), ImportCandidate::TraitAssocItem(trait_candidate) | ImportCandidate::TraitMethod(trait_candidate) => trait_applicable_items( - sema, + db, krate, &scope, trait_candidate, @@ -325,7 +326,7 @@ impl ImportAssets { } fn path_applicable_imports( - sema: &Semantics<'_, RootDatabase>, + db: &RootDatabase, scope: &SemanticsScope<'_>, current_crate: Crate, path_candidate: &PathImportCandidate, @@ -337,7 +338,7 @@ fn path_applicable_imports( match &*path_candidate.qualifier { [] => { items_locator::items_with_name( - sema, + db, current_crate, path_candidate.name.clone(), // FIXME: we could look up assoc items by the input and propose those in completion, @@ -365,7 +366,7 @@ fn path_applicable_imports( // what follows // FIXME: This doesn't handle visibility [first_qsegment, qualifier_rest @ ..] => items_locator::items_with_name( - sema, + db, current_crate, NameToImport::Exact(first_qsegment.as_str().to_owned(), true), AssocSearchMode::Exclude, @@ -374,7 +375,7 @@ fn path_applicable_imports( // we found imports for `first_qsegment`, now we need to filter these imports by whether // they result in resolving the rest of the path successfully validate_resolvable( - sema, + db, scope, mod_path, scope_filter, @@ -391,7 +392,7 @@ fn path_applicable_imports( /// Validates and builds an import for `resolved_qualifier` if the `unresolved_qualifier` appended /// to it resolves and there is a validate `candidate` after that. fn validate_resolvable( - sema: &Semantics<'_, RootDatabase>, + db: &RootDatabase, scope: &SemanticsScope<'_>, mod_path: impl Fn(ItemInNs) -> Option, scope_filter: impl Fn(ItemInNs) -> bool, @@ -406,8 +407,8 @@ fn validate_resolvable( if !unresolved_qualifier.is_empty() { match resolved_qualifier { ItemInNs::Types(ModuleDef::Module(module)) => { - adjusted_resolved_qualifier = sema - .resolve_mod_path_relative(module, unresolved_qualifier.iter().cloned())? + adjusted_resolved_qualifier = module + .resolve_mod_path(db, unresolved_qualifier.iter().cloned())? .next()?; } // can't resolve multiple segments for non-module item path bases @@ -424,7 +425,7 @@ fn validate_resolvable( let ty = match qualifier { ModuleDef::Module(module) => { return items_locator::items_with_name_in_module( - sema, + db, module, candidate.clone(), AssocSearchMode::Exclude, @@ -439,17 +440,17 @@ fn validate_resolvable( ModuleDef::Trait(_) => return None, // FIXME ModuleDef::TraitAlias(_) => return None, - ModuleDef::TypeAlias(alias) => alias.ty(sema.db), - ModuleDef::BuiltinType(builtin) => builtin.ty(sema.db), - ModuleDef::Adt(adt) => adt.ty(sema.db), + ModuleDef::TypeAlias(alias) => alias.ty(db), + ModuleDef::BuiltinType(builtin) => builtin.ty(db), + ModuleDef::Adt(adt) => adt.ty(db), _ => return None, }; - ty.iterate_path_candidates(sema.db, scope, &FxHashSet::default(), None, None, |assoc| { + ty.iterate_path_candidates(db, scope, &FxHashSet::default(), None, None, |assoc| { // FIXME: Support extra trait imports - if assoc.container_or_implemented_trait(sema.db).is_some() { + if assoc.container_or_implemented_trait(db).is_some() { return None; } - let name = assoc.name(sema.db)?; + let name = assoc.name(db)?; let is_match = match candidate { NameToImport::Prefix(text, true) => name.as_str().starts_with(text), NameToImport::Prefix(text, false) => { @@ -495,7 +496,7 @@ fn item_for_path_search_assoc(db: &RootDatabase, assoc_item: AssocItem) -> Optio } fn trait_applicable_items( - sema: &Semantics<'_, RootDatabase>, + db: &RootDatabase, current_crate: Crate, scope: &SemanticsScope<'_>, trait_candidate: &TraitImportCandidate, @@ -505,15 +506,13 @@ fn trait_applicable_items( ) -> FxIndexSet { let _p = tracing::info_span!("ImportAssets::trait_applicable_items").entered(); - let db = sema.db; - let inherent_traits = trait_candidate.receiver_ty.applicable_inherent_traits(db); let env_traits = trait_candidate.receiver_ty.env_traits(db); let related_traits = inherent_traits.chain(env_traits).collect::>(); let mut required_assoc_items = FxHashSet::default(); let mut trait_candidates: FxHashSet<_> = items_locator::items_with_name( - sema, + db, current_crate, trait_candidate.assoc_item_name.clone(), AssocSearchMode::AssocItemsOnly, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs index 80881829800e5..7a543d64e27f4 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs @@ -5,7 +5,7 @@ use std::ops::ControlFlow; use either::Either; -use hir::{Crate, ItemInNs, Module, Semantics, import_map}; +use hir::{Crate, ItemInNs, Module, import_map}; use crate::{ RootDatabase, @@ -20,13 +20,13 @@ pub use import_map::AssocSearchMode; // FIXME: Do callbacks instead to avoid allocations. /// Searches for importable items with the given name in the crate and its dependencies. -pub fn items_with_name<'a>( - sema: &'a Semantics<'_, RootDatabase>, +pub fn items_with_name( + db: &RootDatabase, krate: Crate, name: NameToImport, assoc_item_search: AssocSearchMode, -) -> impl Iterator + 'a { - let _p = tracing::info_span!("items_with_name", name = name.text(), assoc_item_search = ?assoc_item_search, crate = ?krate.display_name(sema.db).map(|name| name.to_string())) +) -> impl Iterator { + let _p = tracing::info_span!("items_with_name", name = name.text(), assoc_item_search = ?assoc_item_search, crate = ?krate.display_name(db).map(|name| name.to_string())) .entered(); let prefix = matches!(name, NameToImport::Prefix(..)); @@ -68,12 +68,12 @@ pub fn items_with_name<'a>( } }; - find_items(sema, krate, local_query, external_query) + find_items(db, krate, local_query, external_query) } /// Searches for importable items with the given name in the crate and its dependencies. pub fn items_with_name_in_module( - sema: &Semantics<'_, RootDatabase>, + db: &RootDatabase, module: Module, name: NameToImport, assoc_item_search: AssocSearchMode, @@ -110,7 +110,7 @@ pub fn items_with_name_in_module( local_query } }; - local_query.search(&[sema.db.module_symbols(module)], |local_candidate| { + local_query.search(&[db.module_symbols(module)], |local_candidate| { cb(match local_candidate.def { hir::ModuleDef::Macro(macro_def) => ItemInNs::Macros(macro_def), def => ItemInNs::from(def), @@ -118,14 +118,13 @@ pub fn items_with_name_in_module( }) } -fn find_items<'a>( - sema: &'a Semantics<'_, RootDatabase>, +fn find_items( + db: &RootDatabase, krate: Crate, local_query: symbol_index::Query, external_query: import_map::Query, -) -> impl Iterator + 'a { +) -> impl Iterator { let _p = tracing::info_span!("find_items").entered(); - let db = sema.db; // NOTE: `external_query` includes `assoc_item_search`, so we don't need to // filter on our own. From 26cfa6f819e10fa597766d8c5549b86e503ff288 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Fri, 21 Mar 2025 22:36:50 +0800 Subject: [PATCH 0225/2248] 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 9a6f889b036d898c9d0d0ee4172e0a1ead5bf97e Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Sat, 22 Mar 2025 12:55:00 +0900 Subject: [PATCH 0226/2248] fix: Properly calculate the layouts of tuple ptrs whose last fields are DST --- src/tools/rust-analyzer/crates/hir-ty/src/layout.rs | 9 +++++++++ .../rust-analyzer/crates/hir-ty/src/layout/tests.rs | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index 0cb868d273f04..81aa16bfdc729 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -388,6 +388,15 @@ fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty { None => pointee, } } + TyKind::Tuple(_, subst) => { + if let Some(last_field_ty) = + subst.iter(Interner).last().and_then(|arg| arg.ty(Interner)) + { + struct_tail_erasing_lifetimes(db, last_field_ty.clone()) + } else { + pointee + } + } _ => pointee, } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index f671b30380724..aac4e94ee3687 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs @@ -468,6 +468,16 @@ fn tuple() { } } +#[test] +fn tuple_ptr_with_dst_tail() { + size_and_align!( + struct Goal(*const ([u8],)); + ); + size_and_align!( + struct Goal(*const (u128, [u8])); + ); +} + #[test] fn non_zero_and_non_null() { size_and_align! { From efda66829eb21a3b8485a6e9e77e81174b938f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felici=C3=A1n=20N=C3=A9meth?= Date: Sat, 15 Mar 2025 08:14:20 +0100 Subject: [PATCH 0227/2248] Speed up resolving "Generate delegate method" assist (part 1) Fix #19322 Sometimes there are 185 "Generate delegate" assists with the same assist_id and asssist_kind. This commit introduces and additional differentiator: assist_subtype. Therefore, when the LSP client sends an assist resolve request, rust-analyzer only need to compute edits for a single assist instead of 185. --- .../src/handlers/generate_delegate_methods.rs | 5 ++--- .../src/handlers/generate_delegate_trait.rs | 8 ++++++-- src/tools/rust-analyzer/crates/ide-db/src/assists.rs | 8 ++++++-- .../crates/rust-analyzer/src/handlers/request.rs | 12 ++++++++++-- .../crates/rust-analyzer/src/lsp/to_proto.rs | 7 ++++++- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs index 750f160ec2d23..4794bf541fa7a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -92,19 +92,18 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' }); } methods.sort_by(|(a, _), (b, _)| a.cmp(b)); - for (name, method) in methods { + for (index, (name, method)) in methods.into_iter().enumerate() { let adt = ast::Adt::Struct(strukt.clone()); let name = name.display(ctx.db(), current_edition).to_string(); // if `find_struct_impl` returns None, that means that a function named `name` already exists. let Some(impl_def) = find_struct_impl(ctx, &adt, std::slice::from_ref(&name)) else { continue; }; - let field = make::ext::field_from_idents(["self", &field_name])?; acc.add_group( &GroupLabel("Generate delegate methods…".to_owned()), - AssistId("generate_delegate_methods", AssistKind::Generate), + AssistId("generate_delegate_methods", AssistKind::Generate, Some(index)), format!("Generate delegate for `{field_name}.{name}()`",), target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs index 5c39214617e49..53a06ba1c6c18 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -201,7 +201,7 @@ impl Struct { pub(crate) fn delegate(&self, field: Field, acc: &mut Assists, ctx: &AssistContext<'_>) { let db = ctx.db(); - for delegee in &field.impls { + for (index, delegee) in field.impls.iter().enumerate() { let trait_ = match delegee { Delegee::Bound(b) => b, Delegee::Impls(i, _) => i, @@ -229,7 +229,11 @@ impl Struct { acc.add_group( &GroupLabel(format!("Generate delegate trait impls for field `{}`", field.name)), - AssistId("generate_delegate_trait", ide_db::assists::AssistKind::Generate), + AssistId( + "generate_delegate_trait", + ide_db::assists::AssistKind::Generate, + Some(index), + ), format!("Generate delegate trait impl `{}` for `{}`", signature, field.name), field.range, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/assists.rs b/src/tools/rust-analyzer/crates/ide-db/src/assists.rs index 1c40685ebb130..7868f6148e5a6 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/assists.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/assists.rs @@ -105,7 +105,7 @@ impl FromStr for AssistKind { /// Unique identifier of the assist, should not be shown to the user /// directly. #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct AssistId(pub &'static str, pub AssistKind); +pub struct AssistId(pub &'static str, pub AssistKind, pub Option); /// A way to control how many assist to resolve during the assist resolution. /// When an assist is resolved, its edits are calculated that might be costly to always do by default. @@ -128,6 +128,8 @@ pub struct SingleResolve { pub assist_id: String, // The kind of the assist. pub assist_kind: AssistKind, + /// Subtype of the assist. When many assists have the same id, it differentiates among them. + pub assist_subtype: Option, } impl AssistResolveStrategy { @@ -136,7 +138,9 @@ impl AssistResolveStrategy { AssistResolveStrategy::None => false, AssistResolveStrategy::All => true, AssistResolveStrategy::Single(single_resolve) => { - single_resolve.assist_id == id.0 && single_resolve.assist_kind == id.1 + single_resolve.assist_id == id.0 + && single_resolve.assist_kind == id.1 + && single_resolve.assist_subtype == id.2 } } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index ef1cc28d15a39..ec8b324aac3cf 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -1568,13 +1568,21 @@ pub(crate) fn handle_code_action_resolve( fn parse_action_id(action_id: &str) -> anyhow::Result<(usize, SingleResolve), String> { let id_parts = action_id.split(':').collect::>(); match id_parts.as_slice() { - [assist_id_string, assist_kind_string, index_string] => { + [assist_id_string, assist_kind_string, index_string, subtype_str] => { let assist_kind: AssistKind = assist_kind_string.parse()?; let index: usize = match index_string.parse() { Ok(index) => index, Err(e) => return Err(format!("Incorrect index string: {e}")), }; - Ok((index, SingleResolve { assist_id: assist_id_string.to_string(), assist_kind })) + let assist_subtype = subtype_str.parse::().ok(); + Ok(( + index, + SingleResolve { + assist_id: assist_id_string.to_string(), + assist_kind, + assist_subtype, + }, + )) } _ => Err("Action id contains incorrect number of segments".to_owned()), } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index 8ea2d46797730..c30ee0fee19d5 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -1514,7 +1514,12 @@ pub(crate) fn code_action( (Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?), (None, Some((index, code_action_params, version))) => { res.data = Some(lsp_ext::CodeActionData { - id: format!("{}:{}:{index}", assist.id.0, assist.id.1.name()), + id: format!( + "{}:{}:{index}:{}", + assist.id.0, + assist.id.1.name(), + assist.id.2.map(|x| x.to_string()).unwrap_or("".to_owned()) + ), code_action_params, version, }); From 2e3e75fae963910ffa8afebea680408d76f3a75f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felici=C3=A1n=20N=C3=A9meth?= Date: Sat, 15 Mar 2025 08:42:30 +0100 Subject: [PATCH 0228/2248] Speed up resolving "Generate delegate method" assist (part 2) Make it compile by adding a `None` subtype to rest of the AssistId instantiations. --- .../ide-assists/src/handlers/add_braces.rs | 4 +- .../add_explicit_enum_discriminant.rs | 8 +- .../src/handlers/add_explicit_type.rs | 4 +- .../src/handlers/add_label_to_loop.rs | 4 +- .../src/handlers/add_lifetime_to_type.rs | 37 ++--- .../src/handlers/add_missing_impl_members.rs | 4 +- .../src/handlers/add_missing_match_arms.rs | 4 +- .../src/handlers/add_return_type.rs | 4 +- .../src/handlers/add_turbo_fish.rs | 6 +- .../src/handlers/apply_demorgan.rs | 6 +- .../ide-assists/src/handlers/auto_import.rs | 4 +- .../src/handlers/bind_unused_param.rs | 8 +- .../src/handlers/change_visibility.rs | 8 +- .../src/handlers/convert_bool_then.rs | 6 +- .../src/handlers/convert_bool_to_enum.rs | 4 +- .../src/handlers/convert_closure_to_fn.rs | 10 +- .../src/handlers/convert_comment_block.rs | 6 +- .../convert_comment_from_or_to_doc.rs | 6 +- .../src/handlers/convert_for_to_while_let.rs | 4 +- .../src/handlers/convert_from_to_tryfrom.rs | 4 +- .../src/handlers/convert_integer_literal.rs | 4 +- .../src/handlers/convert_into_to_from.rs | 4 +- .../handlers/convert_iter_for_each_to_for.rs | 6 +- .../src/handlers/convert_let_else_to_match.rs | 4 +- .../src/handlers/convert_match_to_let_else.rs | 4 +- .../convert_named_struct_to_tuple_struct.rs | 4 +- .../convert_nested_function_to_closure.rs | 4 +- .../src/handlers/convert_to_guarded_return.rs | 6 +- .../convert_tuple_return_type_to_struct.rs | 4 +- .../convert_tuple_struct_to_named_struct.rs | 4 +- ...ert_two_arm_bool_match_to_matches_macro.rs | 4 +- .../src/handlers/convert_while_to_loop.rs | 4 +- .../handlers/destructure_struct_binding.rs | 4 +- .../src/handlers/destructure_tuple_binding.rs | 6 +- .../src/handlers/desugar_doc_comment.rs | 4 +- .../src/handlers/expand_glob_import.rs | 6 +- .../src/handlers/expand_rest_pattern.rs | 4 +- .../extract_expressions_from_format_string.rs | 1 + .../src/handlers/extract_function.rs | 2 +- .../src/handlers/extract_module.rs | 4 +- .../extract_struct_from_enum_variant.rs | 4 +- .../src/handlers/extract_type_alias.rs | 4 +- .../src/handlers/extract_variable.rs | 4 +- .../src/handlers/fix_visibility.rs | 6 +- .../ide-assists/src/handlers/flip_binexpr.rs | 4 +- .../ide-assists/src/handlers/flip_comma.rs | 4 +- .../src/handlers/flip_or_pattern.rs | 19 +-- .../src/handlers/flip_trait_bound.rs | 4 +- .../src/handlers/generate_constant.rs | 19 +-- .../generate_default_from_enum_variant.rs | 4 +- .../src/handlers/generate_default_from_new.rs | 2 +- .../src/handlers/generate_deref.rs | 6 +- .../src/handlers/generate_derive.rs | 4 +- .../generate_documentation_template.rs | 6 +- .../src/handlers/generate_enum_is_method.rs | 4 +- .../generate_enum_projection_method.rs | 4 +- .../src/handlers/generate_enum_variant.rs | 27 ++- .../src/handlers/generate_fn_type_alias.rs | 4 +- .../handlers/generate_from_impl_for_enum.rs | 6 +- .../src/handlers/generate_function.rs | 4 +- .../src/handlers/generate_getter_or_setter.rs | 6 +- .../ide-assists/src/handlers/generate_impl.rs | 6 +- .../handlers/generate_is_empty_from_len.rs | 4 +- .../src/handlers/generate_mut_trait_impl.rs | 4 +- .../ide-assists/src/handlers/generate_new.rs | 4 +- .../src/handlers/generate_trait_from_impl.rs | 2 +- .../ide-assists/src/handlers/inline_call.rs | 29 ++-- .../src/handlers/inline_const_as_literal.rs | 4 +- .../src/handlers/inline_local_variable.rs | 4 +- .../ide-assists/src/handlers/inline_macro.rs | 4 +- .../src/handlers/inline_type_alias.rs | 6 +- .../src/handlers/into_to_qualified_from.rs | 7 +- .../src/handlers/introduce_named_lifetime.rs | 6 +- .../introduce_named_type_parameter.rs | 4 +- .../ide-assists/src/handlers/invert_if.rs | 4 +- .../ide-assists/src/handlers/merge_imports.rs | 87 +++++----- .../src/handlers/merge_match_arms.rs | 4 +- .../src/handlers/merge_nested_if.rs | 37 ++--- .../ide-assists/src/handlers/move_bounds.rs | 4 +- .../src/handlers/move_const_to_impl.rs | 2 +- .../src/handlers/move_from_mod_rs.rs | 7 +- .../ide-assists/src/handlers/move_guard.rs | 6 +- .../src/handlers/move_module_to_file.rs | 4 +- .../src/handlers/move_to_mod_rs.rs | 7 +- .../src/handlers/normalize_import.rs | 13 +- .../src/handlers/number_representation.rs | 6 +- .../src/handlers/promote_local_to_const.rs | 7 +- .../src/handlers/pull_assignment_up.rs | 4 +- .../src/handlers/qualify_method_call.rs | 4 +- .../ide-assists/src/handlers/qualify_path.rs | 4 +- .../ide-assists/src/handlers/raw_string.rs | 10 +- .../ide-assists/src/handlers/remove_dbg.rs | 4 +- .../ide-assists/src/handlers/remove_mut.rs | 25 ++- .../src/handlers/remove_parentheses.rs | 4 +- .../src/handlers/remove_unused_imports.rs | 4 +- .../src/handlers/remove_unused_param.rs | 5 +- .../src/handlers/reorder_fields.rs | 4 +- .../src/handlers/reorder_impl_items.rs | 4 +- .../src/handlers/replace_arith_op.rs | 4 +- .../replace_derive_with_manual_impl.rs | 157 +++++++++--------- .../src/handlers/replace_if_let_with_match.rs | 6 +- .../replace_is_method_with_if_let_method.rs | 4 +- .../src/handlers/replace_let_with_if_let.rs | 4 +- .../src/handlers/replace_method_eager_lazy.rs | 6 +- .../replace_named_generic_with_impl.rs | 4 +- .../replace_qualified_name_with_use.rs | 4 +- .../src/handlers/replace_string_with_char.rs | 6 +- .../handlers/replace_try_expr_with_match.rs | 7 +- .../replace_turbofish_with_explicit_type.rs | 6 +- .../ide-assists/src/handlers/sort_items.rs | 25 ++- .../ide-assists/src/handlers/split_import.rs | 4 +- .../ide-assists/src/handlers/term_search.rs | 4 +- .../src/handlers/toggle_async_sugar.rs | 9 +- .../ide-assists/src/handlers/toggle_ignore.rs | 6 +- .../src/handlers/toggle_macro_delimiter.rs | 4 +- .../src/handlers/unmerge_match_arm.rs | 4 +- .../ide-assists/src/handlers/unmerge_use.rs | 4 +- .../src/handlers/unnecessary_async.rs | 4 +- .../src/handlers/unqualify_method_call.rs | 4 +- .../ide-assists/src/handlers/unwrap_block.rs | 5 +- .../src/handlers/unwrap_return_type.rs | 4 +- .../ide-assists/src/handlers/unwrap_tuple.rs | 4 +- .../src/handlers/wrap_return_type.rs | 4 +- .../src/handlers/wrap_unwrap_cfg_attr.rs | 8 +- .../crates/ide-assists/src/tests.rs | 18 ++ .../crates/ide-db/src/assists.rs | 30 ++++ .../trait_impl_redundant_assoc_item.rs | 4 +- .../src/handlers/typed_hole.rs | 4 +- .../src/handlers/unresolved_field.rs | 10 +- .../src/handlers/unresolved_method.rs | 6 +- .../src/handlers/unused_variables.rs | 4 +- .../crates/ide-diagnostics/src/lib.rs | 4 +- src/tools/rust-analyzer/crates/ide/src/ssr.rs | 8 +- 133 files changed, 532 insertions(+), 570 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs index f9124d2d46551..d8db7cc761ae6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs @@ -3,7 +3,7 @@ use syntax::{ ast::{self, edit_in_place::Indent, syntax_factory::SyntaxFactory}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: add_braces // @@ -32,7 +32,7 @@ pub(crate) fn add_braces(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( let (expr_type, expr) = get_replacement_node(ctx)?; acc.add( - AssistId("add_braces", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("add_braces"), match expr_type { ParentType::ClosureExpr => "Add braces to closure body", ParentType::MatchArmExpr => "Add braces to arm expression", diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs index c8a6f9e65caf5..10b0879e6364d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs @@ -1,9 +1,5 @@ use hir::Semantics; -use ide_db::{ - RootDatabase, - assists::{AssistId, AssistKind}, - source_change::SourceChangeBuilder, -}; +use ide_db::{RootDatabase, assists::AssistId, source_change::SourceChangeBuilder}; use syntax::{AstNode, ast}; use crate::{AssistContext, Assists}; @@ -53,7 +49,7 @@ pub(crate) fn add_explicit_enum_discriminant( } acc.add( - AssistId("add_explicit_enum_discriminant", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("add_explicit_enum_discriminant"), "Add explicit enum discriminants", enum_node.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_type.rs index 8bc285614e039..35a65cc309111 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_type.rs @@ -2,7 +2,7 @@ use hir::HirDisplay; use ide_db::syntax_helpers::node_ext::walk_ty; use syntax::ast::{self, AstNode, LetStmt, Param}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: add_explicit_type // @@ -71,7 +71,7 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> O let inferred_type = ty.display_source_code(ctx.db(), module.into(), false).ok()?; acc.add( - AssistId("add_explicit_type", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("add_explicit_type"), format!("Insert explicit type `{inferred_type}`"), pat_range, |builder| match ascribed_ty { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs index fc10501543b47..d2b903447133f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs @@ -4,7 +4,7 @@ use syntax::{ ast::{self, AstNode, HasLoopBody}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: add_label_to_loop // @@ -35,7 +35,7 @@ pub(crate) fn add_label_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>) -> O } acc.add( - AssistId("add_label_to_loop", AssistKind::Generate), + AssistId::generate("add_label_to_loop"), "Add Label", loop_expr.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs index c3e05b8fb0839..dcdc7ea9cdced 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs @@ -1,6 +1,6 @@ use syntax::ast::{self, AstNode, HasGenericParams, HasName}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: add_lifetime_to_type // @@ -37,31 +37,26 @@ pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext<'_>) - let ref_types = fetch_borrowed_types(&node)?; let target = node.syntax().text_range(); - acc.add( - AssistId("add_lifetime_to_type", AssistKind::Generate), - "Add lifetime", - target, - |builder| { - match node.generic_param_list() { - Some(gen_param) => { - if let Some(left_angle) = gen_param.l_angle_token() { - builder.insert(left_angle.text_range().end(), "'a, "); - } + acc.add(AssistId::generate("add_lifetime_to_type"), "Add lifetime", target, |builder| { + match node.generic_param_list() { + Some(gen_param) => { + if let Some(left_angle) = gen_param.l_angle_token() { + builder.insert(left_angle.text_range().end(), "'a, "); } - None => { - if let Some(name) = node.name() { - builder.insert(name.syntax().text_range().end(), "<'a>"); - } + } + None => { + if let Some(name) = node.name() { + builder.insert(name.syntax().text_range().end(), "<'a>"); } } + } - for ref_type in ref_types { - if let Some(amp_token) = ref_type.amp_token() { - builder.insert(amp_token.text_range().end(), "'a "); - } + for ref_type in ref_types { + if let Some(amp_token) = ref_type.amp_token() { + builder.insert(amp_token.text_range().end(), "'a "); } - }, - ) + } + }) } fn fetch_borrowed_types(node: &ast::Adt) -> Option> { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 6b8a877756982..65bd9141bd238 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -5,7 +5,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, utils::{ DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items, @@ -146,7 +146,7 @@ fn add_missing_impl_members_inner( } let target = impl_def.syntax().text_range(); - acc.add(AssistId(assist_id, AssistKind::QuickFix), label, target, |edit| { + acc.add(AssistId::quick_fix(assist_id), label, target, |edit| { let new_impl_def = edit.make_mut(impl_def.clone()); let first_new_item = add_trait_assoc_items_to_impl( &ctx.sema, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 78f3e26796d60..4cabf4b0048bf 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -12,7 +12,7 @@ use syntax::ast::edit_in_place::Indent; use syntax::ast::syntax_factory::SyntaxFactory; use syntax::ast::{self, AstNode, MatchArmList, MatchExpr, Pat, make}; -use crate::{AssistContext, AssistId, AssistKind, Assists, utils}; +use crate::{AssistContext, AssistId, Assists, utils}; // Assist: add_missing_match_arms // @@ -205,7 +205,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) } acc.add( - AssistId("add_missing_match_arms", AssistKind::QuickFix), + AssistId::quick_fix("add_missing_match_arms"), "Fill match arms", ctx.sema.original_range(match_expr.syntax()).range, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_return_type.rs index 0c745af0ecab7..a7104ce068da8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_return_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_return_type.rs @@ -1,7 +1,7 @@ use hir::HirDisplay; use syntax::{AstNode, SyntaxKind, SyntaxToken, TextRange, TextSize, ast, match_ast}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: add_return_type // @@ -25,7 +25,7 @@ pub(crate) fn add_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt let ty = ty.display_source_code(ctx.db(), module.into(), true).ok()?; acc.add( - AssistId("add_return_type", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("add_return_type"), match fn_type { FnType::Function => "Add this function's return type", FnType::Closure { .. } => "Add this closure's return type", diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs index 372e0dad3cfad..4901962760176 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs @@ -7,7 +7,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; @@ -89,7 +89,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti let_stmt.pat()?; acc.add( - AssistId("add_type_ascription", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("add_type_ascription"), "Add `: _` before assignment operator", ident.text_range(), |builder| { @@ -135,7 +135,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti .count(); acc.add( - AssistId("add_turbo_fish", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("add_turbo_fish"), "Add `::<>`", ident.text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs index e584c709a94a4..daab992276836 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs @@ -17,7 +17,7 @@ use syntax::{ syntax_editor::{Position, SyntaxEditor}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists, utils::invert_boolean_expression}; +use crate::{AssistContext, AssistId, Assists, utils::invert_boolean_expression}; // Assist: apply_demorgan // @@ -107,7 +107,7 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti acc.add_group( &GroupLabel("Apply De Morgan's law".to_owned()), - AssistId("apply_demorgan", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("apply_demorgan"), "Apply De Morgan's law", op_range, |builder| { @@ -190,7 +190,7 @@ pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_> let label = format!("Apply De Morgan's law to `Iterator::{}`", name.text().as_str()); acc.add_group( &GroupLabel("Apply De Morgan's law".to_owned()), - AssistId("apply_demorgan_iterator", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("apply_demorgan_iterator"), label, op_range, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs index f491b9375c33b..2c7532d919adc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs @@ -10,7 +10,7 @@ use ide_db::{ }; use syntax::{AstNode, Edition, NodeOrToken, SyntaxElement, ast}; -use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; +use crate::{AssistContext, AssistId, Assists, GroupLabel}; // Feature: Auto Import // @@ -127,7 +127,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< let import_path = import.import_path; let (assist_id, import_name) = - (AssistId("auto_import", AssistKind::QuickFix), import_path.display(ctx.db(), edition)); + (AssistId::quick_fix("auto_import"), import_path.display(ctx.db(), edition)); acc.add_group( &group_label, assist_id, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bind_unused_param.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bind_unused_param.rs index 5048ff5163abf..dadc38e6f9677 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bind_unused_param.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bind_unused_param.rs @@ -1,9 +1,5 @@ use crate::assist_context::{AssistContext, Assists}; -use ide_db::{ - LineIndexDatabase, - assists::{AssistId, AssistKind}, - defs::Definition, -}; +use ide_db::{LineIndexDatabase, assists::AssistId, defs::Definition}; use syntax::{ AstNode, ast::{self, edit_in_place::Indent}, @@ -42,7 +38,7 @@ pub(crate) fn bind_unused_param(acc: &mut Assists, ctx: &AssistContext<'_>) -> O let r_curly_range = stmt_list.r_curly_token()?.text_range(); acc.add( - AssistId("bind_unused_param", AssistKind::QuickFix), + AssistId::quick_fix("bind_unused_param"), format!("Bind as `let _ = {ident_pat};`"), param.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs index 8af9121fc8d13..9b9f0c4522ed2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs @@ -8,7 +8,7 @@ use syntax::{ ast::{self, HasName, HasVisibility}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists, utils::vis_offset}; +use crate::{AssistContext, AssistId, Assists, utils::vis_offset}; // Assist: change_visibility // @@ -76,7 +76,7 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { }; acc.add( - AssistId("change_visibility", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("change_visibility"), "Change visibility to pub(crate)", target, |edit| { @@ -112,7 +112,7 @@ fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> { if vis.syntax().text() == "pub" { let target = vis.syntax().text_range(); return acc.add( - AssistId("change_visibility", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("change_visibility"), "Change Visibility to pub(crate)", target, |edit| { @@ -123,7 +123,7 @@ fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> { if vis.syntax().text() == "pub(crate)" { let target = vis.syntax().text_range(); return acc.add( - AssistId("change_visibility", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("change_visibility"), "Change visibility to pub", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs index c4a2189f696ea..f3210a625b2f8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs @@ -14,7 +14,7 @@ use syntax::{ }; use crate::{ - AssistContext, AssistId, AssistKind, Assists, + AssistContext, AssistId, Assists, utils::{invert_boolean_expression, unwrap_trivial_block}, }; @@ -73,7 +73,7 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext<'_> let target = expr.syntax().text_range(); acc.add( - AssistId("convert_if_to_bool_then", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_if_to_bool_then"), "Convert `if` expression to `bool::then` call", target, |builder| { @@ -181,7 +181,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_> let target = mcall.syntax().text_range(); acc.add( - AssistId("convert_bool_then_to_if", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_bool_then_to_if"), "Convert `bool::then` call to `if`", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs index 8200ad75df5ff..e3ca28d64d83a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs @@ -3,7 +3,7 @@ use hir::ModuleDef; use ide_db::text_edit::TextRange; use ide_db::{ FxHashSet, - assists::{AssistId, AssistKind}, + assists::AssistId, defs::Definition, helpers::mod_path_to_ast, imports::insert_use::{ImportScope, insert_use}, @@ -62,7 +62,7 @@ pub(crate) fn convert_bool_to_enum(acc: &mut Assists, ctx: &AssistContext<'_>) - let target = name.syntax().text_range(); acc.add( - AssistId("convert_bool_to_enum", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_bool_to_enum"), "Convert boolean to enum", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs index c11a411fb9c2c..fbd925e55ebc9 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs @@ -1,12 +1,8 @@ use either::Either; use hir::{CaptureKind, ClosureCapture, FileRangeWrapper, HirDisplay}; use ide_db::{ - FxHashSet, - assists::{AssistId, AssistKind}, - base_db::SourceDatabase, - defs::Definition, - search::FileReferenceNode, - source_change::SourceChangeBuilder, + FxHashSet, assists::AssistId, base_db::SourceDatabase, defs::Definition, + search::FileReferenceNode, source_change::SourceChangeBuilder, }; use stdx::format_to; use syntax::{ @@ -147,7 +143,7 @@ pub(crate) fn convert_closure_to_fn(acc: &mut Assists, ctx: &AssistContext<'_>) }; acc.add( - AssistId("convert_closure_to_fn", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_closure_to_fn"), "Convert closure to fn", closure.param_list()?.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs index 92b86cee356e8..0d36a5ddb304c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs @@ -4,7 +4,7 @@ use syntax::{ ast::{self, Comment, CommentKind, CommentShape, Whitespace, edit::IndentLevel}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: line_to_block // @@ -38,7 +38,7 @@ fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> { let target = comment.syntax().text_range(); acc.add( - AssistId("block_to_line", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("block_to_line"), "Replace block comment with line comments", target, |edit| { @@ -80,7 +80,7 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { ); acc.add( - AssistId("line_to_block", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("line_to_block"), "Replace line comments with a single block comment", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs index 7b4d27100f15d..187cc74306e25 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs @@ -4,7 +4,7 @@ use syntax::{ ast::{self, Comment, CommentPlacement, Whitespace, edit::IndentLevel}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: comment_to_doc // @@ -39,7 +39,7 @@ fn doc_to_comment(acc: &mut Assists, comment: ast::Comment) -> Option<()> { }; acc.add( - AssistId("doc_to_comment", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("doc_to_comment"), "Replace doc comment with comment", target, |edit| { @@ -86,7 +86,7 @@ fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacem }; acc.add( - AssistId("comment_to_doc", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("comment_to_doc"), "Replace comment with doc comment", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs index 03041f3551d39..801a57b3e3fae 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs @@ -9,7 +9,7 @@ use syntax::{ syntax_editor::Position, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: convert_for_loop_to_while_let // @@ -47,7 +47,7 @@ pub(crate) fn convert_for_loop_to_while_let( } acc.add( - AssistId("convert_for_loop_to_while_let", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_for_loop_to_while_let"), "Replace this for loop with `while let`", for_loop.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs index 07ad5a695b3c3..ec08eb924632f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs @@ -5,7 +5,7 @@ use syntax::{ ted, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: convert_from_to_tryfrom // @@ -71,7 +71,7 @@ pub(crate) fn convert_from_to_tryfrom(acc: &mut Assists, ctx: &AssistContext<'_> } acc.add( - AssistId("convert_from_to_tryfrom", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_from_to_tryfrom"), "Convert From to TryFrom", impl_.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs index 270eecd83b06e..846f4e9b258ae 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs @@ -1,6 +1,6 @@ use syntax::{AstToken, ast, ast::Radix}; -use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; +use crate::{AssistContext, AssistId, Assists, GroupLabel}; // Assist: convert_integer_literal // @@ -47,7 +47,7 @@ pub(crate) fn convert_integer_literal(acc: &mut Assists, ctx: &AssistContext<'_> acc.add_group( &group_id, - AssistId("convert_integer_literal", AssistKind::RefactorInline), + AssistId::refactor_rewrite("convert_integer_literal"), label, range, |builder| builder.replace(range, converted), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs index 8c59ef4314f06..b80276a95fbf5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs @@ -1,7 +1,7 @@ use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast, traits::resolve_target_trait}; use syntax::ast::{self, AstNode, HasGenericArgs, HasName}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // FIXME: this should be a diagnostic @@ -85,7 +85,7 @@ pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext<'_>) - .filter(|name| name.text() == "self" || name.text() == "Self"); acc.add( - AssistId("convert_into_to_from", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_into_to_from"), "Convert Into to From", impl_.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs index 713d215f1209e..d7f6594e6d4e7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs @@ -6,7 +6,7 @@ use syntax::{ ast::{self, HasArgList, HasLoopBody, edit_in_place::Indent, make}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: convert_iter_for_each_to_for // @@ -53,7 +53,7 @@ pub(crate) fn convert_iter_for_each_to_for( let range = stmt.as_ref().map_or(method.syntax(), AstNode::syntax).text_range(); acc.add( - AssistId("convert_iter_for_each_to_for", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_iter_for_each_to_for"), "Replace this `Iterator::for_each` with a for loop", range, |builder| { @@ -108,7 +108,7 @@ pub(crate) fn convert_for_loop_with_for_each( } acc.add( - AssistId("convert_for_loop_with_for_each", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_for_loop_with_for_each"), "Replace this for loop with `Iterator::for_each`", for_loop.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs index 9f71031a1e68a..df92b07cba7cd 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs @@ -4,7 +4,7 @@ use syntax::T; use syntax::ast::RangeItem; use syntax::ast::{AstNode, HasName, LetStmt, Name, Pat, edit::AstNodeEdit}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: convert_let_else_to_match // @@ -43,7 +43,7 @@ pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext<' let target = let_stmt.syntax().text_range(); acc.add( - AssistId("convert_let_else_to_match", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_let_else_to_match"), "Convert let-else to let and match", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs index 2db78f412d740..efcbcef00e903 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs @@ -6,7 +6,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; @@ -55,7 +55,7 @@ pub(crate) fn convert_match_to_let_else(acc: &mut Assists, ctx: &AssistContext<' let extracted_variable_positions = find_extracted_variable(ctx, &extracting_arm)?; acc.add( - AssistId("convert_match_to_let_else", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_match_to_let_else"), "Convert match to let-else", let_stmt.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs index 7b8804e53f087..53a5a9465e08f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs @@ -7,7 +7,7 @@ use syntax::{ match_ast, ted, }; -use crate::{AssistContext, AssistId, AssistKind, Assists, assist_context::SourceChangeBuilder}; +use crate::{AssistContext, AssistId, Assists, assist_context::SourceChangeBuilder}; // Assist: convert_named_struct_to_tuple_struct // @@ -69,7 +69,7 @@ pub(crate) fn convert_named_struct_to_tuple_struct( }; acc.add( - AssistId("convert_named_struct_to_tuple_struct", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_named_struct_to_tuple_struct"), "Convert to tuple struct", strukt.syntax().text_range(), |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs index ea2752b881857..c0fd69779aeae 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs @@ -1,4 +1,4 @@ -use ide_db::assists::{AssistId, AssistKind}; +use ide_db::assists::AssistId; use syntax::ast::{self, HasGenericParams, HasName}; use syntax::{AstNode, SyntaxKind}; @@ -44,7 +44,7 @@ pub(crate) fn convert_nested_function_to_closure( let param_list = function.param_list()?; acc.add( - AssistId("convert_nested_function_to_closure", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_nested_function_to_closure"), "Convert nested function to closure", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs index bd829d1e24bf9..71a61f2db0011 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs @@ -17,7 +17,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, utils::invert_boolean_expression_legacy, }; @@ -128,7 +128,7 @@ fn if_expr_to_guarded_return( let target = if_expr.syntax().text_range(); acc.add( - AssistId("convert_to_guarded_return", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_to_guarded_return"), "Convert to guarded return", target, |edit| { @@ -210,7 +210,7 @@ fn let_stmt_to_guarded_return( }; acc.add( - AssistId("convert_to_guarded_return", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_to_guarded_return"), "Convert to guarded return", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs index 0d79937885717..87eafc39f83c1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs @@ -2,7 +2,7 @@ use either::Either; use hir::ModuleDef; use ide_db::{ FxHashSet, - assists::{AssistId, AssistKind}, + assists::AssistId, defs::Definition, helpers::mod_path_to_ast, imports::insert_use::{ImportScope, insert_use}, @@ -63,7 +63,7 @@ pub(crate) fn convert_tuple_return_type_to_struct( let target = type_ref.syntax().text_range(); acc.add( - AssistId("convert_tuple_return_type_to_struct", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_tuple_return_type_to_struct"), "Convert tuple return type to tuple struct", target, move |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs index 83e4737350c07..ae23fa05f9a28 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs @@ -6,7 +6,7 @@ use syntax::{ match_ast, ted, }; -use crate::{AssistContext, AssistId, AssistKind, Assists, assist_context::SourceChangeBuilder}; +use crate::{AssistContext, AssistId, Assists, assist_context::SourceChangeBuilder}; // Assist: convert_tuple_struct_to_named_struct // @@ -65,7 +65,7 @@ pub(crate) fn convert_tuple_struct_to_named_struct( let target = strukt.as_ref().either(|s| s.syntax(), |v| v.syntax()).text_range(); acc.add( - AssistId("convert_tuple_struct_to_named_struct", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_tuple_struct_to_named_struct"), "Convert to named struct", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs index 6a5b11f542560..e582aa814ae14 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs @@ -3,7 +3,7 @@ use ide_db::RootDatabase; use stdx::format_to; use syntax::ast::{self, AstNode}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: convert_two_arm_bool_match_to_matches_macro // @@ -56,7 +56,7 @@ pub(crate) fn convert_two_arm_bool_match_to_matches_macro( let expr = match_expr.expr()?; acc.add( - AssistId("convert_two_arm_bool_match_to_matches_macro", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_two_arm_bool_match_to_matches_macro"), "Convert to matches!", target_range, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs index 724de1969cb53..dbe3ee0ed6039 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs @@ -12,7 +12,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, utils::invert_boolean_expression_legacy, }; @@ -47,7 +47,7 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>) let target = while_expr.syntax().text_range(); acc.add( - AssistId("convert_while_to_loop", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("convert_while_to_loop"), "Convert while to loop", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs index a8a3a8c927f81..76fb6b6b06a48 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs @@ -2,7 +2,7 @@ use hir::{HasVisibility, sym}; use ide_db::text_edit::TextRange; use ide_db::{ FxHashMap, FxHashSet, - assists::{AssistId, AssistKind}, + assists::AssistId, defs::Definition, helpers::mod_path_to_ast, search::{FileReference, SearchScope}, @@ -47,7 +47,7 @@ pub(crate) fn destructure_struct_binding(acc: &mut Assists, ctx: &AssistContext< let data = collect_data(ident_pat, ctx)?; acc.add( - AssistId("destructure_struct_binding", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("destructure_struct_binding"), "Destructure struct binding", data.ident_pat.syntax().text_range(), |edit| destructure_struct_binding_impl(ctx, edit, &data), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs index 95eb88fa86878..adf0f0997b39d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs @@ -1,5 +1,5 @@ use ide_db::{ - assists::{AssistId, AssistKind}, + assists::AssistId, defs::Definition, search::{FileReference, SearchScope}, syntax_helpers::suggest_name, @@ -65,7 +65,7 @@ pub(crate) fn destructure_tuple_binding_impl( if with_sub_pattern { acc.add( - AssistId("destructure_tuple_binding_in_sub_pattern", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("destructure_tuple_binding_in_sub_pattern"), "Destructure tuple in sub-pattern", data.ident_pat.syntax().text_range(), |edit| destructure_tuple_edit_impl(ctx, edit, &data, true), @@ -73,7 +73,7 @@ pub(crate) fn destructure_tuple_binding_impl( } acc.add( - AssistId("destructure_tuple_binding", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("destructure_tuple_binding"), if with_sub_pattern { "Destructure tuple in place" } else { "Destructure tuple" }, data.ident_pat.syntax().text_range(), |edit| destructure_tuple_edit_impl(ctx, edit, &data, false), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs index 9d0797d32a82f..74bb0ba3f6020 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs @@ -6,7 +6,7 @@ use syntax::{ }; use crate::{ - AssistContext, AssistId, AssistKind, Assists, + AssistContext, AssistId, Assists, handlers::convert_comment_block::{line_comment_text, relevant_line_comments}, utils::required_hashes, }; @@ -54,7 +54,7 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> }; acc.add( - AssistId("desugar_doc_comment", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("desugar_doc_comment"), "Desugar doc-comment to attribute macro", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs index fae5530f99528..307414c79715a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs @@ -13,7 +13,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; @@ -62,7 +62,7 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> let target = parent.either(|n| n.syntax().clone(), |n| n.syntax().clone()); acc.add( - AssistId("expand_glob_import", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("expand_glob_import"), "Expand glob import", target.text_range(), |builder| { @@ -123,7 +123,7 @@ pub(crate) fn expand_glob_reexport(acc: &mut Assists, ctx: &AssistContext<'_>) - let target = parent.either(|n| n.syntax().clone(), |n| n.syntax().clone()); acc.add( - AssistId("expand_glob_reexport", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("expand_glob_reexport"), "Expand glob reexport", target.text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs index e437e7eb75122..ceb13b2f21218 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs @@ -74,7 +74,7 @@ fn expand_record_rest_pattern( let target_range = rest_pat.syntax().text_range(); acc.add( - AssistId("expand_record_rest_pattern", crate::AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("expand_record_rest_pattern"), "Fill struct fields", target_range, move |builder| builder.replace_ast(old_field_list, new_field_list), @@ -155,7 +155,7 @@ fn expand_tuple_struct_rest_pattern( let target_range = rest_pat.syntax().text_range(); acc.add( - AssistId("expand_tuple_struct_rest_pattern", crate::AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("expand_tuple_struct_rest_pattern"), "Fill tuple struct fields", target_range, move |builder| builder.replace_ast(pat, new_pat), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs index c9eb7c52379fc..1212bb770bb1b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs @@ -53,6 +53,7 @@ pub(crate) fn extract_expressions_from_format_string( } else { AssistKind::QuickFix }, + None, ), "Extract format expressions", tt.syntax().text_range(), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs index 6b535a289776f..abc0698b0141e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs @@ -108,7 +108,7 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op acc.add_group( &GroupLabel("Extract into...".to_owned()), - AssistId("extract_function", crate::AssistKind::RefactorExtract), + AssistId::refactor_extract("extract_function"), "Extract into function", target_range, move |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs index 8a7bb5a1f0d8b..a77b5e4a1a5ff 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs @@ -5,7 +5,7 @@ use hir::{HasSource, HirFileIdExt, ModuleSource}; use ide_db::base_db::salsa::AsDynDatabase; use ide_db::{ FileId, FxHashMap, FxHashSet, - assists::{AssistId, AssistKind}, + assists::AssistId, defs::{Definition, NameClass, NameRefClass}, search::{FileReference, SearchScope}, }; @@ -92,7 +92,7 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti let old_item_indent = module.body_items[0].indent_level(); acc.add( - AssistId("extract_module", AssistKind::RefactorExtract), + AssistId::refactor_extract("extract_module"), "Extract Module", module.text_range, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs index 7fba75f9e56d4..72fdae271daba 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs @@ -22,7 +22,7 @@ use syntax::{ match_ast, ted, }; -use crate::{AssistContext, AssistId, AssistKind, Assists, assist_context::SourceChangeBuilder}; +use crate::{AssistContext, AssistId, Assists, assist_context::SourceChangeBuilder}; // Assist: extract_struct_from_enum_variant // @@ -55,7 +55,7 @@ pub(crate) fn extract_struct_from_enum_variant( let enum_hir = ctx.sema.to_def(&enum_ast)?; let target = variant.syntax().text_range(); acc.add( - AssistId("extract_struct_from_enum_variant", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("extract_struct_from_enum_variant"), "Extract struct from enum variant", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs index e6fb4d40d46b5..c1c9a82dd18ad 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs @@ -5,7 +5,7 @@ use syntax::{ syntax_editor, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: extract_type_alias // @@ -40,7 +40,7 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> let target = ty.syntax().text_range(); acc.add( - AssistId("extract_type_alias", AssistKind::RefactorExtract), + AssistId::refactor_extract("extract_type_alias"), "Extract type as type alias", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs index 2e58e62ab0ccc..95ea8b3c8b683 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs @@ -13,7 +13,7 @@ use syntax::{ syntax_editor::Position, }; -use crate::{AssistContext, AssistId, AssistKind, Assists, utils::is_body_const}; +use crate::{AssistContext, AssistId, Assists, utils::is_body_const}; // Assist: extract_variable // @@ -311,7 +311,7 @@ impl ExtractionKind { ExtractionKind::Static => "extract_static", }; - AssistId(s, AssistKind::RefactorExtract) + AssistId::refactor_extract(s) } fn label(&self) -> &'static str { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs index 51dbce2973179..6373699853b32 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs @@ -7,7 +7,7 @@ use syntax::{ ast::{self, HasVisibility as _, edit_in_place::HasVisibilityEdit, make}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // FIXME: this really should be a fix for diagnostic, rather than an assist. @@ -78,7 +78,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>) } }; - acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |edit| { + acc.add(AssistId::quick_fix("fix_visibility"), assist_label, target, |edit| { edit.edit_file(target_file); let vis_owner = edit.make_mut(vis_owner); @@ -131,7 +131,7 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_> target_name.display(ctx.db(), current_edition) ); - acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |edit| { + acc.add(AssistId::quick_fix("fix_visibility"), assist_label, target, |edit| { edit.edit_file(target_file.file_id()); let vis_owner = edit.make_mut(vis_owner); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs index 75133c3a023b8..94d7b73425de1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs @@ -3,7 +3,7 @@ use syntax::{ ast::{self, AstNode, BinExpr, syntax_factory::SyntaxFactory}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: flip_binexpr // @@ -43,7 +43,7 @@ pub(crate) fn flip_binexpr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option } acc.add( - AssistId("flip_binexpr", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("flip_binexpr"), "Flip binary expression", op_token.text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs index 6900e94bdd23b..25e514b49802f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs @@ -5,7 +5,7 @@ use syntax::{ syntax_editor::SyntaxMapping, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: flip_comma // @@ -40,7 +40,7 @@ pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( } let target = comma.text_range(); - acc.add(AssistId("flip_comma", AssistKind::RefactorRewrite), "Flip comma", target, |builder| { + acc.add(AssistId::refactor_rewrite("flip_comma"), "Flip comma", target, |builder| { let parent = comma.parent().unwrap(); let mut editor = builder.make_editor(&parent); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs index 6ef8aa6a739e0..c84d23ffd0e57 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs @@ -4,7 +4,7 @@ use syntax::{ ast::{self, AstNode}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: flip_or_pattern // @@ -31,17 +31,12 @@ pub(crate) fn flip_or_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt let after = non_trivia_sibling(pipe.clone().into(), Direction::Next)?.into_node()?; let target = pipe.text_range(); - acc.add( - AssistId("flip_or_pattern", AssistKind::RefactorRewrite), - "Flip patterns", - target, - |builder| { - let mut editor = builder.make_editor(parent.syntax()); - editor.replace(before.clone(), after.clone()); - editor.replace(after, before); - builder.add_file_edits(ctx.file_id(), editor); - }, - ) + acc.add(AssistId::refactor_rewrite("flip_or_pattern"), "Flip patterns", target, |builder| { + let mut editor = builder.make_editor(parent.syntax()); + editor.replace(before.clone(), after.clone()); + editor.replace(after, before); + builder.add_file_edits(ctx.file_id(), editor); + }) } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs index af40b09643a33..2f3b047b27851 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs @@ -4,7 +4,7 @@ use syntax::{ ast::{self, AstNode}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: flip_trait_bound // @@ -29,7 +29,7 @@ pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op let target = plus.text_range(); acc.add( - AssistId("flip_trait_bound", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("flip_trait_bound"), "Flip trait bounds", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs index 2f4b6a0421bbf..dbf3b6d1f7e45 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs @@ -2,7 +2,7 @@ use crate::assist_context::{AssistContext, Assists}; use hir::{HasVisibility, HirDisplay, HirFileIdExt, Module}; use ide_db::{ FileId, - assists::{AssistId, AssistKind}, + assists::AssistId, base_db::Upcast, defs::{Definition, NameRefClass}, }; @@ -88,17 +88,12 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O ); let text = get_text_for_generate_constant(not_exist_name_ref, indent, outer_exists, type_name)?; - acc.add( - AssistId("generate_constant", AssistKind::QuickFix), - "Generate constant", - target, - |builder| { - if let Some(file_id) = file_id { - builder.edit_file(file_id); - } - builder.insert(offset, format!("{text}{post_string}")); - }, - ) + acc.add(AssistId::quick_fix("generate_constant"), "Generate constant", target, |builder| { + if let Some(file_id) = file_id { + builder.edit_file(file_id); + } + builder.insert(offset, format!("{text}{post_string}")); + }) } fn get_text_for_generate_constant( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs index c6725a013e3b6..6198dbc4ed99b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs @@ -1,7 +1,7 @@ use ide_db::{RootDatabase, famous_defs::FamousDefs}; use syntax::ast::{self, AstNode, HasName}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: generate_default_from_enum_variant // @@ -47,7 +47,7 @@ pub(crate) fn generate_default_from_enum_variant( let target = variant.syntax().text_range(); acc.add( - AssistId("generate_default_from_enum_variant", AssistKind::Generate), + AssistId::generate("generate_default_from_enum_variant"), "Generate `Default` impl from this enum variant", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs index 1a4349cfea91b..79a78ab3698b8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs @@ -65,7 +65,7 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext<' let insert_location = impl_.syntax().text_range(); acc.add( - AssistId("generate_default_from_new", crate::AssistKind::Generate), + AssistId::generate("generate_default_from_new"), "Generate a Default impl from a new fn", insert_location, move |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs index 7bf29978128e0..c7b97dcd231d1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs @@ -8,7 +8,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists, SourceChangeBuilder}, utils::generate_trait_impl_text, }; @@ -65,7 +65,7 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( let field_name = field.name()?; let target = field.syntax().text_range(); acc.add( - AssistId("generate_deref", AssistKind::Generate), + AssistId::generate("generate_deref"), format!("Generate `{deref_type_to_generate:?}` impl using `{field_name}`"), target, |edit| { @@ -106,7 +106,7 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<() let field_type = field.ty()?; let target = field.syntax().text_range(); acc.add( - AssistId("generate_deref", AssistKind::Generate), + AssistId::generate("generate_deref"), format!("Generate `{deref_type_to_generate:?}` impl using `{field}`"), target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs index 8b4dbeff7cf48..73a69c82fbcdd 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs @@ -3,7 +3,7 @@ use syntax::{ ast::{self, AstNode, HasAttrs, edit_in_place::AttrsOwnerEdit, make}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: generate_derive // @@ -39,7 +39,7 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt Some(tt) => Some(tt.right_delimiter_token()?), }; - acc.add(AssistId("generate_derive", AssistKind::Generate), "Add `#[derive]`", target, |edit| { + acc.add(AssistId::generate("generate_derive"), "Add `#[derive]`", target, |edit| { match derive_attr { None => { let derive = make::attr_outer(make::meta_token_tree( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs index df05c0d6b2f35..d4d1b3490cb64 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs @@ -1,5 +1,5 @@ use hir::{AsAssocItem, HasVisibility, ModuleDef, Visibility}; -use ide_db::assists::{AssistId, AssistKind}; +use ide_db::assists::AssistId; use itertools::Itertools; use stdx::{format_to, to_lower_snake_case}; use syntax::{ @@ -56,7 +56,7 @@ pub(crate) fn generate_documentation_template( let indent_level = IndentLevel::from_node(parent_syntax); acc.add( - AssistId("generate_documentation_template", AssistKind::Generate), + AssistId::generate("generate_documentation_template"), "Generate a documentation template", text_range, |builder| { @@ -115,7 +115,7 @@ pub(crate) fn generate_doc_example(acc: &mut Assists, ctx: &AssistContext<'_>) - let indent_level = IndentLevel::from_node(&node); acc.add( - AssistId("generate_doc_example", AssistKind::Generate), + AssistId::generate("generate_doc_example"), "Generate a documentation example", node.text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs index 78fdca910c7a2..3e6d0bec68a6f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs @@ -4,7 +4,7 @@ use syntax::ast::HasVisibility; use syntax::ast::{self, AstNode, HasName}; use crate::{ - AssistContext, AssistId, AssistKind, Assists, + AssistContext, AssistId, Assists, utils::{add_method_to_adt, find_struct_impl}, }; @@ -57,7 +57,7 @@ pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext<'_> let target = variant.syntax().text_range(); acc.add_group( &GroupLabel("Generate an `is_`,`as_`, or `try_into_` for this enum variant".to_owned()), - AssistId("generate_enum_is_method", AssistKind::Generate), + AssistId::generate("generate_enum_is_method"), "Generate an `is_` method for this enum variant", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs index e96be673a1b6b..3974bcf618756 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs @@ -5,7 +5,7 @@ use syntax::ast::HasVisibility; use syntax::ast::{self, AstNode, HasName}; use crate::{ - AssistContext, AssistId, AssistKind, Assists, + AssistContext, AssistId, Assists, utils::{add_method_to_adt, find_struct_impl}, }; @@ -153,7 +153,7 @@ fn generate_enum_projection_method( let target = variant.syntax().text_range(); acc.add_group( &GroupLabel("Generate an `is_`,`as_`, or `try_into_` for this enum variant".to_owned()), - AssistId(assist_id, AssistKind::Generate), + AssistId::generate(assist_id), assist_description, target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs index 51b6a4be019dd..8a20a2dd59d23 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs @@ -1,5 +1,5 @@ use hir::{HasSource, HirDisplay, InRealFile}; -use ide_db::assists::{AssistId, AssistKind}; +use ide_db::assists::AssistId; use syntax::{ AstNode, SyntaxNode, ast::{self, HasArgList, syntax_factory::SyntaxFactory}, @@ -58,21 +58,16 @@ pub(crate) fn generate_enum_variant(acc: &mut Assists, ctx: &AssistContext<'_>) let db = ctx.db(); let InRealFile { file_id, value: enum_node } = e.source(db)?.original_ast_node_rooted(db)?; - acc.add( - AssistId("generate_enum_variant", AssistKind::Generate), - "Generate variant", - target, - |builder| { - let mut editor = builder.make_editor(enum_node.syntax()); - let make = SyntaxFactory::new(); - let field_list = parent.make_field_list(ctx, &make); - let variant = make.variant(None, make.name(&name_ref.text()), field_list, None); - if let Some(it) = enum_node.variant_list() { - it.add_variant(&mut editor, &variant); - } - builder.add_file_edits(file_id, editor); - }, - ) + acc.add(AssistId::generate("generate_enum_variant"), "Generate variant", target, |builder| { + let mut editor = builder.make_editor(enum_node.syntax()); + let make = SyntaxFactory::new(); + let field_list = parent.make_field_list(ctx, &make); + let variant = make.variant(None, make.name(&name_ref.text()), field_list, None); + if let Some(it) = enum_node.variant_list() { + it.add_variant(&mut editor, &variant); + } + builder.add_file_edits(file_id, editor); + }) } #[derive(Debug)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs index bc890ac53b88b..7ece5f8ea5f5d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs @@ -1,5 +1,5 @@ use either::Either; -use ide_db::assists::{AssistId, AssistKind, GroupLabel}; +use ide_db::assists::{AssistId, GroupLabel}; use syntax::{ AstNode, ast::{self, HasGenericParams, HasName, edit::IndentLevel, make}, @@ -139,7 +139,7 @@ impl ParamStyle { ParamStyle::Unnamed => "generate_fn_type_alias_unnamed", }; - AssistId(s, AssistKind::Generate) + AssistId::generate(s) } fn label(&self) -> &'static str { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs index 88226820cf274..af949a0649899 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs @@ -1,9 +1,7 @@ use ide_db::{RootDatabase, famous_defs::FamousDefs}; use syntax::ast::{self, AstNode, HasName}; -use crate::{ - AssistContext, AssistId, AssistKind, Assists, utils::generate_trait_impl_text_intransitive, -}; +use crate::{AssistContext, AssistId, Assists, utils::generate_trait_impl_text_intransitive}; // Assist: generate_from_impl_for_enum // @@ -53,7 +51,7 @@ pub(crate) fn generate_from_impl_for_enum( let target = variant.syntax().text_range(); acc.add( - AssistId("generate_from_impl_for_enum", AssistKind::Generate), + AssistId::generate("generate_from_impl_for_enum"), "Generate `From` impl for this enum variant", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs index a74d477ec8950..55187c38c171d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs @@ -23,7 +23,7 @@ use syntax::{ }; use crate::{ - AssistContext, AssistId, AssistKind, Assists, + AssistContext, AssistId, Assists, utils::{convert_reference_type, find_struct_impl}, }; @@ -173,7 +173,7 @@ fn add_func_to_accumulator( adt_info: Option, label: String, ) -> Option<()> { - acc.add(AssistId("generate_function", AssistKind::Generate), label, text_range, |edit| { + acc.add(AssistId::generate("generate_function"), label, text_range, |edit| { edit.edit_file(file); let target = function_builder.target.clone(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs index 8183a11e1ba0c..c7e5e41aac4ce 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs @@ -7,7 +7,7 @@ use syntax::{ }; use crate::{ - AssistContext, AssistId, AssistKind, Assists, GroupLabel, + AssistContext, AssistId, Assists, GroupLabel, utils::{convert_reference_type, find_struct_impl, generate_impl}, }; @@ -63,7 +63,7 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt acc.add_group( &GroupLabel("Generate getter/setter".to_owned()), - AssistId("generate_setter", AssistKind::Generate), + AssistId::generate("generate_setter"), "Generate a setter method", target, |builder| build_source_change(builder, ctx, info_of_record_fields, setter_info), @@ -204,7 +204,7 @@ pub(crate) fn generate_getter_impl( acc.add_group( &GroupLabel("Generate getter/setter".to_owned()), - AssistId(id, AssistKind::Generate), + AssistId::generate(id), label, target, |builder| build_source_change(builder, ctx, info_of_record_fields, getter_info), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs index ff4f388e39cb0..2862e6d5afba3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs @@ -3,7 +3,7 @@ use syntax::{ ted, }; -use crate::{AssistContext, AssistId, AssistKind, Assists, utils}; +use crate::{AssistContext, AssistId, Assists, utils}; fn insert_impl(impl_: ast::Impl, nominal: &ast::Adt) { let indent = nominal.indent_level(); @@ -44,7 +44,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio } acc.add( - AssistId("generate_impl", AssistKind::Generate), + AssistId::generate("generate_impl"), format!("Generate impl for `{name}`"), target, |edit| { @@ -90,7 +90,7 @@ pub(crate) fn generate_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> } acc.add( - AssistId("generate_trait_impl", AssistKind::Generate), + AssistId::generate("generate_trait_impl"), format!("Generate trait impl for `{name}`"), target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs index d9ed8111c6f8d..f86c717fcce4f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs @@ -5,7 +5,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; @@ -69,7 +69,7 @@ pub(crate) fn generate_is_empty_from_len(acc: &mut Assists, ctx: &AssistContext< let range = node.syntax().value.text_range(); acc.add( - AssistId("generate_is_empty_from_len", AssistKind::Generate), + AssistId::generate("generate_is_empty_from_len"), "Generate a is_empty impl from a len function", range, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs index 8d107e412896e..2ac960ed7e183 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs @@ -5,7 +5,7 @@ use syntax::{ ted, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // FIXME: Generate proper `index_mut` method body refer to `index` method body may impossible due to the unpredictable case [#15581]. // Here just leave the `index_mut` method body be same as `index` method body, user can modify it manually to meet their need. @@ -102,7 +102,7 @@ pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_> let target = impl_def.syntax().text_range(); acc.add( - AssistId("generate_mut_trait_impl", AssistKind::Generate), + AssistId::generate("generate_mut_trait_impl"), "Generate `IndexMut` impl from this `Index` trait", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs index f14a4c1070751..f963f48d62ab6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs @@ -7,7 +7,7 @@ use syntax::{ }; use crate::{ - AssistContext, AssistId, AssistKind, Assists, + AssistContext, AssistId, Assists, utils::{find_struct_impl, generate_impl}, }; @@ -48,7 +48,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option let current_module = ctx.sema.scope(strukt.syntax())?.module(); let target = strukt.syntax().text_range(); - acc.add(AssistId("generate_new", AssistKind::Generate), "Generate `new`", target, |builder| { + acc.add(AssistId::generate("generate_new"), "Generate `new`", target, |builder| { let trivial_constructors = field_list .fields() .map(|f| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs index 3470a4d660dce..154b502e1bf97 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs @@ -95,7 +95,7 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_ let impl_name = impl_ast.self_ty()?; acc.add( - AssistId("generate_trait_from_impl", ide_db::assists::AssistKind::Generate), + AssistId::generate("generate_trait_from_impl"), "Generate trait from impl", impl_ast.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs index b8381a8cce100..bb445e572bef6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs @@ -27,7 +27,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; @@ -98,7 +98,7 @@ pub(crate) fn inline_into_callers(acc: &mut Assists, ctx: &AssistContext<'_>) -> } acc.add( - AssistId("inline_into_callers", AssistKind::RefactorInline), + AssistId::refactor_inline("inline_into_callers"), "Inline into all callers", name.syntax().text_range(), |builder| { @@ -232,21 +232,16 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< } let syntax = call_info.node.syntax().clone(); - acc.add( - AssistId("inline_call", AssistKind::RefactorInline), - label, - syntax.text_range(), - |builder| { - let replacement = inline(&ctx.sema, file_id, function, &fn_body, ¶ms, &call_info); - builder.replace_ast( - match call_info.node { - ast::CallableExpr::Call(it) => ast::Expr::CallExpr(it), - ast::CallableExpr::MethodCall(it) => ast::Expr::MethodCallExpr(it), - }, - replacement, - ); - }, - ) + acc.add(AssistId::refactor_inline("inline_call"), label, syntax.text_range(), |builder| { + let replacement = inline(&ctx.sema, file_id, function, &fn_body, ¶ms, &call_info); + builder.replace_ast( + match call_info.node { + ast::CallableExpr::Call(it) => ast::Expr::CallExpr(it), + ast::CallableExpr::MethodCall(it) => ast::Expr::MethodCallExpr(it), + }, + replacement, + ); + }) } struct CallInfo { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs index 10f9652cfe91e..e5ed04fdc7c9e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs @@ -1,7 +1,7 @@ use hir::HasCrate; use syntax::{AstNode, ast}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: inline_const_as_literal // @@ -44,7 +44,7 @@ pub(crate) fn inline_const_as_literal(acc: &mut Assists, ctx: &AssistContext<'_> .ok()? .render(ctx.sema.db, konst.krate(ctx.sema.db).to_display_target(ctx.sema.db)); - let id = AssistId("inline_const_as_literal", AssistKind::RefactorInline); + let id = AssistId::refactor_inline("inline_const_as_literal"); let label = "Inline const as literal".to_owned(); let target = variable.syntax().text_range(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs index 8b7aa8f4af34f..f1a3f72f7b94c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs @@ -10,7 +10,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; @@ -74,7 +74,7 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>) }; acc.add( - AssistId("inline_local_variable", AssistKind::RefactorInline), + AssistId::refactor_inline("inline_local_variable"), "Inline variable", target.text_range(), move |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs index cd6f900ba15da..37d9b340d08c7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs @@ -2,7 +2,7 @@ use hir::db::ExpandDatabase; use ide_db::syntax_helpers::prettify_macro_expansion; use syntax::ast::{self, AstNode}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: inline_macro // @@ -42,7 +42,7 @@ pub(crate) fn inline_macro(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option let text_range = unexpanded.syntax().text_range(); acc.add( - AssistId("inline_macro", AssistKind::RefactorInline), + AssistId::refactor_inline("inline_macro"), "Inline macro".to_owned(), text_range, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs index 936b09d5a46ca..6a132e119e701 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs @@ -16,7 +16,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; @@ -60,7 +60,7 @@ pub(crate) fn inline_type_alias_uses(acc: &mut Assists, ctx: &AssistContext<'_>) // until this is ok acc.add( - AssistId("inline_type_alias_uses", AssistKind::RefactorInline), + AssistId::refactor_inline("inline_type_alias_uses"), "Inline type alias into all uses", name.syntax().text_range(), |builder| { @@ -149,7 +149,7 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> O let target = alias_instance.syntax().text_range(); acc.add( - AssistId("inline_type_alias", AssistKind::RefactorInline), + AssistId::refactor_inline("inline_type_alias"), "Inline type alias", target, |builder| builder.replace(target, replacement.to_text(&concrete_type)), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs index c8ec3da180b8f..47b273535a88f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs @@ -1,8 +1,5 @@ use hir::{AsAssocItem, HirDisplay}; -use ide_db::{ - assists::{AssistId, AssistKind}, - famous_defs::FamousDefs, -}; +use ide_db::{assists::AssistId, famous_defs::FamousDefs}; use syntax::{AstNode, ast}; use crate::assist_context::{AssistContext, Assists}; @@ -60,7 +57,7 @@ pub(crate) fn into_to_qualified_from(acc: &mut Assists, ctx: &AssistContext<'_>) let sc = adjusted_tc.display_source_code(db, scope.module().into(), true).ok()?; acc.add( - AssistId("into_to_qualified_from", AssistKind::Generate), + AssistId::generate("into_to_qualified_from"), "Convert `into` to fully qualified `from`", nameref.syntax().text_range(), |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs index 587e76585f14a..264e3767a2324 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs @@ -5,7 +5,7 @@ use syntax::{ ted::{self, Position}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists, assist_context::SourceChangeBuilder}; +use crate::{AssistContext, AssistId, Assists, assist_context::SourceChangeBuilder}; static ASSIST_NAME: &str = "introduce_named_lifetime"; static ASSIST_LABEL: &str = "Introduce named lifetime"; @@ -83,7 +83,7 @@ fn generate_fn_def_assist( _ => return None, } }; - acc.add(AssistId(ASSIST_NAME, AssistKind::Refactor), ASSIST_LABEL, lifetime_loc, |builder| { + acc.add(AssistId::refactor(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| { let fn_def = builder.make_mut(fn_def); let lifetime = builder.make_mut(lifetime); let loc_needing_lifetime = @@ -107,7 +107,7 @@ fn generate_impl_def_assist( lifetime: ast::Lifetime, ) -> Option<()> { let new_lifetime_param = generate_unique_lifetime_param_name(impl_def.generic_param_list())?; - acc.add(AssistId(ASSIST_NAME, AssistKind::Refactor), ASSIST_LABEL, lifetime_loc, |builder| { + acc.add(AssistId::refactor(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| { let impl_def = builder.make_mut(impl_def); let lifetime = builder.make_mut(lifetime); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs index d60106cc80423..9c39a7aa41e9d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs @@ -2,7 +2,7 @@ use ide_db::syntax_helpers::suggest_name; use itertools::Itertools; use syntax::ast::{self, AstNode, HasGenericParams, HasName, syntax_factory::SyntaxFactory}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: introduce_named_type_parameter // @@ -27,7 +27,7 @@ pub(crate) fn introduce_named_type_parameter( let make = SyntaxFactory::new(); let target = fn_.syntax().text_range(); acc.add( - AssistId("introduce_named_type_parameter", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("introduce_named_type_parameter"), "Replace impl trait with type parameter", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs index 4273a85df5a6a..d198870b023e6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs @@ -5,7 +5,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, utils::invert_boolean_expression_legacy, }; @@ -47,7 +47,7 @@ pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<() ast::ElseBranch::IfExpr(_) => return None, }; - acc.add(AssistId("invert_if", AssistKind::RefactorRewrite), "Invert if", if_range, |edit| { + acc.add(AssistId::refactor_rewrite("invert_if"), "Invert if", if_range, |edit| { let flip_cond = invert_boolean_expression_legacy(cond.clone()); edit.replace_ast(cond, flip_cond); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs index aae007577c245..b7f7cb9cb01c5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs @@ -12,7 +12,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, utils::next_prev, }; @@ -69,55 +69,50 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio (selection_range, edits?) }; - acc.add( - AssistId("merge_imports", AssistKind::RefactorRewrite), - "Merge imports", - target, - |builder| { - let edits_mut: Vec = edits - .into_iter() - .map(|it| match it { - Remove(Either::Left(it)) => Remove(Either::Left(builder.make_mut(it))), - Remove(Either::Right(it)) => Remove(Either::Right(builder.make_mut(it))), - Replace(old, new) => Replace(builder.make_syntax_mut(old), new), - }) - .collect(); - for edit in edits_mut { - match edit { - Remove(it) => it.as_ref().either(Removable::remove, Removable::remove), - Replace(old, new) => { - ted::replace(old, &new); - - // If there's a selection and we're replacing a use tree in a tree list, - // normalize the parent use tree if it only contains the merged subtree. - if !ctx.has_empty_selection() { - let normalized_use_tree = ast::UseTree::cast(new) - .as_ref() - .and_then(ast::UseTree::parent_use_tree_list) - .and_then(|use_tree_list| { - if use_tree_list.use_trees().collect_tuple::<(_,)>().is_some() { - Some(use_tree_list.parent_use_tree()) - } else { - None - } - }) - .and_then(|target_tree| { - try_normalize_use_tree( - &target_tree, - ctx.config.insert_use.granularity.into(), - ) - .map(|top_use_tree_flat| (target_tree, top_use_tree_flat)) - }); - if let Some((old_tree, new_tree)) = normalized_use_tree { - cov_mark::hit!(replace_parent_with_normalized_use_tree); - ted::replace(old_tree.syntax(), new_tree.syntax()); - } + acc.add(AssistId::refactor_rewrite("merge_imports"), "Merge imports", target, |builder| { + let edits_mut: Vec = edits + .into_iter() + .map(|it| match it { + Remove(Either::Left(it)) => Remove(Either::Left(builder.make_mut(it))), + Remove(Either::Right(it)) => Remove(Either::Right(builder.make_mut(it))), + Replace(old, new) => Replace(builder.make_syntax_mut(old), new), + }) + .collect(); + for edit in edits_mut { + match edit { + Remove(it) => it.as_ref().either(Removable::remove, Removable::remove), + Replace(old, new) => { + ted::replace(old, &new); + + // If there's a selection and we're replacing a use tree in a tree list, + // normalize the parent use tree if it only contains the merged subtree. + if !ctx.has_empty_selection() { + let normalized_use_tree = ast::UseTree::cast(new) + .as_ref() + .and_then(ast::UseTree::parent_use_tree_list) + .and_then(|use_tree_list| { + if use_tree_list.use_trees().collect_tuple::<(_,)>().is_some() { + Some(use_tree_list.parent_use_tree()) + } else { + None + } + }) + .and_then(|target_tree| { + try_normalize_use_tree( + &target_tree, + ctx.config.insert_use.granularity.into(), + ) + .map(|top_use_tree_flat| (target_tree, top_use_tree_flat)) + }); + if let Some((old_tree, new_tree)) = normalized_use_tree { + cov_mark::hit!(replace_parent_with_normalized_use_tree); + ted::replace(old_tree.syntax(), new_tree.syntax()); } } } } - }, - ) + } + }) } trait Merge: AstNode + Clone { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs index be73377070f3f..42f35210b4967 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs @@ -7,7 +7,7 @@ use syntax::{ ast::{self, AstNode, HasName}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists, TextRange}; +use crate::{AssistContext, AssistId, Assists, TextRange}; // Assist: merge_match_arms // @@ -73,7 +73,7 @@ pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op } acc.add( - AssistId("merge_match_arms", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("merge_match_arms"), "Merge match arms", current_text_range, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_nested_if.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_nested_if.rs index 89bd62a084a3c..73cb8204f2096 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_nested_if.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_nested_if.rs @@ -5,7 +5,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; // Assist: merge_nested_if @@ -69,29 +69,24 @@ pub(crate) fn merge_nested_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt let nested_if_then_branch = nested_if_to_merge.then_branch()?; let then_branch_range = then_branch.syntax().text_range(); - acc.add( - AssistId("merge_nested_if", AssistKind::RefactorRewrite), - "Merge nested if", - if_range, - |edit| { - let cond_text = if has_logic_op_or(&cond) { - format!("({})", cond.syntax().text()) - } else { - cond.syntax().text().to_string() - }; + acc.add(AssistId::refactor_rewrite("merge_nested_if"), "Merge nested if", if_range, |edit| { + let cond_text = if has_logic_op_or(&cond) { + format!("({})", cond.syntax().text()) + } else { + cond.syntax().text().to_string() + }; - let nested_if_cond_text = if has_logic_op_or(&nested_if_cond) { - format!("({})", nested_if_cond.syntax().text()) - } else { - nested_if_cond.syntax().text().to_string() - }; + let nested_if_cond_text = if has_logic_op_or(&nested_if_cond) { + format!("({})", nested_if_cond.syntax().text()) + } else { + nested_if_cond.syntax().text().to_string() + }; - let replace_cond = format!("{cond_text} && {nested_if_cond_text}"); + let replace_cond = format!("{cond_text} && {nested_if_cond_text}"); - edit.replace(cond_range, replace_cond); - edit.replace(then_branch_range, nested_if_then_branch.syntax().text()); - }, - ) + edit.replace(cond_range, replace_cond); + edit.replace(then_branch_range, nested_if_then_branch.syntax().text()); + }) } /// Returns whether the given if condition has logical operators. diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs index 35571ed8341d7..7e8735bd7a246 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs @@ -7,7 +7,7 @@ use syntax::{ match_ast, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: move_bounds_to_where_clause // @@ -42,7 +42,7 @@ pub(crate) fn move_bounds_to_where_clause( let target = type_param_list.syntax().text_range(); acc.add( - AssistId("move_bounds_to_where_clause", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("move_bounds_to_where_clause"), "Move to where clause", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs index 71b1461a6ea6c..5c9318f5cf556 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs @@ -83,7 +83,7 @@ pub(crate) fn move_const_to_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> } acc.add( - AssistId("move_const_to_impl", crate::AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("move_const_to_impl"), "Move const to impl block", const_.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs index 0d6fc49e5fe3d..00469f07ba791 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs @@ -1,7 +1,4 @@ -use ide_db::{ - assists::{AssistId, AssistKind}, - base_db::AnchoredPathBuf, -}; +use ide_db::{assists::AssistId, base_db::AnchoredPathBuf}; use syntax::{AstNode, ToSmolStr, ast}; use crate::{ @@ -43,7 +40,7 @@ pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op let path = format!("../{module_name}.rs"); let dst = AnchoredPathBuf { anchor: ctx.file_id().into(), path }; acc.add( - AssistId("move_from_mod_rs", AssistKind::Refactor), + AssistId::refactor("move_from_mod_rs"), format!("Convert {module_name}/mod.rs to {module_name}.rs"), target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs index abba3de4a1fa1..644d1f6cafefc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs @@ -3,7 +3,7 @@ use syntax::{ ast::{AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat, edit::AstNodeEdit, make}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: move_guard_to_arm_body // @@ -49,7 +49,7 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext<'_>) let target = guard.syntax().text_range(); acc.add( - AssistId("move_guard_to_arm_body", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("move_guard_to_arm_body"), "Move guard to arm body", target, |edit| { @@ -118,7 +118,7 @@ pub(crate) fn move_arm_cond_to_match_guard( let (conds_blocks, tail) = parse_if_chain(if_expr)?; acc.add( - AssistId("move_arm_cond_to_match_guard", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("move_arm_cond_to_match_guard"), "Move condition to match guard", replace_node.text_range(), |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs index 5f547593b43a9..cfca89fce462d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs @@ -10,7 +10,7 @@ use syntax::{ ast::{self, HasName, edit::AstNodeEdit}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: move_module_to_file // @@ -45,7 +45,7 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext<'_>) -> let parent_module = module_def.parent(ctx.db())?; acc.add( - AssistId("move_module_to_file", AssistKind::RefactorExtract), + AssistId::refactor_extract("move_module_to_file"), "Extract module to file", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs index a19c122ddf078..ffa3894fe5a63 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs @@ -1,7 +1,4 @@ -use ide_db::{ - assists::{AssistId, AssistKind}, - base_db::AnchoredPathBuf, -}; +use ide_db::{assists::AssistId, base_db::AnchoredPathBuf}; use syntax::{AstNode, ToSmolStr, ast}; use crate::{ @@ -43,7 +40,7 @@ pub(crate) fn move_to_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti let path = format!("./{module_name}/mod.rs"); let dst = AnchoredPathBuf { anchor: ctx.file_id().into(), path }; acc.add( - AssistId("move_to_mod_rs", AssistKind::Refactor), + AssistId::refactor("move_to_mod_rs"), format!("Convert {module_name}.rs to {module_name}/mod.rs"), target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs index 813c2dd191dbd..bba28b5fc8af5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs @@ -2,7 +2,7 @@ use ide_db::imports::merge_imports::try_normalize_import; use syntax::{AstNode, ast}; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; @@ -28,14 +28,9 @@ pub(crate) fn normalize_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op let normalized_use_item = try_normalize_import(&use_item, ctx.config.insert_use.granularity.into())?; - acc.add( - AssistId("normalize_import", AssistKind::RefactorRewrite), - "Normalize import", - target, - |builder| { - builder.replace_ast(use_item, normalized_use_item); - }, - ) + acc.add(AssistId::refactor_rewrite("normalize_import"), "Normalize import", target, |builder| { + builder.replace_ast(use_item, normalized_use_item); + }) } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs index 9b81aecd7da84..1fe40f8ee83ed 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs @@ -1,6 +1,6 @@ use syntax::{AstToken, ast, ast::Radix}; -use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; +use crate::{AssistContext, AssistId, Assists, GroupLabel}; const MIN_NUMBER_OF_DIGITS_TO_FORMAT: usize = 5; @@ -42,7 +42,7 @@ pub(crate) fn reformat_number_literal(acc: &mut Assists, ctx: &AssistContext<'_> let range = literal.syntax().text_range(); acc.add_group( &group_id, - AssistId("reformat_number_literal", AssistKind::RefactorInline), + AssistId::refactor_inline("reformat_number_literal"), label, range, |builder| builder.replace(range, converted), @@ -54,7 +54,7 @@ fn remove_separators(acc: &mut Assists, literal: ast::IntNumber) -> Option<()> { let range = literal.syntax().text_range(); acc.add_group( &group_id, - AssistId("reformat_number_literal", AssistKind::RefactorInline), + AssistId::refactor_inline("reformat_number_literal"), "Remove digit separators", range, |builder| builder.replace(range, literal.text().replace('_', "")), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs index 04a19d7869c5e..6316a8f0db24d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs @@ -1,8 +1,5 @@ use hir::HirDisplay; -use ide_db::{ - assists::{AssistId, AssistKind}, - defs::Definition, -}; +use ide_db::{assists::AssistId, defs::Definition}; use stdx::to_upper_snake_case; use syntax::{ AstNode, @@ -68,7 +65,7 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_>) } acc.add( - AssistId("promote_local_to_const", AssistKind::Refactor), + AssistId::refactor("promote_local_to_const"), "Promote local to constant", let_stmt.syntax().text_range(), |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/pull_assignment_up.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/pull_assignment_up.rs index d9e71ec763d01..5f626d2957111 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/pull_assignment_up.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/pull_assignment_up.rs @@ -5,7 +5,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; @@ -68,7 +68,7 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext<'_>) -> } acc.add( - AssistId("pull_assignment_up", AssistKind::RefactorExtract), + AssistId::refactor_extract("pull_assignment_up"), "Pull assignment up", tgt.syntax().text_range(), move |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs index d8ade0eb8718f..985121780b1ab 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs @@ -1,5 +1,5 @@ use hir::{AsAssocItem, AssocItem, AssocItemContainer, ItemInNs, ModuleDef, db::HirDatabase}; -use ide_db::assists::{AssistId, AssistKind}; +use ide_db::assists::AssistId; use syntax::{AstNode, ast}; use crate::{ @@ -54,7 +54,7 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call, resolved_call); acc.add( - AssistId("qualify_method_call", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("qualify_method_call"), format!("Qualify `{ident}` method call"), range, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs index a4f066ad364f8..4c213a27f4b81 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs @@ -15,7 +15,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, GroupLabel, + AssistId, GroupLabel, assist_context::{AssistContext, Assists}, handlers::auto_import::find_importable_node, }; @@ -104,7 +104,7 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option for import in proposed_imports { acc.add_group( &group_label, - AssistId("qualify_path", AssistKind::QuickFix), + AssistId::quick_fix("qualify_path"), label(ctx.db(), candidate, &import, current_edition), range, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs index 21c697f538694..ed86380a56cdc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use syntax::{AstToken, TextRange, TextSize, ast, ast::IsString}; -use crate::{AssistContext, AssistId, AssistKind, Assists, utils::required_hashes}; +use crate::{AssistContext, AssistId, Assists, utils::required_hashes}; // Assist: make_raw_string // @@ -28,7 +28,7 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt let value = token.value().ok()?; let target = token.syntax().text_range(); acc.add( - AssistId("make_raw_string", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("make_raw_string"), "Rewrite as raw string", target, |edit| { @@ -67,7 +67,7 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> O let value = token.value().ok()?; let target = token.syntax().text_range(); acc.add( - AssistId("make_usual_string", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("make_usual_string"), "Rewrite as regular string", target, |edit| { @@ -108,7 +108,7 @@ pub(crate) fn add_hash(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> } let text_range = token.syntax().text_range(); let target = text_range; - acc.add(AssistId("add_hash", AssistKind::Refactor), "Add #", target, |edit| { + acc.add(AssistId::refactor("add_hash"), "Add #", target, |edit| { edit.insert(text_range.start() + TextSize::of('r'), "#"); edit.insert(text_range.end(), "#"); }) @@ -150,7 +150,7 @@ pub(crate) fn remove_hash(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< return None; } - acc.add(AssistId("remove_hash", AssistKind::RefactorRewrite), "Remove #", text_range, |edit| { + acc.add(AssistId::refactor_rewrite("remove_hash"), "Remove #", text_range, |edit| { edit.delete(TextRange::at(text_range.start() + TextSize::of('r'), TextSize::of('#'))); edit.delete(TextRange::new(text_range.end() - TextSize::of('#'), text_range.end())); }) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs index cbc2e4f004733..809ef6dae3122 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs @@ -5,7 +5,7 @@ use syntax::{ match_ast, ted, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: remove_dbg // @@ -42,7 +42,7 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( macro_calls.into_iter().filter_map(compute_dbg_replacement).collect::>(); acc.add( - AssistId("remove_dbg", AssistKind::QuickFix), + AssistId::quick_fix("remove_dbg"), "Remove dbg!()", replacements.iter().map(|&(range, _)| range).reduce(|acc, range| acc.cover(range))?, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_mut.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_mut.rs index 43740a5a6d5c7..1b2a8336a844f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_mut.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_mut.rs @@ -1,6 +1,6 @@ use syntax::{SyntaxKind, T}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: remove_mut // @@ -21,18 +21,13 @@ pub(crate) fn remove_mut(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( let mut_token = ctx.find_token_syntax_at_offset(T![mut])?; let target = mut_token.text_range(); - acc.add( - AssistId("remove_mut", AssistKind::Refactor), - "Remove `mut` keyword", - target, - |builder| { - let mut editor = builder.make_editor(&mut_token.parent().unwrap()); - match mut_token.next_token() { - Some(it) if it.kind() == SyntaxKind::WHITESPACE => editor.delete(it), - _ => (), - } - editor.delete(mut_token); - builder.add_file_edits(ctx.file_id(), editor); - }, - ) + acc.add(AssistId::refactor("remove_mut"), "Remove `mut` keyword", target, |builder| { + let mut editor = builder.make_editor(&mut_token.parent().unwrap()); + match mut_token.next_token() { + Some(it) if it.kind() == SyntaxKind::WHITESPACE => editor.delete(it), + _ => (), + } + editor.delete(mut_token); + builder.add_file_edits(ctx.file_id(), editor); + }) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs index 9bd8decbedcdb..f5b3e003be023 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs @@ -4,7 +4,7 @@ use syntax::{ syntax_editor::Position, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: remove_parentheses // @@ -40,7 +40,7 @@ pub(crate) fn remove_parentheses(acc: &mut Assists, ctx: &AssistContext<'_>) -> let target = parens.syntax().text_range(); acc.add( - AssistId("remove_parentheses", AssistKind::Refactor), + AssistId::refactor("remove_parentheses"), "Remove redundant parentheses", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs index 01c4eedd3e2d2..09697eb9b2966 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs @@ -12,7 +12,7 @@ use syntax::{ ast::{self, Rename}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: remove_unused_imports // @@ -126,7 +126,7 @@ pub(crate) fn remove_unused_imports(acc: &mut Assists, ctx: &AssistContext<'_>) // Peek so we terminate early if an unused use is found. Only do the rest of the work if the user selects the assist. if unused.peek().is_some() { acc.add( - AssistId("remove_unused_imports", AssistKind::QuickFix), + AssistId::quick_fix("remove_unused_imports"), "Remove all the unused imports", selected_el.text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs index 6ebc9007cf1cb..5ed1efe614b1d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs @@ -11,8 +11,7 @@ use syntax::{ use SyntaxKind::WHITESPACE; use crate::{ - AssistContext, AssistId, AssistKind, Assists, assist_context::SourceChangeBuilder, - utils::next_prev, + AssistContext, AssistId, Assists, assist_context::SourceChangeBuilder, utils::next_prev, }; // Assist: remove_unused_param @@ -79,7 +78,7 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext<'_>) -> } let parent = param.syntax().parent()?; acc.add( - AssistId("remove_unused_param", AssistKind::Refactor), + AssistId::refactor("remove_unused_param"), "Remove unused parameter", param.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs index 410e2bbbdffcd..1951d007ca4b5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs @@ -3,7 +3,7 @@ use ide_db::FxHashMap; use itertools::Itertools; use syntax::{AstNode, SmolStr, SyntaxElement, ToSmolStr, ast, syntax_editor::SyntaxEditor}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: reorder_fields // @@ -67,7 +67,7 @@ pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti } let target = record.as_ref().either(AstNode::syntax, AstNode::syntax).text_range(); acc.add( - AssistId("reorder_fields", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("reorder_fields"), "Reorder record fields", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs index e254fb9949d49..1222ba928c829 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs @@ -6,7 +6,7 @@ use syntax::{ ast::{self, HasName}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: reorder_impl_items // @@ -95,7 +95,7 @@ pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) -> let target = items.syntax().text_range(); acc.add( - AssistId("reorder_impl_items", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("reorder_impl_items"), "Sort items by trait definition", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs index 39f350fb68d5e..6b385a03625b7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs @@ -1,4 +1,4 @@ -use ide_db::assists::{AssistId, AssistKind, GroupLabel}; +use ide_db::assists::{AssistId, GroupLabel}; use syntax::{ AstNode, TextRange, ast::{self, ArithOp, BinaryOp}, @@ -132,7 +132,7 @@ impl ArithKind { ArithKind::Wrapping => "replace_arith_with_wrapping", }; - AssistId(s, AssistKind::RefactorRewrite) + AssistId::refactor_rewrite(s) } fn label(&self) -> &'static str { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index c5faf6d3e0126..691ae931f8ade 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -9,7 +9,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists, SourceChangeBuilder}, utils::{ DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items, @@ -125,101 +125,94 @@ fn add_assist( let annotated_name = adt.name()?; let label = format!("Convert to manual `impl {replace_trait_path} for {annotated_name}`"); - acc.add( - AssistId("replace_derive_with_manual_impl", AssistKind::Refactor), - label, - target, - |builder| { - let insert_after = ted::Position::after(builder.make_mut(adt.clone()).syntax()); - let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false); - let impl_def_with_items = - impl_def_from_trait(&ctx.sema, adt, &annotated_name, trait_, replace_trait_path); - update_attribute(builder, old_derives, old_tree, old_trait_path, attr); - - let trait_path = make::ty_path(replace_trait_path.clone()); - - match (ctx.config.snippet_cap, impl_def_with_items) { - (None, None) => { - let impl_def = generate_trait_impl(adt, trait_path); - if impl_is_unsafe { - ted::insert( - Position::first_child_of(impl_def.syntax()), - make::token(T![unsafe]), - ); - } + acc.add(AssistId::refactor("replace_derive_with_manual_impl"), label, target, |builder| { + let insert_after = ted::Position::after(builder.make_mut(adt.clone()).syntax()); + let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false); + let impl_def_with_items = + impl_def_from_trait(&ctx.sema, adt, &annotated_name, trait_, replace_trait_path); + update_attribute(builder, old_derives, old_tree, old_trait_path, attr); + + let trait_path = make::ty_path(replace_trait_path.clone()); + + match (ctx.config.snippet_cap, impl_def_with_items) { + (None, None) => { + let impl_def = generate_trait_impl(adt, trait_path); + if impl_is_unsafe { + ted::insert( + Position::first_child_of(impl_def.syntax()), + make::token(T![unsafe]), + ); + } - ted::insert_all( - insert_after, - vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()], + ted::insert_all( + insert_after, + vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()], + ); + } + (None, Some((impl_def, _))) => { + if impl_is_unsafe { + ted::insert( + Position::first_child_of(impl_def.syntax()), + make::token(T![unsafe]), ); } - (None, Some((impl_def, _))) => { - if impl_is_unsafe { - ted::insert( - Position::first_child_of(impl_def.syntax()), - make::token(T![unsafe]), - ); - } - ted::insert_all( - insert_after, - vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()], + ted::insert_all( + insert_after, + vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()], + ); + } + (Some(cap), None) => { + let impl_def = generate_trait_impl(adt, trait_path); + + if impl_is_unsafe { + ted::insert( + Position::first_child_of(impl_def.syntax()), + make::token(T![unsafe]), ); } - (Some(cap), None) => { - let impl_def = generate_trait_impl(adt, trait_path); - - if impl_is_unsafe { - ted::insert( - Position::first_child_of(impl_def.syntax()), - make::token(T![unsafe]), - ); - } - if let Some(l_curly) = - impl_def.assoc_item_list().and_then(|it| it.l_curly_token()) - { - builder.add_tabstop_after_token(cap, l_curly); - } + if let Some(l_curly) = impl_def.assoc_item_list().and_then(|it| it.l_curly_token()) + { + builder.add_tabstop_after_token(cap, l_curly); + } - ted::insert_all( - insert_after, - vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()], + ted::insert_all( + insert_after, + vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()], + ); + } + (Some(cap), Some((impl_def, first_assoc_item))) => { + let mut added_snippet = false; + + if impl_is_unsafe { + ted::insert( + Position::first_child_of(impl_def.syntax()), + make::token(T![unsafe]), ); } - (Some(cap), Some((impl_def, first_assoc_item))) => { - let mut added_snippet = false; - - if impl_is_unsafe { - ted::insert( - Position::first_child_of(impl_def.syntax()), - make::token(T![unsafe]), - ); - } - if let ast::AssocItem::Fn(ref func) = first_assoc_item { - if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast) - { - if m.syntax().text() == "todo!()" { - // Make the `todo!()` a placeholder - builder.add_placeholder_snippet(cap, m); - added_snippet = true; - } + if let ast::AssocItem::Fn(ref func) = first_assoc_item { + if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast) { + if m.syntax().text() == "todo!()" { + // Make the `todo!()` a placeholder + builder.add_placeholder_snippet(cap, m); + added_snippet = true; } } + } - if !added_snippet { - // If we haven't already added a snippet, add a tabstop before the generated function - builder.add_tabstop_before(cap, first_assoc_item); - } - - ted::insert_all( - insert_after, - vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()], - ); + if !added_snippet { + // If we haven't already added a snippet, add a tabstop before the generated function + builder.add_tabstop_before(cap, first_assoc_item); } - }; - }, - ) + + ted::insert_all( + insert_after, + vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()], + ); + } + }; + }) } fn impl_def_from_trait( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs index c3b753653c212..734bd1786cb6e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs @@ -13,7 +13,7 @@ use syntax::{ }; use crate::{ - AssistContext, AssistId, AssistKind, Assists, + AssistContext, AssistId, Assists, utils::{does_pat_match_variant, does_pat_variant_nested_or_literal, unwrap_trivial_block}, }; @@ -101,7 +101,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<' let let_ = if pat_seen { " let" } else { "" }; acc.add( - AssistId("replace_if_let_with_match", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_if_let_with_match"), format!("Replace if{let_} with match"), available_range, move |builder| { @@ -249,7 +249,7 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<' _ => " let", }; acc.add( - AssistId("replace_match_with_if_let", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_match_with_if_let"), format!("Replace match with if{let_}"), match_expr.syntax().text_range(), move |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs index c49f285d8e9d3..e933bcc40dbbb 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs @@ -4,7 +4,7 @@ use syntax::{ ted, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: replace_is_some_with_if_let_some // @@ -56,7 +56,7 @@ pub(crate) fn replace_is_method_with_if_let_method( }; acc.add( - AssistId(assist_id, AssistKind::RefactorRewrite), + AssistId::refactor_rewrite(assist_id), message, call_expr.syntax().text_range(), |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs index 34bbd6ba5be7b..a2dcbf948d8de 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs @@ -4,7 +4,7 @@ use syntax::{ ast::{self, edit::IndentLevel, edit_in_place::Indent, syntax_factory::SyntaxFactory}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: replace_let_with_if_let // @@ -38,7 +38,7 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext<'_> let target = let_kw.text_range(); acc.add( - AssistId("replace_let_with_if_let", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_let_with_if_let"), "Replace let with if let", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs index 88b56ebb4b1cd..afac6cd724ce0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs @@ -1,4 +1,4 @@ -use ide_db::assists::{AssistId, AssistKind}; +use ide_db::assists::AssistId; use syntax::{ AstNode, ast::{self, Expr, HasArgList, make}, @@ -60,7 +60,7 @@ pub(crate) fn replace_with_lazy_method(acc: &mut Assists, ctx: &AssistContext<'_ )?; acc.add( - AssistId("replace_with_lazy_method", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_with_lazy_method"), format!("Replace {method_name} with {method_name_lazy}"), call.syntax().text_range(), |builder| { @@ -136,7 +136,7 @@ pub(crate) fn replace_with_eager_method(acc: &mut Assists, ctx: &AssistContext<' )?; acc.add( - AssistId("replace_with_eager_method", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_with_eager_method"), format!("Replace {method_name} with {method_name_eager}"), call.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs index f99394e8775e0..3cd7b58f4ddd4 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs @@ -14,7 +14,7 @@ use syntax::{ match_ast, ted, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: replace_named_generic_with_impl // @@ -70,7 +70,7 @@ pub(crate) fn replace_named_generic_with_impl( let target = type_param.syntax().text_range(); acc.add( - AssistId("replace_named_generic_with_impl", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_named_generic_with_impl"), "Replace named generic with impl trait", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs index 08a4d28e9fea9..c067747bc1bb1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs @@ -9,7 +9,7 @@ use syntax::{ match_ast, ted, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: replace_qualified_name_with_use // @@ -75,7 +75,7 @@ pub(crate) fn replace_qualified_name_with_use( let scope = ImportScope::find_insert_use_container(original_path.syntax(), &ctx.sema)?; let target = original_path.syntax().text_range(); acc.add( - AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_qualified_name_with_use"), "Replace qualified path with use", target, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs index 176b4e4af088d..0eab70424a1bc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs @@ -5,7 +5,7 @@ use syntax::{ ast::IsString, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: replace_string_with_char // @@ -33,7 +33,7 @@ pub(crate) fn replace_string_with_char(acc: &mut Assists, ctx: &AssistContext<'_ let quote_offsets = token.quote_offsets()?; acc.add( - AssistId("replace_string_with_char", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_string_with_char"), "Replace string with char", target, |edit| { @@ -67,7 +67,7 @@ pub(crate) fn replace_char_with_string(acc: &mut Assists, ctx: &AssistContext<'_ let target = token.text_range(); acc.add( - AssistId("replace_char_with_string", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_char_with_string"), "Replace char with string", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs index 93dfe48ebcab8..3fd59f3b69daa 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs @@ -1,9 +1,6 @@ use std::iter; -use ide_db::{ - assists::{AssistId, AssistKind}, - ty_filter::TryEnum, -}; +use ide_db::{assists::AssistId, ty_filter::TryEnum}; use syntax::{ AstNode, T, ast::{ @@ -48,7 +45,7 @@ pub(crate) fn replace_try_expr_with_match( let target = qm_kw_parent.syntax().text_range(); acc.add( - AssistId("replace_try_expr_with_match", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_try_expr_with_match"), "Replace try expression with match", target, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs index 39ebca25a90f6..311cbf6ad3fa2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs @@ -5,7 +5,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; @@ -74,7 +74,7 @@ pub(crate) fn replace_turbofish_with_explicit_type( let ident_range = let_stmt.pat()?.syntax().text_range(); return acc.add( - AssistId("replace_turbofish_with_explicit_type", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_turbofish_with_explicit_type"), "Replace turbofish with explicit type", TextRange::new(initializer_start, turbofish_range.end()), |builder| { @@ -89,7 +89,7 @@ pub(crate) fn replace_turbofish_with_explicit_type( let underscore_range = t.syntax().text_range(); return acc.add( - AssistId("replace_turbofish_with_explicit_type", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("replace_turbofish_with_explicit_type"), "Replace `_` with turbofish type", turbofish_range, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs index 73dfbf023792c..e973e70345dc2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs @@ -7,7 +7,7 @@ use syntax::{ ast::{self, HasName}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists, utils::get_methods}; +use crate::{AssistContext, AssistId, Assists, utils::get_methods}; // Assist: sort_items // @@ -126,20 +126,15 @@ impl AddRewrite for Assists { new: Vec, target: &SyntaxNode, ) -> Option<()> { - self.add( - AssistId("sort_items", AssistKind::RefactorRewrite), - label, - target.text_range(), - |builder| { - let mut editor = builder.make_editor(target); - - old.into_iter() - .zip(new) - .for_each(|(old, new)| editor.replace(old.syntax(), new.syntax())); - - builder.add_file_edits(builder.file_id, editor) - }, - ) + self.add(AssistId::refactor_rewrite("sort_items"), label, target.text_range(), |builder| { + let mut editor = builder.make_editor(target); + + old.into_iter() + .zip(new) + .for_each(|(old, new)| editor.replace(old.syntax(), new.syntax())); + + builder.add_file_edits(builder.file_id, editor) + }) } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/split_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/split_import.rs index 63371ddf9fbc5..1729a0667c0a2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/split_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/split_import.rs @@ -1,6 +1,6 @@ use syntax::{AstNode, T, ast}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: split_import // @@ -29,7 +29,7 @@ pub(crate) fn split_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option } let target = colon_colon.text_range(); - acc.add(AssistId("split_import", AssistKind::RefactorRewrite), "Split import", target, |edit| { + acc.add(AssistId::refactor_rewrite("split_import"), "Split import", target, |edit| { let use_tree = edit.make_mut(use_tree.clone()); let path = edit.make_mut(path); use_tree.split_prefix(&path); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs index 7b2598b45575d..86121e7fc8c2c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs @@ -1,7 +1,7 @@ //! Term search assist use hir::term_search::{TermSearchConfig, TermSearchCtx}; use ide_db::{ - assists::{AssistId, AssistKind, GroupLabel}, + assists::{AssistId, GroupLabel}, famous_defs::FamousDefs, }; @@ -68,7 +68,7 @@ pub(crate) fn term_search(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< for code in paths { acc.add_group( &GroupLabel(String::from("Term search")), - AssistId("term_search", AssistKind::Generate), + AssistId::generate("term_search"), format!("Replace {macro_name}!() with {code}"), goal_range, |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs index 9f45b2898a769..eed070cb07dd6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs @@ -1,8 +1,5 @@ use hir::ModuleDef; -use ide_db::{ - assists::{AssistId, AssistKind}, - famous_defs::FamousDefs, -}; +use ide_db::{assists::AssistId, famous_defs::FamousDefs}; use syntax::{ AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, ast::{self, HasGenericArgs, HasVisibility}, @@ -60,7 +57,7 @@ pub(crate) fn sugar_impl_future_into_async( let future_output = unwrap_future_output(main_trait_path)?; acc.add( - AssistId("sugar_impl_future_into_async", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("sugar_impl_future_into_async"), "Convert `impl Future` into async", function.syntax().text_range(), |builder| { @@ -145,7 +142,7 @@ pub(crate) fn desugar_async_into_impl_future( let trait_path = trait_path.display(ctx.db(), edition); acc.add( - AssistId("desugar_async_into_impl_future", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("desugar_async_into_impl_future"), "Convert async into `impl Future`", function.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs index c1ea7dc4c78c5..7a29928af93f7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs @@ -3,7 +3,7 @@ use syntax::{ ast::{self, HasAttrs}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists, utils::test_related_attribute_syn}; +use crate::{AssistContext, AssistId, Assists, utils::test_related_attribute_syn}; // Assist: toggle_ignore // @@ -30,13 +30,13 @@ pub(crate) fn toggle_ignore(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio match has_ignore_attribute(&func) { None => acc.add( - AssistId("toggle_ignore", AssistKind::None), + AssistId::none("toggle_ignore"), "Ignore this test", attr.syntax().text_range(), |builder| builder.insert(attr.syntax().text_range().end(), "\n#[ignore]"), ), Some(ignore_attr) => acc.add( - AssistId("toggle_ignore", AssistKind::None), + AssistId::none("toggle_ignore"), "Re-enable this test", ignore_attr.syntax().text_range(), |builder| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs index 80834abecc95a..109269bd6e611 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs @@ -1,4 +1,4 @@ -use ide_db::assists::{AssistId, AssistKind}; +use ide_db::assists::AssistId; use syntax::{ AstNode, T, ast::{self, make}, @@ -63,7 +63,7 @@ pub(crate) fn toggle_macro_delimiter(acc: &mut Assists, ctx: &AssistContext<'_>) }; acc.add( - AssistId("toggle_macro_delimiter", AssistKind::Refactor), + AssistId::refactor("toggle_macro_delimiter"), match token { MacroDelims::LPar | MacroDelims::RPar => "Replace delimiters with braces", MacroDelims::LBra | MacroDelims::RBra => "Replace delimiters with parentheses", diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs index 8b6aef02eccd0..31ff47a05492e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs @@ -5,7 +5,7 @@ use syntax::{ ted::{self, Position}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: unmerge_match_arm // @@ -47,7 +47,7 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O let old_parent_range = new_parent.text_range(); acc.add( - AssistId("unmerge_match_arm", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("unmerge_match_arm"), "Unmerge match arm", pipe_token.text_range(), |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs index 7f2dd19ce0755..805a7344494aa 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs @@ -5,7 +5,7 @@ use syntax::{ }; use crate::{ - AssistId, AssistKind, + AssistId, assist_context::{AssistContext, Assists}, }; @@ -43,7 +43,7 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< }; let target = tree.syntax().text_range(); - acc.add(AssistId("unmerge_use", AssistKind::RefactorRewrite), label, target, |builder| { + acc.add(AssistId::refactor_rewrite("unmerge_use"), label, target, |builder| { let new_use = make::use_( use_.visibility(), make::use_tree(path, tree.use_tree_list(), tree.rename(), tree.star_token().is_some()), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs index f3ae70160bf3a..ac10a829bbf1b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs @@ -1,6 +1,6 @@ use ide_db::{ EditionedFileId, - assists::{AssistId, AssistKind}, + assists::AssistId, defs::Definition, search::{FileReference, FileReferenceNode}, syntax_helpers::node_ext::full_path_of_name_ref, @@ -60,7 +60,7 @@ pub(crate) fn unnecessary_async(acc: &mut Assists, ctx: &AssistContext<'_>) -> O // Otherwise, we may remove the `async` keyword. acc.add( - AssistId("unnecessary_async", AssistKind::QuickFix), + AssistId::quick_fix("unnecessary_async"), "Remove unnecessary async", async_range, |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs index 712c8c3d14d0f..ebb8ef99100e7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs @@ -4,7 +4,7 @@ use syntax::{ ast::{self, AstNode, HasArgList, prec::ExprPrecedence}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: unqualify_method_call // @@ -69,7 +69,7 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) ); acc.add( - AssistId("unqualify_method_call", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("unqualify_method_call"), "Unqualify method call", call.syntax().text_range(), |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs index 80d8cebff5bb3..a83f6835ca615 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs @@ -7,7 +7,7 @@ use syntax::{ }, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: unwrap_block // @@ -27,9 +27,8 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // } // ``` pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - let assist_id = AssistId("unwrap_block", AssistKind::RefactorRewrite); + let assist_id = AssistId::refactor_rewrite("unwrap_block"); let assist_label = "Unwrap block"; - let l_curly_token = ctx.find_token_syntax_at_offset(T!['{'])?; let mut block = ast::BlockExpr::cast(l_curly_token.parent_ancestors().nth(1)?)?; let target = block.syntax().text_range(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs index f6eb68524f2df..8804fea72f86b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs @@ -9,7 +9,7 @@ use syntax::{ match_ast, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: unwrap_option_return_type // @@ -187,7 +187,7 @@ impl UnwrapperKind { UnwrapperKind::Result => "unwrap_result_return_type", }; - AssistId(s, AssistKind::RefactorRewrite) + AssistId::refactor_rewrite(s) } fn label(&self) -> &'static str { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs index 55053ac97dc6e..ecfecbb04ff22 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs @@ -3,7 +3,7 @@ use syntax::{ ast::{self, edit::AstNodeEdit}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: unwrap_tuple // @@ -56,7 +56,7 @@ pub(crate) fn unwrap_tuple(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option let parent = let_kw.parent()?; acc.add( - AssistId("unwrap_tuple", AssistKind::RefactorRewrite), + AssistId::refactor_rewrite("unwrap_tuple"), "Unwrap tuple", let_kw.text_range(), |edit| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs index 8857c446f6d53..a0440680d010a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs @@ -12,7 +12,7 @@ use syntax::{ match_ast, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: wrap_return_type_in_option // @@ -155,7 +155,7 @@ impl WrapperKind { WrapperKind::Result => "wrap_return_type_in_result", }; - AssistId(s, AssistKind::RefactorRewrite) + AssistId::refactor_rewrite(s) } fn label(&self) -> &'static str { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs index 717c68d04e05b..1068d5d4cd57c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs @@ -6,7 +6,7 @@ use syntax::{ ted::{self, Position}, }; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, Assists}; // Assist: wrap_unwrap_cfg_attr // @@ -210,7 +210,7 @@ fn wrap_derive( }; acc.add( - AssistId("wrap_unwrap_cfg_attr", AssistKind::Refactor), + AssistId::refactor("wrap_unwrap_cfg_attr"), format!("Wrap #[derive({path_text})] in `cfg_attr`",), range, handle_source_change, @@ -267,7 +267,7 @@ fn wrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>, attr: ast::Attr) -> } }; acc.add( - AssistId("wrap_unwrap_cfg_attr", AssistKind::Refactor), + AssistId::refactor("wrap_unwrap_cfg_attr"), "Convert to `cfg_attr`", range, handle_source_change, @@ -336,7 +336,7 @@ fn unwrap_cfg_attr(acc: &mut Assists, attr: ast::Attr) -> Option<()> { f.replace(range, inner_attrs); }; acc.add( - AssistId("wrap_unwrap_cfg_attr", AssistKind::Refactor), + AssistId::refactor("wrap_unwrap_cfg_attr"), "Extract Inner Attributes from `cfg_attr`", range, handle_source_change, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs index a23461e69a5fc..13e061724e4d5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -504,6 +504,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_variable", RefactorExtract, + None, ), label: "Extract into variable", group: Some( @@ -524,6 +525,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_constant", RefactorExtract, + None, ), label: "Extract into constant", group: Some( @@ -544,6 +546,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_static", RefactorExtract, + None, ), label: "Extract into static", group: Some( @@ -564,6 +567,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_function", RefactorExtract, + None, ), label: "Extract into function", group: Some( @@ -586,6 +590,7 @@ pub fn test_some_range(a: int) -> bool { AssistResolveStrategy::Single(SingleResolve { assist_id: "SOMETHING_MISMATCHING".to_owned(), assist_kind: AssistKind::RefactorExtract, + assist_subtype: None, }), frange.into(), ); @@ -598,6 +603,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_variable", RefactorExtract, + None, ), label: "Extract into variable", group: Some( @@ -618,6 +624,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_constant", RefactorExtract, + None, ), label: "Extract into constant", group: Some( @@ -638,6 +645,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_static", RefactorExtract, + None, ), label: "Extract into static", group: Some( @@ -658,6 +666,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_function", RefactorExtract, + None, ), label: "Extract into function", group: Some( @@ -680,6 +689,7 @@ pub fn test_some_range(a: int) -> bool { AssistResolveStrategy::Single(SingleResolve { assist_id: "extract_variable".to_owned(), assist_kind: AssistKind::RefactorExtract, + assist_subtype: None, }), frange.into(), ); @@ -692,6 +702,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_variable", RefactorExtract, + None, ), label: "Extract into variable", group: Some( @@ -758,6 +769,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_constant", RefactorExtract, + None, ), label: "Extract into constant", group: Some( @@ -778,6 +790,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_static", RefactorExtract, + None, ), label: "Extract into static", group: Some( @@ -798,6 +811,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_function", RefactorExtract, + None, ), label: "Extract into function", group: Some( @@ -824,6 +838,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_variable", RefactorExtract, + None, ), label: "Extract into variable", group: Some( @@ -890,6 +905,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_constant", RefactorExtract, + None, ), label: "Extract into constant", group: Some( @@ -960,6 +976,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_static", RefactorExtract, + None, ), label: "Extract into static", group: Some( @@ -1030,6 +1047,7 @@ pub fn test_some_range(a: int) -> bool { id: AssistId( "extract_function", RefactorExtract, + None, ), label: "Extract into function", group: Some( diff --git a/src/tools/rust-analyzer/crates/ide-db/src/assists.rs b/src/tools/rust-analyzer/crates/ide-db/src/assists.rs index 7868f6148e5a6..9ff3e10a1e7c6 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/assists.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/assists.rs @@ -107,6 +107,36 @@ impl FromStr for AssistKind { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct AssistId(pub &'static str, pub AssistKind, pub Option); +impl AssistId { + pub fn none(id: &'static str) -> AssistId { + AssistId(id, AssistKind::None, None) + } + + pub fn quick_fix(id: &'static str) -> AssistId { + AssistId(id, AssistKind::QuickFix, None) + } + + pub fn generate(id: &'static str) -> AssistId { + AssistId(id, AssistKind::Generate, None) + } + + pub fn refactor(id: &'static str) -> AssistId { + AssistId(id, AssistKind::Refactor, None) + } + + pub fn refactor_extract(id: &'static str) -> AssistId { + AssistId(id, AssistKind::RefactorExtract, None) + } + + pub fn refactor_inline(id: &'static str) -> AssistId { + AssistId(id, AssistKind::RefactorInline, None) + } + + pub fn refactor_rewrite(id: &'static str) -> AssistId { + AssistId(id, AssistKind::RefactorRewrite, None) + } +} + /// A way to control how many assist to resolve during the assist resolution. /// When an assist is resolved, its edits are calculated that might be costly to always do by default. #[derive(Debug)] diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs index 79231685c0154..9f1901ff95eb6 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs @@ -1,7 +1,7 @@ use hir::{HasSource, HirDisplay, db::ExpandDatabase}; use ide_db::text_edit::TextRange; use ide_db::{ - assists::{Assist, AssistId, AssistKind}, + assists::{Assist, AssistId}, label::Label, source_change::SourceChangeBuilder, }; @@ -97,7 +97,7 @@ fn quickfix_for_redundant_assoc_item( add_assoc_item_def(&mut source_change_builder)?; Some(vec![Assist { - id: AssistId("add assoc item def into trait def", AssistKind::QuickFix), + id: AssistId::quick_fix("add assoc item def into trait def"), label: Label::new("Add assoc item def into trait def".to_owned()), group: None, target: range, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs index e817929390225..0bef91f3375e4 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs @@ -5,7 +5,7 @@ use hir::{ }; use ide_db::text_edit::TextEdit; use ide_db::{ - assists::{Assist, AssistId, AssistKind, GroupLabel}, + assists::{Assist, AssistId, GroupLabel}, label::Label, source_change::SourceChange, }; @@ -78,7 +78,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option }) .unique() .map(|code| Assist { - id: AssistId("typed-hole", AssistKind::QuickFix), + id: AssistId::quick_fix("typed-hole"), label: Label::new(format!("Replace `_` with `{code}`")), group: Some(GroupLabel("Replace `_` with a term".to_owned())), target: original_range.range, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs index 7020fce24ff3a..986ebb8818f41 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs @@ -4,7 +4,7 @@ use either::Either; use hir::{Adt, FileRange, HasSource, HirDisplay, InFile, Struct, Union, db::ExpandDatabase}; use ide_db::text_edit::TextEdit; use ide_db::{ - assists::{Assist, AssistId, AssistKind}, + assists::{Assist, AssistId}, helpers::is_editable_crate, label::Label, source_change::{SourceChange, SourceChangeBuilder}, @@ -122,7 +122,7 @@ fn add_variant_to_union( let mut src_change_builder = SourceChangeBuilder::new(range.file_id); src_change_builder.insert(offset, record_field); Some(Assist { - id: AssistId("add-variant-to-union", AssistKind::QuickFix), + id: AssistId::quick_fix("add-variant-to-union"), label: Label::new("Add field to union".to_owned()), group: None, target: error_range.range, @@ -170,7 +170,7 @@ fn add_field_to_struct_fix( // FIXME: Allow for choosing a visibility modifier see https://github.com/rust-lang/rust-analyzer/issues/11563 src_change_builder.insert(offset, record_field); Some(Assist { - id: AssistId("add-field-to-record-struct", AssistKind::QuickFix), + id: AssistId::quick_fix("add-field-to-record-struct"), label: Label::new("Add field to Record Struct".to_owned()), group: None, target: error_range.range, @@ -206,7 +206,7 @@ fn add_field_to_struct_fix( src_change_builder.replace(semi_colon.text_range(), record_field_list.to_string()); Some(Assist { - id: AssistId("convert-unit-struct-to-record-struct", AssistKind::QuickFix), + id: AssistId::quick_fix("convert-unit-struct-to-record-struct"), label: Label::new("Convert Unit Struct to Record Struct and add field".to_owned()), group: None, target: error_range.range, @@ -265,7 +265,7 @@ fn method_fix( let expr = expr_ptr.value.to_node(&root); let FileRange { range, file_id } = ctx.sema.original_range_opt(expr.syntax())?; Some(Assist { - id: AssistId("expected-field-found-method-call-fix", AssistKind::QuickFix), + id: AssistId::quick_fix("expected-field-found-method-call-fix"), label: Label::new("Use parentheses to call the method".to_owned()), group: None, target: range, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs index e6e86214bba27..b5d7aa113a10a 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -1,7 +1,7 @@ use hir::{FileRange, HirDisplay, InFile, db::ExpandDatabase}; use ide_db::text_edit::TextEdit; use ide_db::{ - assists::{Assist, AssistId, AssistKind}, + assists::{Assist, AssistId}, label::Label, source_change::SourceChange, }; @@ -96,7 +96,7 @@ fn field_fix( _ => return None, }; Some(Assist { - id: AssistId("expected-method-found-field-fix", AssistKind::QuickFix), + id: AssistId::quick_fix("expected-method-found-field-fix"), label: Label::new("Use parentheses to call the value of the field".to_owned()), group: None, target: range, @@ -175,7 +175,7 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) - let file_id = ctx.sema.original_range_opt(call.receiver()?.syntax())?.file_id; Some(Assist { - id: AssistId("method_call_to_assoc_func_call_fix", AssistKind::QuickFix), + id: AssistId::quick_fix("method_call_to_assoc_func_call_fix"), label: Label::new(format!( "Use associated func call instead: `{assoc_func_call_expr_string}`" )), diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs index c412536d749e0..5857b1dab2fbb 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs @@ -2,7 +2,7 @@ use hir::Name; use ide_db::text_edit::TextEdit; use ide_db::{ FileRange, RootDatabase, - assists::{Assist, AssistId, AssistKind}, + assists::{Assist, AssistId}, label::Label, source_change::SourceChange, }; @@ -68,7 +68,7 @@ fn fixes( } Some(vec![Assist { - id: AssistId("unscore_unused_variable_name", AssistKind::QuickFix), + id: AssistId::quick_fix("unscore_unused_variable_name"), label: Label::new(format!( "Rename unused {} to _{}", var_name.display(db, edition), diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index 7cba58f66baed..a8d9b67b4ea3c 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -89,7 +89,7 @@ use hir::{ use ide_db::base_db::salsa::AsDynDatabase; use ide_db::{ EditionedFileId, FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, Severity, SnippetCap, - assists::{Assist, AssistId, AssistKind, AssistResolveStrategy}, + assists::{Assist, AssistId, AssistResolveStrategy}, base_db::{ReleaseChannel, RootQueryDb as _}, generated::lints::{CLIPPY_LINT_GROUPS, DEFAULT_LINT_GROUPS, DEFAULT_LINTS, Lint, LintGroup}, imports::insert_use::InsertUseConfig, @@ -992,7 +992,7 @@ fn fix(id: &'static str, label: &str, source_change: SourceChange, target: TextR fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist { assert!(!id.contains(' ')); Assist { - id: AssistId(id, AssistKind::QuickFix), + id: AssistId::quick_fix(id), label: Label::new(label.to_owned()), group: None, target, diff --git a/src/tools/rust-analyzer/crates/ide/src/ssr.rs b/src/tools/rust-analyzer/crates/ide/src/ssr.rs index 5e439bd38a58a..0e06b8e2daeb6 100644 --- a/src/tools/rust-analyzer/crates/ide/src/ssr.rs +++ b/src/tools/rust-analyzer/crates/ide/src/ssr.rs @@ -2,7 +2,7 @@ //! assist in ide_assists because that would require the ide_assists crate //! depend on the ide_ssr crate. -use ide_assists::{Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel}; +use ide_assists::{Assist, AssistId, AssistResolveStrategy, GroupLabel}; use ide_db::{FileRange, RootDatabase, label::Label, source_change::SourceChange}; pub(crate) fn ssr_assists( @@ -16,7 +16,7 @@ pub(crate) fn ssr_assists( Some(ssr_data) => ssr_data, None => return ssr_assists, }; - let id = AssistId("ssr", AssistKind::RefactorRewrite); + let id = AssistId::refactor_rewrite("ssr"); let (source_change_for_file, source_change_for_workspace) = if resolve.should_resolve(&id) { let edits = match_finder.edits(); @@ -120,6 +120,7 @@ mod tests { id: AssistId( "ssr", RefactorRewrite, + None, ), label: "Apply SSR in file", group: Some( @@ -163,6 +164,7 @@ mod tests { id: AssistId( "ssr", RefactorRewrite, + None, ), label: "Apply SSR in workspace", group: Some( @@ -240,6 +242,7 @@ mod tests { id: AssistId( "ssr", RefactorRewrite, + None, ), label: "Apply SSR in file", group: Some( @@ -260,6 +263,7 @@ mod tests { id: AssistId( "ssr", RefactorRewrite, + None, ), label: "Apply SSR in workspace", group: Some( From f386d92c409dc44f0931cb2a9f2b52d1c3538280 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Sat, 22 Mar 2025 18:57:37 +0900 Subject: [PATCH 0229/2248] fix: Handle multiple `#[repr(..)]` attrs correctly --- .../rust-analyzer/crates/hir-def/src/attr.rs | 147 ++++++++++-------- .../rust-analyzer/crates/hir-def/src/lib.rs | 3 - .../crates/hir-ty/src/layout/tests.rs | 12 ++ 3 files changed, 91 insertions(+), 71 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 78f26d6756907..005d5830ea7f4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -233,7 +233,12 @@ impl Attrs { } pub fn repr(&self) -> Option { - self.by_key(&sym::repr).tt_values().find_map(parse_repr_tt) + self.by_key(&sym::repr).tt_values().filter_map(parse_repr_tt).fold(None, |acc, repr| { + acc.map_or(Some(repr), |mut acc| { + merge_repr(&mut acc, repr); + Some(acc) + }) + }) } } @@ -260,6 +265,19 @@ fn parse_rustc_legacy_const_generics(tt: &crate::tt::TopSubtree) -> Box<[u32]> { indices.into_boxed_slice() } +fn merge_repr(this: &mut ReprOptions, other: ReprOptions) { + let ReprOptions { int, align, pack, flags, field_shuffle_seed: _ } = this; + flags.insert(other.flags); + *align = (*align).max(other.align); + *pack = match (*pack, other.pack) { + (Some(pack), None) | (None, Some(pack)) => Some(pack), + _ => (*pack).min(other.pack), + }; + if other.int.is_some() { + *int = other.int; + } +} + fn parse_repr_tt(tt: &crate::tt::TopSubtree) -> Option { use crate::builtin_type::{BuiltinInt, BuiltinUint}; use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; @@ -269,83 +287,76 @@ fn parse_repr_tt(tt: &crate::tt::TopSubtree) -> Option { _ => return None, } - let mut flags = ReprFlags::empty(); - let mut int = None; - let mut max_align: Option = None; - let mut min_pack: Option = None; - + let mut acc = ReprOptions::default(); let mut tts = tt.iter(); while let Some(tt) = tts.next() { - if let TtElement::Leaf(tt::Leaf::Ident(ident)) = tt { - flags.insert(match &ident.sym { - s if *s == sym::packed => { - let pack = if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { - tts.next(); - if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() { - lit.symbol.as_str().parse().unwrap_or_default() - } else { - 0 - } + let TtElement::Leaf(tt::Leaf::Ident(ident)) = tt else { + continue; + }; + let repr = match &ident.sym { + s if *s == sym::packed => { + let pack = if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { + tts.next(); + if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() { + lit.symbol.as_str().parse().unwrap_or_default() } else { 0 - }; - let pack = Align::from_bytes(pack).unwrap_or(Align::ONE); - min_pack = - Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack }); - ReprFlags::empty() - } - s if *s == sym::align => { - if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { - tts.next(); - if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() { - if let Ok(align) = lit.symbol.as_str().parse() { - let align = Align::from_bytes(align).ok(); - max_align = max_align.max(align); - } + } + } else { + 0 + }; + let pack = Some(Align::from_bytes(pack).unwrap_or(Align::ONE)); + ReprOptions { pack, ..Default::default() } + } + s if *s == sym::align => { + let mut align = None; + if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { + tts.next(); + if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() { + if let Ok(a) = lit.symbol.as_str().parse() { + align = Align::from_bytes(a).ok(); } } - ReprFlags::empty() } - s if *s == sym::C => ReprFlags::IS_C, - s if *s == sym::transparent => ReprFlags::IS_TRANSPARENT, - s if *s == sym::simd => ReprFlags::IS_SIMD, - repr => { - if let Some(builtin) = BuiltinInt::from_suffix_sym(repr) - .map(Either::Left) - .or_else(|| BuiltinUint::from_suffix_sym(repr).map(Either::Right)) - { - int = Some(match builtin { - Either::Left(bi) => match bi { - BuiltinInt::Isize => IntegerType::Pointer(true), - BuiltinInt::I8 => IntegerType::Fixed(Integer::I8, true), - BuiltinInt::I16 => IntegerType::Fixed(Integer::I16, true), - BuiltinInt::I32 => IntegerType::Fixed(Integer::I32, true), - BuiltinInt::I64 => IntegerType::Fixed(Integer::I64, true), - BuiltinInt::I128 => IntegerType::Fixed(Integer::I128, true), - }, - Either::Right(bu) => match bu { - BuiltinUint::Usize => IntegerType::Pointer(false), - BuiltinUint::U8 => IntegerType::Fixed(Integer::I8, false), - BuiltinUint::U16 => IntegerType::Fixed(Integer::I16, false), - BuiltinUint::U32 => IntegerType::Fixed(Integer::I32, false), - BuiltinUint::U64 => IntegerType::Fixed(Integer::I64, false), - BuiltinUint::U128 => IntegerType::Fixed(Integer::I128, false), - }, - }); - } - ReprFlags::empty() + ReprOptions { align, ..Default::default() } + } + s if *s == sym::C => ReprOptions { flags: ReprFlags::IS_C, ..Default::default() }, + s if *s == sym::transparent => { + ReprOptions { flags: ReprFlags::IS_TRANSPARENT, ..Default::default() } + } + s if *s == sym::simd => ReprOptions { flags: ReprFlags::IS_SIMD, ..Default::default() }, + repr => { + let mut int = None; + if let Some(builtin) = BuiltinInt::from_suffix_sym(repr) + .map(Either::Left) + .or_else(|| BuiltinUint::from_suffix_sym(repr).map(Either::Right)) + { + int = Some(match builtin { + Either::Left(bi) => match bi { + BuiltinInt::Isize => IntegerType::Pointer(true), + BuiltinInt::I8 => IntegerType::Fixed(Integer::I8, true), + BuiltinInt::I16 => IntegerType::Fixed(Integer::I16, true), + BuiltinInt::I32 => IntegerType::Fixed(Integer::I32, true), + BuiltinInt::I64 => IntegerType::Fixed(Integer::I64, true), + BuiltinInt::I128 => IntegerType::Fixed(Integer::I128, true), + }, + Either::Right(bu) => match bu { + BuiltinUint::Usize => IntegerType::Pointer(false), + BuiltinUint::U8 => IntegerType::Fixed(Integer::I8, false), + BuiltinUint::U16 => IntegerType::Fixed(Integer::I16, false), + BuiltinUint::U32 => IntegerType::Fixed(Integer::I32, false), + BuiltinUint::U64 => IntegerType::Fixed(Integer::I64, false), + BuiltinUint::U128 => IntegerType::Fixed(Integer::I128, false), + }, + }); } - }) - } + ReprOptions { int, ..Default::default() } + } + }; + merge_repr(&mut acc, repr); } - Some(ReprOptions { - int, - align: max_align, - pack: min_pack, - flags, - field_shuffle_seed: rustc_hashes::Hash64::ZERO, - }) + Some(acc) } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 615bd33feb6fa..fad0b56f336bc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -24,9 +24,6 @@ extern crate rustc_hashes; #[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_abi as rustc_abi; -#[cfg(not(feature = "in-rust-tree"))] -extern crate ra_ap_rustc_hashes as rustc_hashes; - pub mod db; pub mod attr; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index f671b30380724..bf93dad25d198 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs @@ -284,6 +284,18 @@ fn repr_packed() { check_size_and_align("#[repr(Rust, packed(5))] struct Goal(i32);", "", 4, 1); } +#[test] +fn multiple_repr_attrs() { + size_and_align!( + #[repr(C)] + #[repr(packed)] + struct Goal { + id: i32, + u: u8, + } + ) +} + #[test] fn generic() { size_and_align! { From 82381608c993262b562e56b8b52ff47b42650c8e Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 16 Feb 2025 16:05:02 +0100 Subject: [PATCH 0230/2248] Lint more cases in `collapsible_if` Replace the use of `Sugg::ast()` which prevented combining `if` together when they contained comments by span manipulation. A new configuration option `lint_commented_code`, which is `true` by default, opts out from this behavior. --- CHANGELOG.md | 1 + book/src/lint_configuration.md | 11 ++ clippy_config/src/conf.rs | 4 + clippy_lints/src/collapsible_if.rs | 186 +++++++++++------- clippy_lints/src/lib.rs | 2 +- tests/ui-toml/collapsible_if/clippy.toml | 1 + .../collapsible_if/collapsible_if.fixed | 34 ++++ .../ui-toml/collapsible_if/collapsible_if.rs | 38 ++++ .../collapsible_if/collapsible_if.stderr | 80 ++++++++ .../toml_unknown_key/conf_unknown_key.stderr | 3 + tests/ui/collapsible_if.fixed | 102 +++++----- tests/ui/collapsible_if.rs | 52 ++--- tests/ui/collapsible_if.stderr | 91 ++++++--- 13 files changed, 410 insertions(+), 195 deletions(-) create mode 100644 tests/ui-toml/collapsible_if/clippy.toml create mode 100644 tests/ui-toml/collapsible_if/collapsible_if.fixed create mode 100644 tests/ui-toml/collapsible_if/collapsible_if.rs create mode 100644 tests/ui-toml/collapsible_if/collapsible_if.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bf4b51ff0fe2..1babf0bd61440 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6362,6 +6362,7 @@ Released 2018-09-13 [`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold [`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability [`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold +[`lint-commented-code`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-commented-code [`lint-inconsistent-struct-field-initializers`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-inconsistent-struct-field-initializers [`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold [`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 3726d6e8a8691..36f3985fc0281 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -613,6 +613,17 @@ The maximum size of the `Err`-variant in a `Result` returned from a function * [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err) +## `lint-commented-code` +Whether collapsible `if` chains are linted if they contain comments inside the parts +that would be collapsed. + +**Default Value:** `false` + +--- +**Affected lints:** +* [`collapsible_if`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if) + + ## `lint-inconsistent-struct-field-initializers` Whether to suggest reordering constructor fields when initializers are present. diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 798f8b3aa5a90..eeb462dedc974 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -549,6 +549,10 @@ define_Conf! { /// The maximum size of the `Err`-variant in a `Result` returned from a function #[lints(result_large_err)] large_error_threshold: u64 = 128, + /// Whether collapsible `if` chains are linted if they contain comments inside the parts + /// that would be collapsed. + #[lints(collapsible_if)] + lint_commented_code: bool = false, /// Whether to suggest reordering constructor fields when initializers are present. /// /// Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index e73bfc6ebf7a1..b100e2408de3d 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -1,10 +1,13 @@ +use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::source::{snippet, snippet_block, snippet_block_with_applicability}; -use clippy_utils::sugg::Sugg; +use clippy_utils::source::{ + HasSession, IntoSpan as _, SpanRangeExt, snippet, snippet_block, snippet_block_with_applicability, +}; +use clippy_utils::span_contains_comment; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; use rustc_span::Span; declare_clippy_lint! { @@ -75,7 +78,95 @@ declare_clippy_lint! { "nested `else`-`if` expressions that can be collapsed (e.g., `else { if x { ... } }`)" } -declare_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]); +pub struct CollapsibleIf { + lint_commented_code: bool, +} + +impl CollapsibleIf { + pub fn new(conf: &'static Conf) -> Self { + Self { + lint_commented_code: conf.lint_commented_code, + } + } + + fn check_collapsible_else_if(cx: &EarlyContext<'_>, then_span: Span, else_: &ast::Expr) { + if let ast::ExprKind::Block(ref block, _) = else_.kind + && !block_starts_with_comment(cx, block) + && let Some(else_) = expr_block(block) + && else_.attrs.is_empty() + && !else_.span.from_expansion() + && let ast::ExprKind::If(..) = else_.kind + { + // Prevent "elseif" + // Check that the "else" is followed by whitespace + let up_to_else = then_span.between(block.span); + let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() { + !c.is_whitespace() + } else { + false + }; + + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + COLLAPSIBLE_ELSE_IF, + block.span, + "this `else { if .. }` block can be collapsed", + "collapse nested if block", + format!( + "{}{}", + if requires_space { " " } else { "" }, + snippet_block_with_applicability(cx, else_.span, "..", Some(block.span), &mut applicability) + ), + applicability, + ); + } + } + + fn check_collapsible_if_if(&self, cx: &EarlyContext<'_>, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) { + if let Some(inner) = expr_block(then) + && inner.attrs.is_empty() + && let ast::ExprKind::If(check_inner, _, None) = &inner.kind + // Prevent triggering on `if c { if let a = b { .. } }`. + && !matches!(check_inner.kind, ast::ExprKind::Let(..)) + && let ctxt = expr.span.ctxt() + && inner.span.ctxt() == ctxt + && let contains_comment = span_contains_comment(cx.sess().source_map(), check.span.to(check_inner.span)) + && (!contains_comment || self.lint_commented_code) + { + span_lint_and_then( + cx, + COLLAPSIBLE_IF, + expr.span, + "this `if` statement can be collapsed", + |diag| { + let then_open_bracket = then.span.split_at(1).0.with_leading_whitespace(cx).into_span(); + let then_closing_bracket = { + let end = then.span.shrink_to_hi(); + end.with_lo(end.lo() - rustc_span::BytePos(1)) + .with_leading_whitespace(cx) + .into_span() + }; + let inner_if = inner.span.split_at(2).0; + let mut sugg = vec![ + // Remove the outer then block `{` + (then_open_bracket, String::new()), + // Remove the outer then block '}' + (then_closing_bracket, String::new()), + // Replace inner `if` by `&&` + (inner_if, String::from("&&")), + ]; + sugg.extend(parens_around(check)); + sugg.extend(parens_around(check_inner)); + + diag.multipart_suggestion("collapse nested if block", sugg, Applicability::MachineApplicable); + }, + ); + } + } +} + +impl_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]); impl EarlyLintPass for CollapsibleIf { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { @@ -83,9 +174,10 @@ impl EarlyLintPass for CollapsibleIf { && !expr.span.from_expansion() { if let Some(else_) = else_ { - check_collapsible_maybe_if_let(cx, then.span, else_); + Self::check_collapsible_else_if(cx, then.span, else_); } else if !matches!(cond.kind, ast::ExprKind::Let(..)) { - check_collapsible_no_if_let(cx, expr, cond, then); + // Prevent triggering on `if c { if let a = b { .. } }`. + self.check_collapsible_if_if(cx, expr, cond, then); } } } @@ -99,74 +191,6 @@ fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool { trimmed_block_text.starts_with("//") || trimmed_block_text.starts_with("/*") } -fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, then_span: Span, else_: &ast::Expr) { - if let ast::ExprKind::Block(ref block, _) = else_.kind - && !block_starts_with_comment(cx, block) - && let Some(else_) = expr_block(block) - && else_.attrs.is_empty() - && !else_.span.from_expansion() - && let ast::ExprKind::If(..) = else_.kind - { - // Prevent "elseif" - // Check that the "else" is followed by whitespace - let up_to_else = then_span.between(block.span); - let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() { - !c.is_whitespace() - } else { - false - }; - - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - COLLAPSIBLE_ELSE_IF, - block.span, - "this `else { if .. }` block can be collapsed", - "collapse nested if block", - format!( - "{}{}", - if requires_space { " " } else { "" }, - snippet_block_with_applicability(cx, else_.span, "..", Some(block.span), &mut applicability) - ), - applicability, - ); - } -} - -fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) { - if !block_starts_with_comment(cx, then) - && let Some(inner) = expr_block(then) - && inner.attrs.is_empty() - && let ast::ExprKind::If(ref check_inner, ref content, None) = inner.kind - // Prevent triggering on `if c { if let a = b { .. } }`. - && !matches!(check_inner.kind, ast::ExprKind::Let(..)) - && let ctxt = expr.span.ctxt() - && inner.span.ctxt() == ctxt - { - span_lint_and_then( - cx, - COLLAPSIBLE_IF, - expr.span, - "this `if` statement can be collapsed", - |diag| { - let mut app = Applicability::MachineApplicable; - let lhs = Sugg::ast(cx, check, "..", ctxt, &mut app); - let rhs = Sugg::ast(cx, check_inner, "..", ctxt, &mut app); - diag.span_suggestion( - expr.span, - "collapse nested if block", - format!( - "if {} {}", - lhs.and(&rhs), - snippet_block(cx, content.span, "..", Some(expr.span)), - ), - app, // snippet - ); - }, - ); - } -} - /// If the block contains only one expression, return it. fn expr_block(block: &ast::Block) -> Option<&ast::Expr> { if let [stmt] = &*block.stmts @@ -177,3 +201,17 @@ fn expr_block(block: &ast::Block) -> Option<&ast::Expr> { None } } + +/// If the expression is a `||`, suggest parentheses around it. +fn parens_around(expr: &ast::Expr) -> Vec<(Span, String)> { + if let ast::ExprKind::Binary(op, _, _) = expr.kind + && op.node == ast::BinOpKind::Or + { + vec![ + (expr.span.shrink_to_lo(), String::from("(")), + (expr.span.shrink_to_hi(), String::from(")")), + ] + } else { + vec![] + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3fe3cd67e1671..2d390be5248c6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -772,7 +772,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall)); store.register_early_pass(|| Box::new(unused_unit::UnusedUnit)); store.register_late_pass(|_| Box::new(returns::Return)); - store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf)); + store.register_early_pass(move || Box::new(collapsible_if::CollapsibleIf::new(conf))); store.register_late_pass(|_| Box::new(items_after_statements::ItemsAfterStatements)); store.register_early_pass(|| Box::new(precedence::Precedence)); store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals)); diff --git a/tests/ui-toml/collapsible_if/clippy.toml b/tests/ui-toml/collapsible_if/clippy.toml new file mode 100644 index 0000000000000..592cea90cff5c --- /dev/null +++ b/tests/ui-toml/collapsible_if/clippy.toml @@ -0,0 +1 @@ +lint-commented-code = true diff --git a/tests/ui-toml/collapsible_if/collapsible_if.fixed b/tests/ui-toml/collapsible_if/collapsible_if.fixed new file mode 100644 index 0000000000000..f695f9804d59c --- /dev/null +++ b/tests/ui-toml/collapsible_if/collapsible_if.fixed @@ -0,0 +1,34 @@ +#![allow(clippy::eq_op, clippy::nonminimal_bool)] + +#[rustfmt::skip] +#[warn(clippy::collapsible_if)] +fn main() { + let (x, y) = ("hello", "world"); + + if x == "hello" + // Comment must be kept + && y == "world" { + println!("Hello world!"); + } + //~^^^^^^ collapsible_if + + // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798 + if x == "hello" // Inner comment + && y == "world" { + println!("Hello world!"); + } + //~^^^^^ collapsible_if + + if x == "hello" + /* Inner comment */ + && y == "world" { + println!("Hello world!"); + } + //~^^^^^^ collapsible_if + + if x == "hello" /* Inner comment */ + && y == "world" { + println!("Hello world!"); + } + //~^^^^^ collapsible_if +} diff --git a/tests/ui-toml/collapsible_if/collapsible_if.rs b/tests/ui-toml/collapsible_if/collapsible_if.rs new file mode 100644 index 0000000000000..868b4adcde502 --- /dev/null +++ b/tests/ui-toml/collapsible_if/collapsible_if.rs @@ -0,0 +1,38 @@ +#![allow(clippy::eq_op, clippy::nonminimal_bool)] + +#[rustfmt::skip] +#[warn(clippy::collapsible_if)] +fn main() { + let (x, y) = ("hello", "world"); + + if x == "hello" { + // Comment must be kept + if y == "world" { + println!("Hello world!"); + } + } + //~^^^^^^ collapsible_if + + // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798 + if x == "hello" { // Inner comment + if y == "world" { + println!("Hello world!"); + } + } + //~^^^^^ collapsible_if + + if x == "hello" { + /* Inner comment */ + if y == "world" { + println!("Hello world!"); + } + } + //~^^^^^^ collapsible_if + + if x == "hello" { /* Inner comment */ + if y == "world" { + println!("Hello world!"); + } + } + //~^^^^^ collapsible_if +} diff --git a/tests/ui-toml/collapsible_if/collapsible_if.stderr b/tests/ui-toml/collapsible_if/collapsible_if.stderr new file mode 100644 index 0000000000000..a12c2112f5877 --- /dev/null +++ b/tests/ui-toml/collapsible_if/collapsible_if.stderr @@ -0,0 +1,80 @@ +error: this `if` statement can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_if.rs:8:5 + | +LL | / if x == "hello" { +LL | | // Comment must be kept +LL | | if y == "world" { +LL | | println!("Hello world!"); +LL | | } +LL | | } + | |_____^ + | + = note: `-D clippy::collapsible-if` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::collapsible_if)]` +help: collapse nested if block + | +LL ~ if x == "hello" +LL | // Comment must be kept +LL ~ && y == "world" { +LL | println!("Hello world!"); +LL ~ } + | + +error: this `if` statement can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_if.rs:17:5 + | +LL | / if x == "hello" { // Inner comment +LL | | if y == "world" { +LL | | println!("Hello world!"); +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ if x == "hello" // Inner comment +LL ~ && y == "world" { +LL | println!("Hello world!"); +LL ~ } + | + +error: this `if` statement can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_if.rs:24:5 + | +LL | / if x == "hello" { +LL | | /* Inner comment */ +LL | | if y == "world" { +LL | | println!("Hello world!"); +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ if x == "hello" +LL | /* Inner comment */ +LL ~ && y == "world" { +LL | println!("Hello world!"); +LL ~ } + | + +error: this `if` statement can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_if.rs:32:5 + | +LL | / if x == "hello" { /* Inner comment */ +LL | | if y == "world" { +LL | | println!("Hello world!"); +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ if x == "hello" /* Inner comment */ +LL ~ && y == "world" { +LL | println!("Hello world!"); +LL ~ } + | + +error: aborting due to 4 previous errors + diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index fee5b01b68982..de0eefc422e70 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -49,6 +49,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect future-size-threshold ignore-interior-mutability large-error-threshold + lint-commented-code lint-inconsistent-struct-field-initializers literal-representation-threshold matches-for-let-else @@ -142,6 +143,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect future-size-threshold ignore-interior-mutability large-error-threshold + lint-commented-code lint-inconsistent-struct-field-initializers literal-representation-threshold matches-for-let-else @@ -235,6 +237,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni future-size-threshold ignore-interior-mutability large-error-threshold + lint-commented-code lint-inconsistent-struct-field-initializers literal-representation-threshold matches-for-let-else diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index 6e994018aef01..df281651ab14f 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -12,34 +12,40 @@ fn main() { let x = "hello"; let y = "world"; - if x == "hello" && y == "world" { - println!("Hello world!"); - } + if x == "hello" + && y == "world" { + println!("Hello world!"); + } //~^^^^^ collapsible_if - if (x == "hello" || x == "world") && (y == "world" || y == "hello") { - println!("Hello world!"); - } + if (x == "hello" || x == "world") + && (y == "world" || y == "hello") { + println!("Hello world!"); + } //~^^^^^ collapsible_if - if x == "hello" && x == "world" && (y == "world" || y == "hello") { - println!("Hello world!"); - } + if x == "hello" && x == "world" + && (y == "world" || y == "hello") { + println!("Hello world!"); + } //~^^^^^ collapsible_if - if (x == "hello" || x == "world") && y == "world" && y == "hello" { - println!("Hello world!"); - } + if (x == "hello" || x == "world") + && y == "world" && y == "hello" { + println!("Hello world!"); + } //~^^^^^ collapsible_if - if x == "hello" && x == "world" && y == "world" && y == "hello" { - println!("Hello world!"); - } + if x == "hello" && x == "world" + && y == "world" && y == "hello" { + println!("Hello world!"); + } //~^^^^^ collapsible_if - if 42 == 1337 && 'a' != 'A' { - println!("world!") - } + if 42 == 1337 + && 'a' != 'A' { + println!("world!") + } //~^^^^^ collapsible_if // Works because any if with an else statement cannot be collapsed. @@ -71,37 +77,17 @@ fn main() { assert!(true); // assert! is just an `if` } - - // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798 - if x == "hello" {// Not collapsible - if y == "world" { + if x == "hello" + && y == "world" { // Collapsible println!("Hello world!"); } - } - - if x == "hello" { // Not collapsible - if y == "world" { - println!("Hello world!"); - } - } - - if x == "hello" { - // Not collapsible - if y == "world" { - println!("Hello world!"); - } - } - - if x == "hello" && y == "world" { // Collapsible - println!("Hello world!"); - } //~^^^^^ collapsible_if if x == "hello" { print!("Hello "); } else { // Not collapsible - if y == "world" { + if let Some(42) = Some(42) { println!("world!") } } @@ -110,21 +96,8 @@ fn main() { print!("Hello "); } else { // Not collapsible - if let Some(42) = Some(42) { - println!("world!") - } - } - - if x == "hello" { - /* Not collapsible */ if y == "world" { - println!("Hello world!"); - } - } - - if x == "hello" { /* Not collapsible */ - if y == "world" { - println!("Hello world!"); + println!("world!") } } @@ -150,11 +123,13 @@ fn main() { } // Fix #5962 - if matches!(true, true) && matches!(true, true) {} + if matches!(true, true) + && matches!(true, true) {} //~^^^ collapsible_if // Issue #9375 - if matches!(true, true) && truth() && matches!(true, true) {} + if matches!(true, true) && truth() + && matches!(true, true) {} //~^^^ collapsible_if if true { @@ -163,4 +138,17 @@ fn main() { println!("Hello world!"); } } + + if true + && true { + println!("No comment, linted"); + } + //~^^^^^ collapsible_if + + if true { + // Do not collapse because of this comment + if true { + println!("Hello world!"); + } + } } diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index 5cf591a658c7a..ce979568cc895 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -83,27 +83,6 @@ fn main() { assert!(true); // assert! is just an `if` } - - // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798 - if x == "hello" {// Not collapsible - if y == "world" { - println!("Hello world!"); - } - } - - if x == "hello" { // Not collapsible - if y == "world" { - println!("Hello world!"); - } - } - - if x == "hello" { - // Not collapsible - if y == "world" { - println!("Hello world!"); - } - } - if x == "hello" { if y == "world" { // Collapsible println!("Hello world!"); @@ -115,7 +94,7 @@ fn main() { print!("Hello "); } else { // Not collapsible - if y == "world" { + if let Some(42) = Some(42) { println!("world!") } } @@ -124,21 +103,8 @@ fn main() { print!("Hello "); } else { // Not collapsible - if let Some(42) = Some(42) { - println!("world!") - } - } - - if x == "hello" { - /* Not collapsible */ if y == "world" { - println!("Hello world!"); - } - } - - if x == "hello" { /* Not collapsible */ - if y == "world" { - println!("Hello world!"); + println!("world!") } } @@ -181,4 +147,18 @@ fn main() { println!("Hello world!"); } } + + if true { + if true { + println!("No comment, linted"); + } + } + //~^^^^^ collapsible_if + + if true { + // Do not collapse because of this comment + if true { + println!("Hello world!"); + } + } } diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 3cc3fe5534f25..559db238cb182 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -12,9 +12,10 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::collapsible_if)]` help: collapse nested if block | -LL ~ if x == "hello" && y == "world" { -LL + println!("Hello world!"); -LL + } +LL ~ if x == "hello" +LL ~ && y == "world" { +LL | println!("Hello world!"); +LL ~ } | error: this `if` statement can be collapsed @@ -29,9 +30,10 @@ LL | | } | help: collapse nested if block | -LL ~ if (x == "hello" || x == "world") && (y == "world" || y == "hello") { -LL + println!("Hello world!"); -LL + } +LL ~ if (x == "hello" || x == "world") { +LL ~ && (y == "world" || y == "hello") { +LL | println!("Hello world!"); +LL ~ } | error: this `if` statement can be collapsed @@ -46,9 +48,10 @@ LL | | } | help: collapse nested if block | -LL ~ if x == "hello" && x == "world" && (y == "world" || y == "hello") { -LL + println!("Hello world!"); -LL + } +LL ~ if x == "hello" && x == "world" +LL ~ && (y == "world" || y == "hello") { +LL | println!("Hello world!"); +LL ~ } | error: this `if` statement can be collapsed @@ -63,9 +66,10 @@ LL | | } | help: collapse nested if block | -LL ~ if (x == "hello" || x == "world") && y == "world" && y == "hello" { -LL + println!("Hello world!"); -LL + } +LL ~ if (x == "hello" || x == "world") { +LL ~ && y == "world" && y == "hello" { +LL | println!("Hello world!"); +LL ~ } | error: this `if` statement can be collapsed @@ -80,9 +84,10 @@ LL | | } | help: collapse nested if block | -LL ~ if x == "hello" && x == "world" && y == "world" && y == "hello" { -LL + println!("Hello world!"); -LL + } +LL ~ if x == "hello" && x == "world" +LL ~ && y == "world" && y == "hello" { +LL | println!("Hello world!"); +LL ~ } | error: this `if` statement can be collapsed @@ -97,13 +102,14 @@ LL | | } | help: collapse nested if block | -LL ~ if 42 == 1337 && 'a' != 'A' { -LL + println!("world!") -LL + } +LL ~ if 42 == 1337 +LL ~ && 'a' != 'A' { +LL | println!("world!") +LL ~ } | error: this `if` statement can be collapsed - --> tests/ui/collapsible_if.rs:107:5 + --> tests/ui/collapsible_if.rs:86:5 | LL | / if x == "hello" { LL | | if y == "world" { // Collapsible @@ -114,26 +120,57 @@ LL | | } | help: collapse nested if block | -LL ~ if x == "hello" && y == "world" { // Collapsible -LL + println!("Hello world!"); -LL + } +LL ~ if x == "hello" +LL ~ && y == "world" { // Collapsible +LL | println!("Hello world!"); +LL ~ } | error: this `if` statement can be collapsed - --> tests/ui/collapsible_if.rs:167:5 + --> tests/ui/collapsible_if.rs:133:5 | LL | / if matches!(true, true) { LL | | if matches!(true, true) {} LL | | } - | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}` + | |_____^ + | +help: collapse nested if block + | +LL ~ if matches!(true, true) +LL ~ && matches!(true, true) {} + | error: this `if` statement can be collapsed - --> tests/ui/collapsible_if.rs:173:5 + --> tests/ui/collapsible_if.rs:139:5 | LL | / if matches!(true, true) && truth() { LL | | if matches!(true, true) {} LL | | } - | |_____^ help: collapse nested if block: `if matches!(true, true) && truth() && matches!(true, true) {}` + | |_____^ + | +help: collapse nested if block + | +LL ~ if matches!(true, true) && truth() +LL ~ && matches!(true, true) {} + | + +error: this `if` statement can be collapsed + --> tests/ui/collapsible_if.rs:151:5 + | +LL | / if true { +LL | | if true { +LL | | println!("No comment, linted"); +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ if true +LL ~ && true { +LL | println!("No comment, linted"); +LL ~ } + | -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors From 282b61b64174f8dca382932c5f5f3385c28c4a11 Mon Sep 17 00:00:00 2001 From: yanglsh Date: Mon, 17 Mar 2025 23:28:43 +0800 Subject: [PATCH 0231/2248] fix: `nonminimal_bool` wrongly showed the macro definition --- clippy_lints/src/booleans.rs | 12 ++++++++---- tests/ui/nonminimal_bool.rs | 20 ++++++++++++++++++++ tests/ui/nonminimal_bool.stderr | 10 ++++++++-- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 48b5d4da88860..36c1aea263781 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -13,7 +13,7 @@ use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp}; use rustc_lint::{LateContext, LateLintPass, Level}; use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; -use rustc_span::{Span, sym}; +use rustc_span::{Span, SyntaxContext, sym}; declare_clippy_lint! { /// ### What it does @@ -349,9 +349,13 @@ impl SuggestContext<'_, '_, '_> { if let Some(str) = simplify_not(self.cx, self.msrv, terminal) { self.output.push_str(&str); } else { - self.output.push('!'); - self.output - .push_str(&Sugg::hir_opt(self.cx, terminal)?.maybe_par().to_string()); + let mut app = Applicability::MachineApplicable; + let snip = Sugg::hir_with_context(self.cx, terminal, SyntaxContext::root(), "", &mut app); + // Ignore the case If the expression is inside a macro expansion, or the default snippet is used + if app != Applicability::MachineApplicable { + return None; + } + self.output.push_str(&(!snip).to_string()); } }, True | False | Not(_) => { diff --git a/tests/ui/nonminimal_bool.rs b/tests/ui/nonminimal_bool.rs index a155ff3508be0..1eecc3dee3dc5 100644 --- a/tests/ui/nonminimal_bool.rs +++ b/tests/ui/nonminimal_bool.rs @@ -216,3 +216,23 @@ fn issue14184(a: f32, b: bool) { println!("Hi"); } } + +mod issue14404 { + enum TyKind { + Ref(i32, i32, i32), + Other, + } + + struct Expr; + + fn is_mutable(expr: &Expr) -> bool { + todo!() + } + + fn should_not_give_macro(ty: TyKind, expr: Expr) { + if !(matches!(ty, TyKind::Ref(_, _, _)) && !is_mutable(&expr)) { + //~^ nonminimal_bool + todo!() + } + } +} diff --git a/tests/ui/nonminimal_bool.stderr b/tests/ui/nonminimal_bool.stderr index 336cce40abf0d..0e3e4cf7988e2 100644 --- a/tests/ui/nonminimal_bool.stderr +++ b/tests/ui/nonminimal_bool.stderr @@ -227,7 +227,13 @@ error: this boolean expression can be simplified --> tests/ui/nonminimal_bool.rs:214:8 | LL | if !(a < 2.0 && !b) { - | ^^^^^^^^^^^^^^^^ help: try: `!(a < 2.0) || b` + | ^^^^^^^^^^^^^^^^ help: try: `a >= 2.0 || b` -error: aborting due to 30 previous errors +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool.rs:233:12 + | +LL | if !(matches!(ty, TyKind::Ref(_, _, _)) && !is_mutable(&expr)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!matches!(ty, TyKind::Ref(_, _, _)) || is_mutable(&expr)` + +error: aborting due to 31 previous errors From 2c4643e1fa195ba45866f6d61d1bc329f2a68a1d Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Sat, 22 Mar 2025 23:50:20 +0900 Subject: [PATCH 0232/2248] Render layout and other extra informations on hovering `Self` --- .../rust-analyzer/crates/ide/src/hover.rs | 16 ++++-- .../crates/ide/src/hover/render.rs | 10 +++- .../crates/ide/src/hover/tests.rs | 54 +++++++++++++++++++ 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index ea1f673e5be1a..5cab8efa798db 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -18,7 +18,11 @@ use ide_db::{ }; use itertools::{Itertools, multizip}; use span::Edition; -use syntax::{AstNode, SyntaxKind::*, SyntaxNode, T, ast}; +use syntax::{ + AstNode, + SyntaxKind::{self, *}, + SyntaxNode, T, ast, +}; use crate::{ FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, TryToNav, @@ -274,11 +278,13 @@ fn hover_offset( } class => { - let is_def = matches!(class, IdentClass::NameClass(_)); + let render_extras = matches!(class, IdentClass::NameClass(_)) + // Render extra information for `Self` keyword as well + || ast::NameRef::cast(node.clone()).is_some_and(|name_ref| name_ref.token_kind() == SyntaxKind::SELF_TYPE_KW); multizip(( class.definitions(), iter::repeat(None), - iter::repeat(is_def), + iter::repeat(render_extras), iter::repeat(node), )) .collect::>() @@ -422,7 +428,7 @@ pub(crate) fn hover_for_definition( subst: Option, scope_node: &SyntaxNode, macro_arm: Option, - hovered_definition: bool, + render_extras: bool, config: &HoverConfig, edition: Edition, display_target: DisplayTarget, @@ -456,7 +462,7 @@ pub(crate) fn hover_for_definition( famous_defs.as_ref(), ¬able_traits, macro_arm, - hovered_definition, + render_extras, subst_types.as_ref(), config, edition, diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index cf2ff1c9560dc..a4cb869ac1f6c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -477,7 +477,7 @@ pub(super) fn definition( famous_defs: Option<&FamousDefs<'_, '_>>, notable_traits: &[(Trait, Vec<(Option, Name)>)], macro_arm: Option, - hovered_definition: bool, + render_extras: bool, subst_types: Option<&Vec<(Symbol, Type)>>, config: &HoverConfig, edition: Edition, @@ -640,6 +640,12 @@ pub(super) fn definition( Definition::Local(it) => { render_memory_layout(config.memory_layout, || it.ty(db).layout(db), |_| None, |_| None) } + Definition::SelfType(it) => render_memory_layout( + config.memory_layout, + || it.self_ty(db).layout(db), + |_| None, + |_| None, + ), _ => None, }; @@ -741,7 +747,7 @@ pub(super) fn definition( }; let mut extra = String::new(); - if hovered_definition { + if render_extras { if let Some(notable_traits) = render_notable_trait(db, notable_traits, edition, display_target) { diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 0266b87499da2..c5f87910302e5 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -2089,6 +2089,10 @@ impl Thing { x: u32, } ``` + + --- + + size = 4, align = 4 "#]], ); check_hover_fields_limit( @@ -2109,6 +2113,10 @@ impl Thing { ```rust struct Thing ``` + + --- + + size = 4, align = 4 "#]], ); check( @@ -2130,6 +2138,10 @@ impl Thing { x: u32, } ``` + + --- + + size = 4, align = 4 "#]], ); check( @@ -2151,6 +2163,10 @@ impl Thing { A, } ``` + + --- + + size = 0, align = 1 "#]], ); check( @@ -2172,6 +2188,10 @@ impl Thing { A, } ``` + + --- + + size = 0, align = 1 "#]], ); check( @@ -2190,6 +2210,10 @@ impl usize { ```rust usize ``` + + --- + + size = 8, align = 8 "#]], ); check( @@ -2208,6 +2232,36 @@ impl fn() -> usize { ```rust fn() -> usize ``` + + --- + + size = 8, align = 8, niches = 1 + "#]], + ); + check( + r#" +pub struct Foo +where + Self$0:; +"#, + expect![[r#" + *Self* + + ```rust + ra_test_fixture + ``` + + ```rust + pub struct Foo + ``` + + --- + + size = 0, align = 1 + + --- + + does not contain types with destructors (drop glue); doesn't have a destructor "#]], ); } From 729cd251233a2c49cb4b1fb4e426f7b4170e7249 Mon Sep 17 00:00:00 2001 From: BenjaminBrienen Date: Sat, 22 Mar 2025 17:54:46 +0100 Subject: [PATCH 0233/2248] Improve contributing/README.md --- .../docs/book/src/contributing/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tools/rust-analyzer/docs/book/src/contributing/README.md b/src/tools/rust-analyzer/docs/book/src/contributing/README.md index cbbf6acf3e590..9e1cdb08893fc 100644 --- a/src/tools/rust-analyzer/docs/book/src/contributing/README.md +++ b/src/tools/rust-analyzer/docs/book/src/contributing/README.md @@ -3,7 +3,7 @@ rust-analyzer is an ordinary Rust project, which is organized as a Cargo workspace, builds on stable and doesn't depend on C libraries. So, just -``` +```bash $ cargo test ``` @@ -140,7 +140,7 @@ By default, log goes to stderr, but the stderr itself is processed by VS Code. `--log-file ` CLI argument allows logging to file. Setting the `RA_LOG_FILE=` environment variable will also log to file, it will also override `--log-file`. -To see stderr in the running VS Code instance, go to the "Output" tab of the panel and select `rust-analyzer`. +To see stderr in the running VS Code instance, go to the "Output" tab of the panel and select `Rust Analyzer Client`. This shows `eprintln!` as well. Note that `stdout` is used for the actual protocol, so `println!` will break things. @@ -148,7 +148,7 @@ To log all communication between the server and the client, there are two choice * You can log on the server side, by running something like - ``` + ```bash env RA_LOG=lsp_server=debug code . ``` @@ -180,7 +180,7 @@ There are also several VS Code commands which might be of interest: We have a built-in hierarchical profiler, you can enable it by using `RA_PROFILE` env-var: -``` +```bash RA_PROFILE=* // dump everything RA_PROFILE=foo|bar|baz // enabled only selected entries RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms @@ -191,7 +191,7 @@ Some rust-analyzer contributors have `export RA_PROFILE='*>10'` in my shell prof For machine-readable JSON output, we have the `RA_PROFILE_JSON` env variable. We support filtering only by span name: -``` +```bash RA_PROFILE=* // dump everything RA_PROFILE_JSON="vfs_load|parallel_prime_caches|discover_command" // dump selected spans ``` @@ -201,13 +201,13 @@ It is enabled by `RA_COUNT=1`. To measure time for from-scratch analysis, use something like this: -``` +```bash $ cargo run --release -p rust-analyzer -- analysis-stats ../chalk/ ``` For measuring time of incremental analysis, use either of these: -``` +```bash $ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --highlight ../chalk/chalk-engine/src/logic.rs $ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --complete ../chalk/chalk-engine/src/logic.rs:94:0 ``` @@ -220,7 +220,7 @@ Release process is handled by `release`, `dist`, `publish-release-notes` and `pr `release` assumes that you have checkouts of `rust-analyzer`, `rust-analyzer.github.io`, and `rust-lang/rust` in the same directory: -``` +```bash ./rust-analyzer ./rust-analyzer.github.io ./rust-rust-analyzer # Note the name! From ee6a1598268e07cf1fbecc6ad1c2d5a5db593fb4 Mon Sep 17 00:00:00 2001 From: Chiichen Date: Sun, 23 Mar 2025 12:34:41 +0800 Subject: [PATCH 0234/2248] 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 8bc164b81824a1d13a6cb10ebe6d169cea82916e Mon Sep 17 00:00:00 2001 From: yanglsh Date: Sun, 23 Mar 2025 12:49:03 +0800 Subject: [PATCH 0235/2248] fix: `option_if_let_else` suggests wrongly when coercion --- clippy_lints/src/option_if_let_else.rs | 13 +++++++++++-- tests/ui/option_if_let_else.fixed | 14 ++++++++++++++ tests/ui/option_if_let_else.rs | 14 ++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 6f302ea196217..fa5481f27b490 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -4,8 +4,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_copy; use clippy_utils::{ - CaptureKind, can_move_expr_to_closure, eager_or_lazy, higher, is_else_clause, is_in_const_context, - is_res_lang_ctor, peel_blocks, peel_hir_expr_while, + CaptureKind, can_move_expr_to_closure, eager_or_lazy, expr_requires_coercion, higher, is_else_clause, + is_in_const_context, is_res_lang_ctor, peel_blocks, peel_hir_expr_while, }; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -212,6 +212,15 @@ fn try_get_option_occurrence<'tcx>( } } + let some_body_ty = cx.typeck_results().expr_ty(some_body); + let none_body_ty = cx.typeck_results().expr_ty(none_body); + // Check if coercion is needed for the `None` arm. If so, we cannot suggest because it will + // introduce a type mismatch. A special case is when both arms have the same type, then + // coercion is fine. + if some_body_ty != none_body_ty && expr_requires_coercion(cx, none_body) { + return None; + } + let mut app = Applicability::Unspecified; let (none_body, is_argless_call) = match none_body.kind { diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index ee30988960175..fe3ac9e8f92c3 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -288,3 +288,17 @@ mod issue13964 { }; } } + +mod issue11059 { + use std::fmt::Debug; + + fn box_coercion_unsize(o: Option) -> Box { + if let Some(o) = o { Box::new(o) } else { Box::new("foo") } + } + + static S: String = String::new(); + + fn deref_with_overload(o: Option<&str>) -> &str { + if let Some(o) = o { o } else { &S } + } +} diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 525a5df4371c2..5b7498bc8e23b 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -351,3 +351,17 @@ mod issue13964 { }; } } + +mod issue11059 { + use std::fmt::Debug; + + fn box_coercion_unsize(o: Option) -> Box { + if let Some(o) = o { Box::new(o) } else { Box::new("foo") } + } + + static S: String = String::new(); + + fn deref_with_overload(o: Option<&str>) -> &str { + if let Some(o) = o { o } else { &S } + } +} From 9b1924df898ba81eeb7ea72da31ff986b3986b3e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 23 Mar 2025 07:45:29 +0100 Subject: [PATCH 0236/2248] chore: Remove unused dependencies --- src/tools/rust-analyzer/Cargo.lock | 35 +------------- .../rust-analyzer/crates/base-db/Cargo.toml | 3 -- .../rust-analyzer/crates/hir-def/Cargo.toml | 3 -- .../crates/hir-expand/Cargo.toml | 2 - .../rust-analyzer/crates/hir-ty/Cargo.toml | 2 - .../rust-analyzer/crates/ide-db/Cargo.toml | 1 - .../rust-analyzer/crates/ide-ssr/Cargo.toml | 4 +- .../crates/load-cargo/Cargo.toml | 1 - src/tools/rust-analyzer/crates/mbe/Cargo.toml | 5 +- .../crates/proc-macro-srv-cli/src/main.rs | 1 + .../crates/proc-macro-srv/Cargo.toml | 5 +- .../crates/proc-macro-srv/src/lib.rs | 1 + .../rust-analyzer/crates/profile/Cargo.toml | 4 +- .../crates/query-group-macro/Cargo.toml | 3 +- .../crates/rust-analyzer/Cargo.toml | 3 -- .../crates/rust-analyzer/src/diagnostics.rs | 48 +++++++++---------- .../crates/rust-analyzer/src/global_state.rs | 7 ++- .../rust-analyzer/src/handlers/request.rs | 2 +- .../crates/rust-analyzer/src/main_loop.rs | 3 +- .../rust-analyzer/crates/stdx/Cargo.toml | 4 +- .../crates/syntax-bridge/Cargo.toml | 1 - .../rust-analyzer/crates/syntax/Cargo.toml | 2 - .../crates/test-utils/Cargo.toml | 1 - 23 files changed, 45 insertions(+), 96 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 54cc9d1c68025..4310cfc04a88a 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -32,12 +32,6 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "always-assert" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1078fa1ce1e34b1872d8611ad921196d76bdd7027e949fbe31231abde201892" - [[package]] name = "anyhow" version = "1.0.97" @@ -85,13 +79,11 @@ dependencies = [ "dashmap 5.5.3", "intern", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lz4_flex", "query-group-macro", "rustc-hash 2.1.1", "salsa", "semver", "span", - "stdx", "syntax", "tracing", "triomphe", @@ -638,12 +630,10 @@ dependencies = [ "bitflags 2.9.0", "cfg", "cov-mark", - "dashmap 5.5.3", "drop_bomb", "either", "expect-test", "fst", - "hashbrown 0.14.5", "hir-expand", "indexmap", "intern", @@ -652,7 +642,6 @@ dependencies = [ "mbe", "query-group-macro", "ra-ap-rustc_abi", - "ra-ap-rustc_hashes", "ra-ap-rustc_parse_format", "rustc-hash 2.1.1", "rustc_apfloat", @@ -679,10 +668,8 @@ dependencies = [ "cov-mark", "either", "expect-test", - "hashbrown 0.14.5", "intern", "itertools", - "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "mbe", "parser", "query-group-macro", @@ -710,7 +697,6 @@ dependencies = [ "chalk-recursive", "chalk-solve", "cov-mark", - "dashmap 5.5.3", "either", "ena", "expect-test", @@ -720,7 +706,6 @@ dependencies = [ "intern", "itertools", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nohash-hasher", "oorandom", "project-model", "query-group-macro", @@ -951,7 +936,6 @@ dependencies = [ "bitflags 2.9.0", "cov-mark", "crossbeam-channel", - "dashmap 5.5.3", "either", "expect-test", "fst", @@ -1006,9 +990,7 @@ dependencies = [ "hir", "ide-db", "itertools", - "nohash-hasher", "parser", - "stdx", "syntax", "test-fixture", "test-utils", @@ -1206,7 +1188,6 @@ dependencies = [ "ide-db", "intern", "itertools", - "paths", "proc-macro-api", "project-model", "span", @@ -1284,12 +1265,6 @@ dependencies = [ "url", ] -[[package]] -name = "lz4_flex" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" - [[package]] name = "matchers" version = "0.1.0" @@ -1316,7 +1291,6 @@ dependencies = [ "syntax", "syntax-bridge", "test-utils", - "tracing", "tt", ] @@ -1644,7 +1618,6 @@ dependencies = [ "proc-macro-test", "ra-ap-rustc_lexer", "span", - "stdx", "syntax-bridge", "tt", ] @@ -1767,7 +1740,6 @@ name = "query-group-macro" version = "0.0.0" dependencies = [ "expect-test", - "heck", "proc-macro2", "quote", "salsa", @@ -1960,7 +1932,6 @@ dependencies = [ name = "rust-analyzer" version = "0.0.0" dependencies = [ - "always-assert", "anyhow", "base64", "cargo_metadata", @@ -2292,10 +2263,8 @@ dependencies = [ name = "syntax" version = "0.0.0" dependencies = [ - "cov-mark", "either", "expect-test", - "indexmap", "itertools", "parser", "ra-ap-rustc_lexer", @@ -2321,7 +2290,6 @@ dependencies = [ "stdx", "syntax", "test-utils", - "tracing", "tt", ] @@ -2357,7 +2325,6 @@ dependencies = [ "rustc-hash 2.1.1", "stdx", "text-size", - "tracing", ] [[package]] diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml index 4780d5191befb..441434504c293 100644 --- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml +++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml @@ -12,8 +12,6 @@ rust-version.workspace = true [lib] [dependencies] -lz4_flex = { version = "0.11", default-features = false } - la-arena.workspace = true dashmap.workspace = true salsa.workspace = true @@ -25,7 +23,6 @@ tracing.workspace = true # local deps cfg.workspace = true -stdx.workspace = true syntax.workspace = true vfs.workspace = true span.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml index 1b1d430ffdfd5..628a78cdeafbe 100644 --- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml @@ -15,7 +15,6 @@ rust-version.workspace = true arrayvec.workspace = true bitflags.workspace = true cov-mark = "2.0.0-pre.1" -dashmap.workspace = true drop_bomb = "0.1.5" either.workspace = true fst = { version = "0.4.7", default-features = false } @@ -25,14 +24,12 @@ la-arena.workspace = true rustc-hash.workspace = true tracing.workspace = true smallvec.workspace = true -hashbrown.workspace = true triomphe.workspace = true rustc_apfloat = "0.2.0" text-size.workspace = true salsa.workspace = true query-group.workspace = true -ra-ap-rustc_hashes.workspace = true ra-ap-rustc_parse_format.workspace = true ra-ap-rustc_abi.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml index 607199a62443d..5884c0a5a4a52 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml @@ -16,9 +16,7 @@ cov-mark = "2.0.0-pre.1" tracing.workspace = true either.workspace = true rustc-hash.workspace = true -la-arena.workspace = true itertools.workspace = true -hashbrown.workspace = true smallvec.workspace = true triomphe.workspace = true query-group.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml index 30074105331c5..49d0c5e58f530 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml @@ -29,9 +29,7 @@ chalk-recursive.workspace = true chalk-derive.workspace = true la-arena.workspace = true triomphe.workspace = true -nohash-hasher.workspace = true typed-arena = "2.0.1" -dashmap.workspace = true indexmap.workspace = true rustc_apfloat = "0.2.0" query-group.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml index 848556523387e..485a72050fc94 100644 --- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml @@ -15,7 +15,6 @@ rust-version.workspace = true cov-mark = "2.0.0-pre.1" crossbeam-channel.workspace = true tracing.workspace = true -dashmap.workspace = true rayon.workspace = true fst = { version = "0.4.7", default-features = false } rustc-hash.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml index fa75e5a421476..39a71c1d6558d 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml @@ -14,18 +14,16 @@ rust-version.workspace = true [dependencies] cov-mark = "2.0.0-pre.1" itertools.workspace = true -triomphe.workspace = true -nohash-hasher.workspace = true # local deps hir.workspace = true ide-db.workspace = true parser.workspace = true -stdx.workspace = true syntax.workspace = true [dev-dependencies] expect-test = "1.4.0" +triomphe.workspace = true # local deps test-utils.workspace = true diff --git a/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml b/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml index 23fd50a05644c..91b012e05071f 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml +++ b/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml @@ -21,7 +21,6 @@ tracing.workspace = true hir-expand.workspace = true ide-db.workspace = true -paths.workspace = true proc-macro-api.workspace = true project-model.workspace = true span.workspace = true diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml index e6fbb298ebdb7..6ee505e64efe6 100644 --- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml +++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml @@ -15,12 +15,10 @@ rust-version.workspace = true cov-mark = "2.0.0-pre.1" rustc-hash.workspace = true smallvec.workspace = true -tracing.workspace = true arrayvec.workspace = true ra-ap-rustc_lexer.workspace = true # local deps -syntax.workspace = true parser.workspace = true tt.workspace = true stdx.workspace = true @@ -31,9 +29,10 @@ syntax-bridge.workspace = true [dev-dependencies] test-utils.workspace = true expect-test.workspace = true +syntax.workspace = true [features] -in-rust-tree = ["parser/in-rust-tree", "tt/in-rust-tree", "syntax/in-rust-tree"] +in-rust-tree = ["parser/in-rust-tree", "tt/in-rust-tree"] [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs index 0e6b18ecaef19..c47ed053254bf 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs @@ -1,6 +1,7 @@ //! A standalone binary for `proc-macro-srv`. //! Driver for proc macro server #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +#![cfg_attr(not(feature = "sysroot-abi"), allow(unused_crate_dependencies))] #![allow(clippy::print_stderr)] #[cfg(feature = "in-rust-tree")] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml index d3b56b402ea83..8fd675d0d31f4 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml @@ -13,11 +13,9 @@ rust-version.workspace = true [dependencies] object.workspace = true -libc.workspace = true libloading.workspace = true memmap2.workspace = true -stdx.workspace = true tt.workspace = true syntax-bridge.workspace = true paths.workspace = true @@ -27,6 +25,9 @@ intern.workspace = true ra-ap-rustc_lexer.workspace = true +[target.'cfg(unix)'.dependencies] +libc.workspace = true + [dev-dependencies] expect-test.workspace = true diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index 4f817b6bc0a58..2623b2d45cd43 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -11,6 +11,7 @@ //! rustc rather than `unstable`. (Although in general ABI compatibility is still an issue)… #![cfg(any(feature = "sysroot-abi", rust_analyzer))] +#![cfg_attr(not(feature = "sysroot-abi"), allow(unused_crate_dependencies))] #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)] #![allow(unreachable_pub, internal_features, clippy::disallowed_types, clippy::print_stderr)] diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml index 9384fe265584f..376737cec677a 100644 --- a/src/tools/rust-analyzer/crates/profile/Cargo.toml +++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml @@ -13,12 +13,14 @@ rust-version.workspace = true [dependencies] cfg-if = "1.0.0" -libc.workspace = true jemalloc-ctl = { version = "0.5.0", package = "tikv-jemalloc-ctl", optional = true } [target.'cfg(all(target_os = "linux", not(target_env = "ohos")))'.dependencies] perf-event = "=0.4.7" +[target.'cfg(all(target_os = "linux", target_env = "gnu"))'.dependencies] +libc.workspace = true + [target.'cfg(windows)'.dependencies] windows-sys = { version = "0.59", features = [ "Win32_System_Threading", diff --git a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml index 99d1bf7e2c7ce..116028b5ba6dd 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml +++ b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml @@ -13,11 +13,10 @@ rust-version.workspace = true proc-macro = true [dependencies] -heck = "0.5.0" proc-macro2 = "1.0" quote = "1.0" syn = { version = "2.0", features = ["full", "extra-traits"] } -salsa.workspace = true [dev-dependencies] expect-test = "1.5.0" +salsa.workspace = true diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index 9d30c5d38eb42..d47074198fd70 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml @@ -47,7 +47,6 @@ tracing-tree.workspace = true triomphe.workspace = true toml = "0.8.8" nohash-hasher.workspace = true -always-assert = "0.2.0" walkdir = "2.3.2" semver.workspace = true memchr = "2.7.1" @@ -95,9 +94,7 @@ syntax-bridge.workspace = true [features] jemalloc = ["jemallocator", "profile/jemalloc"] force-always-assert = ["stdx/force-always-assert"] -sysroot-abi = [] in-rust-tree = [ - "sysroot-abi", "syntax/in-rust-tree", "parser/in-rust-tree", "hir/in-rust-tree", diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs index 0b51dd87fea0c..a09d96d16296b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs @@ -7,7 +7,6 @@ use cargo_metadata::PackageId; use ide::FileId; use ide_db::FxHashMap; use itertools::Itertools; -use nohash_hasher::{IntMap, IntSet}; use rustc_hash::FxHashSet; use stdx::iter_eq_by; use triomphe::Arc; @@ -15,7 +14,7 @@ use triomphe::Arc; use crate::{global_state::GlobalStateSnapshot, lsp, lsp_ext, main_loop::DiagnosticsTaskKind}; pub(crate) type CheckFixes = - Arc>, IntMap>>>>; + Arc>, FxHashMap>>>>; #[derive(Debug, Default, Clone)] pub struct DiagnosticsMapConfig { @@ -29,16 +28,16 @@ pub(crate) type DiagnosticsGeneration = usize; #[derive(Debug, Default, Clone)] pub(crate) struct DiagnosticCollection { - // FIXME: should be IntMap> - pub(crate) native_syntax: IntMap)>, - pub(crate) native_semantic: IntMap)>, + // FIXME: should be FxHashMap> + pub(crate) native_syntax: + FxHashMap)>, + pub(crate) native_semantic: + FxHashMap)>, // FIXME: should be Vec - pub(crate) check: IntMap< - usize, - FxHashMap>, IntMap>>, - >, + pub(crate) check: + Vec>, FxHashMap>>>, pub(crate) check_fixes: CheckFixes, - changes: IntSet, + changes: FxHashSet, /// Counter for supplying a new generation number for diagnostics. /// This is used to keep track of when to clear the diagnostics for a given file as we compute /// diagnostics on multiple worker threads simultaneously which may result in multiple diagnostics @@ -55,11 +54,11 @@ pub(crate) struct Fix { impl DiagnosticCollection { pub(crate) fn clear_check(&mut self, flycheck_id: usize) { - let Some(check) = self.check.get_mut(&flycheck_id) else { + let Some(check) = self.check.get_mut(flycheck_id) else { return; }; self.changes.extend(check.drain().flat_map(|(_, v)| v.into_keys())); - if let Some(fixes) = Arc::make_mut(&mut self.check_fixes).get_mut(&flycheck_id) { + if let Some(fixes) = Arc::make_mut(&mut self.check_fixes).get_mut(flycheck_id) { fixes.clear(); } } @@ -67,7 +66,7 @@ impl DiagnosticCollection { pub(crate) fn clear_check_all(&mut self) { Arc::make_mut(&mut self.check_fixes).clear(); self.changes.extend( - self.check.values_mut().flat_map(|it| it.drain().flat_map(|(_, v)| v.into_keys())), + self.check.iter_mut().flat_map(|it| it.drain().flat_map(|(_, v)| v.into_keys())), ) } @@ -76,14 +75,14 @@ impl DiagnosticCollection { flycheck_id: usize, package_id: Arc, ) { - let Some(check) = self.check.get_mut(&flycheck_id) else { + let Some(check) = self.check.get_mut(flycheck_id) else { return; }; let package_id = Some(package_id); if let Some(checks) = check.remove(&package_id) { self.changes.extend(checks.into_keys()); } - if let Some(fixes) = Arc::make_mut(&mut self.check_fixes).get_mut(&flycheck_id) { + if let Some(fixes) = Arc::make_mut(&mut self.check_fixes).get_mut(flycheck_id) { fixes.remove(&package_id); } } @@ -102,10 +101,10 @@ impl DiagnosticCollection { diagnostic: lsp_types::Diagnostic, fix: Option>, ) { - let diagnostics = self - .check - .entry(flycheck_id) - .or_default() + if self.check.len() <= flycheck_id { + self.check.resize_with(flycheck_id + 1, Default::default); + } + let diagnostics = self.check[flycheck_id] .entry(package_id.clone()) .or_default() .entry(file_id) @@ -118,9 +117,10 @@ impl DiagnosticCollection { if let Some(fix) = fix { let check_fixes = Arc::make_mut(&mut self.check_fixes); - check_fixes - .entry(flycheck_id) - .or_default() + if check_fixes.len() <= flycheck_id { + check_fixes.resize_with(flycheck_id + 1, Default::default); + } + check_fixes[flycheck_id] .entry(package_id.clone()) .or_default() .entry(file_id) @@ -176,14 +176,14 @@ impl DiagnosticCollection { let native_semantic = self.native_semantic.get(&file_id).into_iter().flat_map(|(_, d)| d); let check = self .check - .values() + .iter() .flat_map(|it| it.values()) .filter_map(move |it| it.get(&file_id)) .flatten(); native_syntax.chain(native_semantic).chain(check) } - pub(crate) fn take_changes(&mut self) -> Option> { + pub(crate) fn take_changes(&mut self) -> Option> { if self.changes.is_empty() { return None; } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index af1f6ce2b0b11..6fc0ba9e66cdb 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -12,7 +12,6 @@ use ide_db::base_db::{Crate, ProcMacroPaths, SourceDatabase}; use itertools::Itertools; use load_cargo::SourceRootConfig; use lsp_types::{SemanticTokens, Url}; -use nohash_hasher::IntMap; use parking_lot::{ MappedRwLockReadGuard, Mutex, RwLock, RwLockReadGuard, RwLockUpgradableReadGuard, RwLockWriteGuard, @@ -117,7 +116,7 @@ pub(crate) struct GlobalState { // VFS pub(crate) loader: Handle, Receiver>, - pub(crate) vfs: Arc)>>, + pub(crate) vfs: Arc)>>, pub(crate) vfs_config_version: u32, pub(crate) vfs_progress_config_version: u32, pub(crate) vfs_done: bool, @@ -181,7 +180,7 @@ pub(crate) struct GlobalStateSnapshot { pub(crate) check_fixes: CheckFixes, mem_docs: MemDocs, pub(crate) semantic_tokens_cache: Arc>>, - vfs: Arc)>>, + vfs: Arc)>>, pub(crate) workspaces: Arc>, // used to signal semantic highlighting to fall back to syntax based highlighting until // proc-macros have been loaded @@ -265,7 +264,7 @@ impl GlobalState { discover_sender, discover_receiver, - vfs: Arc::new(RwLock::new((vfs::Vfs::default(), IntMap::default()))), + vfs: Arc::new(RwLock::new((vfs::Vfs::default(), Default::default()))), vfs_config_version: 0, vfs_progress_config_version: 0, vfs_span: None, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index ec8b324aac3cf..75fe99e95d918 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -1465,7 +1465,7 @@ pub(crate) fn handle_code_action( // Fixes from `cargo check`. for fix in snap .check_fixes - .values() + .iter() .flat_map(|it| it.values()) .filter_map(|it| it.get(&frange.file_id)) .flatten() diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index 9cc990eec06a2..47fcb5ac02b76 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -8,7 +8,6 @@ use std::{ time::{Duration, Instant}, }; -use always_assert::always; use crossbeam_channel::{Receiver, select}; use ide_db::base_db::{SourceDatabase, VfsPath, salsa::Database as _}; use lsp_server::{Connection, Notification, Request}; @@ -845,7 +844,7 @@ impl GlobalState { } vfs::loader::Message::Progress { n_total, n_done, dir, config_version } => { let _p = span!(Level::INFO, "GlobalState::handle_vfs_msg/progress").entered(); - always!(config_version <= self.vfs_config_version); + stdx::always!(config_version <= self.vfs_config_version); let (n_done, state) = match n_done { LoadingProgress::Started => { diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml index 3727d0c9562e6..f6a5dedfda2c2 100644 --- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml +++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml @@ -14,12 +14,14 @@ rust-version.workspace = true [dependencies] backtrace = { version = "0.3.67", optional = true } jod-thread = "0.1.2" -libc.workspace = true crossbeam-channel.workspace = true itertools.workspace = true tracing.workspace = true # Think twice before adding anything here +[target.'cfg(unix)'.dependencies] +libc.workspace = true + [target.'cfg(windows)'.dependencies] miow = "0.6.0" windows-sys = { version = "0.59", features = ["Win32_Foundation"] } diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml b/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml index 3e663422a04ec..cccd41d542991 100644 --- a/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml @@ -13,7 +13,6 @@ rust-version.workspace = true [dependencies] rustc-hash.workspace = true -tracing.workspace = true # local deps syntax.workspace = true diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 3fe6e01dc3c92..7db1a4e4ba103 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -12,12 +12,10 @@ rust-version.workspace = true [lib] [dependencies] -cov-mark = "2.0.0-pre.1" either.workspace = true itertools.workspace = true rowan = "=0.15.15" rustc-hash.workspace = true -indexmap.workspace = true smol_str.workspace = true triomphe.workspace = true tracing.workspace = true diff --git a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml index b99a2c4bd75c5..f25512b2b7e12 100644 --- a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml +++ b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml @@ -15,7 +15,6 @@ rust-version.workspace = true # Avoid adding deps here, this crate is widely used in tests it should compile fast! dissimilar = "1.0.7" text-size.workspace = true -tracing.workspace = true rustc-hash.workspace = true paths.workspace = true From d96df9d4384af61e4d70d1d11698e03012370fee Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 23 Mar 2025 08:13:14 +0100 Subject: [PATCH 0237/2248] chore: Bump dependencies --- src/tools/rust-analyzer/Cargo.lock | 202 +++++++++++------- src/tools/rust-analyzer/Cargo.toml | 69 +++--- src/tools/rust-analyzer/crates/cfg/Cargo.toml | 8 +- .../rust-analyzer/crates/hir-def/Cargo.toml | 4 +- .../crates/hir-expand/Cargo.toml | 4 +- .../rust-analyzer/crates/hir-ty/Cargo.toml | 14 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 6 +- .../crates/hir/src/source_analyzer.rs | 2 +- .../crates/ide-assists/Cargo.toml | 4 +- .../ide-assists/src/handlers/remove_dbg.rs | 2 +- .../crates/ide-completion/Cargo.toml | 4 +- .../src/completions/attribute.rs | 2 +- .../rust-analyzer/crates/ide-db/Cargo.toml | 6 +- .../ide-db/src/syntax_helpers/node_ext.rs | 2 +- .../crates/ide-diagnostics/Cargo.toml | 4 +- .../rust-analyzer/crates/ide-ssr/Cargo.toml | 4 +- src/tools/rust-analyzer/crates/ide/Cargo.toml | 6 +- src/tools/rust-analyzer/crates/mbe/Cargo.toml | 2 +- .../rust-analyzer/crates/parser/Cargo.toml | 2 +- .../proc-macro-srv/proc-macro-test/Cargo.toml | 2 +- .../proc-macro-srv/proc-macro-test/build.rs | 2 +- .../rust-analyzer/crates/profile/Cargo.toml | 2 +- .../crates/project-model/Cargo.toml | 2 +- .../project-model/src/build_dependencies.rs | 7 +- .../project-model/src/cargo_workspace.rs | 24 ++- .../crates/query-group-macro/Cargo.toml | 2 +- .../crates/rust-analyzer/Cargo.toml | 24 +-- .../crates/rust-analyzer/src/diagnostics.rs | 2 +- .../rust-analyzer/crates/stdx/Cargo.toml | 2 +- .../rust-analyzer/crates/syntax/Cargo.toml | 4 +- .../crates/test-utils/Cargo.toml | 2 +- .../rust-analyzer/crates/toolchain/Cargo.toml | 2 +- .../crates/vfs-notify/Cargo.toml | 2 +- .../rust-analyzer/lib/line-index/Cargo.toml | 2 +- .../rust-analyzer/lib/lsp-server/Cargo.toml | 10 +- src/tools/rust-analyzer/xtask/Cargo.toml | 14 +- src/tools/rust-analyzer/xtask/src/dist.rs | 6 +- 37 files changed, 261 insertions(+), 197 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 4310cfc04a88a..4a01a658576b7 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -43,6 +43,9 @@ name = "arbitrary" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] [[package]] name = "arrayvec" @@ -66,7 +69,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.36.7", + "object", "rustc-demangle", "windows-targets 0.52.6", ] @@ -127,10 +130,10 @@ dependencies = [ ] [[package]] -name = "byteorder" -version = "1.5.0" +name = "bumpalo" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "camino" @@ -152,16 +155,16 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.18.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", "semver", "serde", "serde_json", - "thiserror", + "thiserror 2.0.12", ] [[package]] @@ -246,7 +249,7 @@ dependencies = [ "chalk-ir", "ena", "indexmap", - "itertools", + "itertools 0.12.1", "petgraph", "rustc-hash 1.1.0", "tracing", @@ -355,9 +358,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", ] @@ -375,32 +378,32 @@ dependencies = [ [[package]] name = "directories" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" dependencies = [ "dirs-sys", ] [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -607,7 +610,7 @@ dependencies = [ "hir-ty", "indexmap", "intern", - "itertools", + "itertools 0.14.0", "rustc-hash 2.1.1", "smallvec", "span", @@ -637,7 +640,7 @@ dependencies = [ "hir-expand", "indexmap", "intern", - "itertools", + "itertools 0.14.0", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "mbe", "query-group-macro", @@ -669,7 +672,7 @@ dependencies = [ "either", "expect-test", "intern", - "itertools", + "itertools 0.14.0", "mbe", "parser", "query-group-macro", @@ -704,7 +707,7 @@ dependencies = [ "hir-expand", "indexmap", "intern", - "itertools", + "itertools 0.14.0", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "oorandom", "project-model", @@ -872,7 +875,7 @@ dependencies = [ "ide-db", "ide-diagnostics", "ide-ssr", - "itertools", + "itertools 0.14.0", "nohash-hasher", "oorandom", "profile", @@ -900,7 +903,7 @@ dependencies = [ "expect-test", "hir", "ide-db", - "itertools", + "itertools 0.14.0", "smallvec", "stdx", "syntax", @@ -918,7 +921,7 @@ dependencies = [ "expect-test", "hir", "ide-db", - "itertools", + "itertools 0.14.0", "smallvec", "stdx", "syntax", @@ -941,7 +944,7 @@ dependencies = [ "fst", "hir", "indexmap", - "itertools", + "itertools 0.14.0", "line-index 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "memchr", "nohash-hasher", @@ -971,7 +974,7 @@ dependencies = [ "expect-test", "hir", "ide-db", - "itertools", + "itertools 0.14.0", "paths", "serde_json", "stdx", @@ -989,7 +992,7 @@ dependencies = [ "expect-test", "hir", "ide-db", - "itertools", + "itertools 0.14.0", "parser", "syntax", "test-fixture", @@ -1020,9 +1023,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -1068,6 +1071,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.15" @@ -1118,9 +1130,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.170" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libloading" @@ -1134,9 +1146,9 @@ dependencies = [ [[package]] name = "libmimalloc-sys" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +checksum = "07d0e07885d6a754b9c7993f2625187ad694ee985d60f23355ff0e7077261502" dependencies = [ "cc", "libc", @@ -1187,7 +1199,7 @@ dependencies = [ "hir-expand", "ide-db", "intern", - "itertools", + "itertools 0.14.0", "proc-macro-api", "project-model", "span", @@ -1207,6 +1219,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "lockfree-object-pool" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" + [[package]] name = "log" version = "0.4.26" @@ -1302,9 +1320,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" -version = "0.5.10" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] @@ -1320,9 +1338,9 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +checksum = "99585191385958383e13f6b822e6b6d8d9cf928e7d286ceb092da92b43c87bc1" dependencies = [ "libmimalloc-sys", ] @@ -1444,15 +1462,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d" -dependencies = [ - "memchr", -] - [[package]] name = "object" version = "0.36.7" @@ -1464,9 +1473,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.0" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" [[package]] name = "oorandom" @@ -1613,7 +1622,7 @@ dependencies = [ "libc", "libloading", "memmap2", - "object 0.33.0", + "object", "paths", "proc-macro-test", "ra-ap-rustc_lexer", @@ -1680,7 +1689,7 @@ dependencies = [ "cfg", "expect-test", "intern", - "itertools", + "itertools 0.14.0", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "paths", "rustc-hash 2.1.1", @@ -1703,7 +1712,7 @@ checksum = "a3a7c64d9bf75b1b8d981124c14c179074e8caa7dfe7b6a12e6222ddcd0c8f72" dependencies = [ "once_cell", "protobuf-support", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1712,7 +1721,7 @@ version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b088fd20b938a875ea00843b6faf48579462630015c3788d397ad6a786663252" dependencies = [ - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1748,9 +1757,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -1862,13 +1871,13 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 2.0.12", ] [[package]] @@ -1949,7 +1958,7 @@ dependencies = [ "ide-ssr", "indexmap", "intern", - "itertools", + "itertools 0.14.0", "load-cargo", "lsp-server 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-types", @@ -2187,6 +2196,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "smallvec" version = "1.14.0" @@ -2229,7 +2244,7 @@ version = "0.0.0" dependencies = [ "backtrace", "crossbeam-channel", - "itertools", + "itertools 0.14.0", "jod-thread", "libc", "miow", @@ -2265,7 +2280,7 @@ version = "0.0.0" dependencies = [ "either", "expect-test", - "itertools", + "itertools 0.14.0", "parser", "ra-ap-rustc_lexer", "rayon", @@ -2339,7 +2354,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", ] [[package]] @@ -2353,6 +2377,17 @@ dependencies = [ "syn", ] +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.8" @@ -2396,9 +2431,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.39" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" +checksum = "9d9c75b47bdff86fa3334a3db91356b8d7d86a9b839dab7d0bdc5c3d3a077618" dependencies = [ "deranged", "itoa", @@ -2413,15 +2448,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" +checksum = "29aa485584182073ed57fd5004aa09c371f021325014694e432313345865fd04" dependencies = [ "num-conv", "time-core", @@ -2543,9 +2578,9 @@ dependencies = [ [[package]] name = "tracing-tree" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b56c62d2c80033cb36fae448730a2f2ef99410fe3ecbffc916681a32f6807dbe" +checksum = "f459ca79f1b0d5f71c54ddfde6debfc59c8b6eeb46808ae492077f739dc7b49c" dependencies = [ "nu-ansi-term 0.50.1", "tracing-core", @@ -3123,7 +3158,7 @@ dependencies = [ "edition", "either", "flate2", - "itertools", + "itertools 0.14.0", "proc-macro2", "quote", "stdx", @@ -3204,13 +3239,32 @@ dependencies = [ [[package]] name = "zip" -version = "0.6.6" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50" dependencies = [ - "byteorder", + "arbitrary", "crc32fast", "crossbeam-utils", + "displaydoc", "flate2", + "indexmap", + "memchr", + "thiserror 2.0.12", "time", + "zopfli", +] + +[[package]] +name = "zopfli" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +dependencies = [ + "bumpalo", + "crc32fast", + "lockfree-object-pool", + "log", + "once_cell", + "simd-adler32", ] diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 03ecc8f2741e3..49365cd0225c9 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -97,60 +97,57 @@ ra-ap-rustc_pattern_analysis = { version = "0.100", default-features = false } # in-tree crates that are published separately and follow semver. See lib/README.md line-index = { version = "0.1.2" } la-arena = { version = "0.3.1" } -lsp-server = { version = "0.7.6" } +lsp-server = { version = "0.7.8" } # non-local crates -anyhow = "1.0.75" -arrayvec = "0.7.4" -bitflags = "2.4.1" -cargo_metadata = "0.18.1" -camino = "1.1.6" +anyhow = "1.0.97" +arrayvec = "0.7.6" +bitflags = "2.9.0" +cargo_metadata = "0.19.2" +camino = "1.1.9" chalk-solve = { version = "0.100.0", default-features = false } chalk-ir = "0.100.0" chalk-recursive = { version = "0.100.0", default-features = false } chalk-derive = "0.100.0" -crossbeam-channel = "0.5.8" -dissimilar = "1.0.7" +crossbeam-channel = "0.5.14" +dissimilar = "1.0.10" dot = "0.1.4" -either = "1.9.0" -expect-test = "1.4.0" -hashbrown = { version = "0.14", features = [ - "inline-more", -], default-features = false } -indexmap = { version = "2.1.0", features = ["serde"] } -itertools = "0.12.0" -libc = "0.2.150" -libloading = "0.8.0" -memmap2 = "0.5.4" +either = "1.15.0" +expect-test = "1.5.1" +indexmap = { version = "2.8.0", features = ["serde"] } +itertools = "0.14.0" +libc = "0.2.171" +libloading = "0.8.6" +memmap2 = "0.9.5" nohash-hasher = "0.2.0" -oorandom = "11.1.3" -object = { version = "0.33.0", default-features = false, features = [ +oorandom = "11.1.5" +object = { version = "0.36.7", default-features = false, features = [ "std", "read_core", "elf", "macho", "pe", ] } -process-wrap = { version = "8.0.2", features = ["std"] } +process-wrap = { version = "8.2.0", features = ["std"] } pulldown-cmark-to-cmark = "10.0.4" -pulldown-cmark = { version = "0.9.0", default-features = false } -rayon = "1.8.0" +pulldown-cmark = { version = "0.9.6", default-features = false } +rayon = "1.10.0" salsa = "0.19" -rustc-hash = "2.0.0" -semver = "1.0.14" -serde = { version = "1.0.192" } -serde_derive = { version = "1.0.192" } -serde_json = "1.0.108" -smallvec = { version = "1.10.0", features = [ +rustc-hash = "2.1.1" +semver = "1.0.26" +serde = { version = "1.0.219" } +serde_derive = { version = "1.0.219" } +serde_json = "1.0.140" +smallvec = { version = "1.14.0", features = [ "const_new", "union", "const_generics", ] } smol_str = "0.3.2" text-size = "1.1.1" -tracing = "0.1.40" -tracing-tree = "0.3.0" -tracing-subscriber = { version = "0.3.18", default-features = false, features = [ +tracing = "0.1.41" +tracing-tree = "0.4.0" +tracing-subscriber = { version = "0.3.19", default-features = false, features = [ "registry", "fmt", "local-time", @@ -159,12 +156,16 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features = "tracing-log", ] } triomphe = { version = "0.1.14", default-features = false, features = ["std"] } -url = "2.3.1" -xshell = "0.2.5" +url = "2.5.4" +xshell = "0.2.7" # We need to freeze the version of the crate, as the raw-api feature is considered unstable dashmap = { version = "=5.5.3", features = ["raw-api"] } +# We need to freeze the version of the crate, as it needs to match with dashmap +hashbrown = { version = "=0.14.5", features = [ + "inline-more", +], default-features = false } [workspace.lints.rust] # remember to update RUSTFLAGS in ci.yml if you add something here diff --git a/src/tools/rust-analyzer/crates/cfg/Cargo.toml b/src/tools/rust-analyzer/crates/cfg/Cargo.toml index e887368ef28f8..d7764a16c044c 100644 --- a/src/tools/rust-analyzer/crates/cfg/Cargo.toml +++ b/src/tools/rust-analyzer/crates/cfg/Cargo.toml @@ -20,13 +20,13 @@ tt = { workspace = true, optional = true } intern.workspace = true [dev-dependencies] -expect-test = "1.4.1" -oorandom = "11.1.3" +expect-test = "1.5.1" +oorandom = "11.1.5" # We depend on both individually instead of using `features = ["derive"]` to microoptimize the # build graph: if the feature was enabled, syn would be built early on in the graph if `smolstr` # supports `arbitrary`. This way, we avoid feature unification. -arbitrary = "1.3.2" -derive_arbitrary = "1.3.2" +arbitrary = "1.4.1" +derive_arbitrary = "1.4.1" # local deps syntax-bridge.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml index 628a78cdeafbe..98d24d20b0cd2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml @@ -14,7 +14,7 @@ rust-version.workspace = true [dependencies] arrayvec.workspace = true bitflags.workspace = true -cov-mark = "2.0.0-pre.1" +cov-mark = "2.0.0" drop_bomb = "0.1.5" either.workspace = true fst = { version = "0.4.7", default-features = false } @@ -25,7 +25,7 @@ rustc-hash.workspace = true tracing.workspace = true smallvec.workspace = true triomphe.workspace = true -rustc_apfloat = "0.2.0" +rustc_apfloat = "0.2.2" text-size.workspace = true salsa.workspace = true query-group.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml index 5884c0a5a4a52..b83efca255286 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -cov-mark = "2.0.0-pre.1" +cov-mark = "2.0.0" tracing.workspace = true either.workspace = true rustc-hash.workspace = true @@ -35,7 +35,7 @@ parser.workspace = true syntax-bridge.workspace = true [dev-dependencies] -expect-test = "1.4.0" +expect-test = "1.5.1" [features] in-rust-tree = ["syntax/in-rust-tree"] diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml index 49d0c5e58f530..69ad7703c2caf 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml @@ -12,26 +12,26 @@ rust-version.workspace = true [lib] [dependencies] -cov-mark = "2.0.0-pre.1" +cov-mark = "2.0.0" itertools.workspace = true arrayvec.workspace = true bitflags.workspace = true smallvec.workspace = true -ena = "0.14.0" +ena = "0.14.3" either.workspace = true -oorandom = "11.1.3" +oorandom = "11.1.5" tracing.workspace = true rustc-hash.workspace = true -scoped-tls = "1.0.0" +scoped-tls = "1.0.1" chalk-solve.workspace = true chalk-ir.workspace = true chalk-recursive.workspace = true chalk-derive.workspace = true la-arena.workspace = true triomphe.workspace = true -typed-arena = "2.0.1" +typed-arena = "2.0.2" indexmap.workspace = true -rustc_apfloat = "0.2.0" +rustc_apfloat = "0.2.2" query-group.workspace = true salsa.workspace = true @@ -50,7 +50,7 @@ syntax.workspace = true span.workspace = true [dev-dependencies] -expect-test = "1.4.0" +expect-test = "1.5.1" tracing.workspace = true tracing-subscriber.workspace = true tracing-tree.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 1e58c076f225d..124cbd2ed1a35 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -1221,15 +1221,15 @@ fn precise_macro_call_location( .nth(derive_attr_index.ast_index()) .and_then(|x| Either::left(x.1))?; let token_tree = derive_attr.meta()?.token_tree()?; - let group_by = token_tree + let chunk_by = token_tree .syntax() .children_with_tokens() .filter_map(|elem| match elem { syntax::NodeOrToken::Token(tok) => Some(tok), _ => None, }) - .group_by(|t| t.kind() == T![,]); - let (_, mut group) = group_by + .chunk_by(|t| t.kind() == T![,]); + let (_, mut group) = chunk_by .into_iter() .filter(|&(comma, _)| !comma) .nth(*derive_index as usize)?; diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index bb5c7c0d20600..ba5ceef00a698 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -929,7 +929,7 @@ impl SourceAnalyzer { // FIXME: Multiple derives can have the same helper let name_ref = name_ref.as_name(); for (macro_id, mut helpers) in - helpers.iter().group_by(|(_, macro_id, ..)| macro_id).into_iter() + helpers.iter().chunk_by(|(_, macro_id, ..)| macro_id).into_iter() { if let Some(idx) = helpers.position(|(name, ..)| *name == name_ref) { diff --git a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml index 3768c2257cadd..53af980c194c5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -cov-mark = "2.0.0-pre.1" +cov-mark = "2.0.0" itertools.workspace = true either.workspace = true @@ -26,7 +26,7 @@ ide-db.workspace = true hir.workspace = true [dev-dependencies] -expect-test = "1.4.0" +expect-test = "1.5.1" # local deps test-utils.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs index 809ef6dae3122..f2767a32213c9 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs @@ -74,7 +74,7 @@ fn compute_dbg_replacement(macro_expr: ast::MacroExpr) -> Option<(TextRange, Opt } let mac_input = tt.syntax().children_with_tokens().skip(1).take_while(|it| *it != r_delim); - let input_expressions = mac_input.group_by(|tok| tok.kind() == T![,]); + let input_expressions = mac_input.chunk_by(|tok| tok.kind() == T![,]); let input_expressions = input_expressions .into_iter() .filter_map(|(is_sep, group)| (!is_sep).then_some(group)) diff --git a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml index 68cc7a0b9a6df..94c01e333ed44 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -cov-mark = "2.0.0-pre.1" +cov-mark = "2.0.0" itertools.workspace = true tracing.workspace = true @@ -29,7 +29,7 @@ syntax.workspace = true hir.workspace = true [dev-dependencies] -expect-test = "1.4.0" +expect-test = "1.5.1" # local deps test-utils.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs index fb7df8cc7f448..3c195f80fea47 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs @@ -380,7 +380,7 @@ fn parse_comma_sep_expr(input: ast::TokenTree) -> Option> { .children_with_tokens() .skip(1) .take_while(|it| it.as_token() != Some(&r_paren)); - let input_expressions = tokens.group_by(|tok| tok.kind() == T![,]); + let input_expressions = tokens.chunk_by(|tok| tok.kind() == T![,]); Some( input_expressions .into_iter() diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml index 485a72050fc94..f1d6b605b0021 100644 --- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -cov-mark = "2.0.0-pre.1" +cov-mark = "2.0.0" crossbeam-channel.workspace = true tracing.workspace = true rayon.workspace = true @@ -22,7 +22,7 @@ either.workspace = true itertools.workspace = true arrayvec.workspace = true indexmap.workspace = true -memchr = "2.6.4" +memchr = "2.7.4" salsa.workspace = true query-group.workspace = true triomphe.workspace = true @@ -44,7 +44,7 @@ hir.workspace = true line-index.workspace = true [dev-dependencies] -expect-test = "1.4.0" +expect-test = "1.5.1" # local deps test-utils.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs index f0aa3daf55b63..cd47524caa3c5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs @@ -484,7 +484,7 @@ pub fn parse_tt_as_comma_sep_paths( None => None, Some(tok) => Some(tok), }); - let input_expressions = tokens.group_by(|tok| tok.kind() == T![,]); + let input_expressions = tokens.chunk_by(|tok| tok.kind() == T![,]); let paths = input_expressions .into_iter() .filter_map(|(is_sep, group)| (!is_sep).then_some(group)) diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml index 483cb6df86236..96be51e1b2666 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -cov-mark = "2.0.0-pre.1" +cov-mark = "2.0.0" either.workspace = true itertools.workspace = true serde_json.workspace = true @@ -27,7 +27,7 @@ ide-db.workspace = true paths.workspace = true [dev-dependencies] -expect-test = "1.4.0" +expect-test = "1.5.1" # local deps test-utils.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml index 39a71c1d6558d..1212fa9f9c65f 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -cov-mark = "2.0.0-pre.1" +cov-mark = "2.0.0" itertools.workspace = true # local deps @@ -22,7 +22,7 @@ parser.workspace = true syntax.workspace = true [dev-dependencies] -expect-test = "1.4.0" +expect-test = "1.5.1" triomphe.workspace = true # local deps diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml index 9af56c40e982e..1d19daf2f5aa9 100644 --- a/src/tools/rust-analyzer/crates/ide/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -cov-mark = "2.0.0-pre.1" +cov-mark = "2.0.0" arrayvec.workspace = true either.workspace = true itertools.workspace = true @@ -25,7 +25,7 @@ dot.workspace = true smallvec.workspace = true triomphe.workspace = true nohash-hasher.workspace = true -rustc_apfloat = "0.2.0" +rustc_apfloat = "0.2.2" # local deps cfg.workspace = true @@ -46,7 +46,7 @@ hir.workspace = true toolchain.workspace = true [dev-dependencies] -expect-test = "1.4.0" +expect-test = "1.5.1" # local deps test-utils.workspace = true diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml index 6ee505e64efe6..f3ab093bae08a 100644 --- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml +++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -cov-mark = "2.0.0-pre.1" +cov-mark = "2.0.0" rustc-hash.workspace = true smallvec.workspace = true arrayvec.workspace = true diff --git a/src/tools/rust-analyzer/crates/parser/Cargo.toml b/src/tools/rust-analyzer/crates/parser/Cargo.toml index a36a39dbee6ce..a90edfca28d9a 100644 --- a/src/tools/rust-analyzer/crates/parser/Cargo.toml +++ b/src/tools/rust-analyzer/crates/parser/Cargo.toml @@ -19,7 +19,7 @@ tracing = { workspace = true, optional = true } edition.workspace = true [dev-dependencies] -expect-test = "1.4.0" +expect-test = "1.5.1" stdx.workspace = true diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml index 2a5bfdd2572f4..eddefb33c0ff1 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml @@ -9,4 +9,4 @@ license = "MIT OR Apache-2.0" [lib] [build-dependencies] -cargo_metadata = "0.18.1" +cargo_metadata = "0.19.2" diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs index d3d58a6df0115..b97569d4dbdf1 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs @@ -110,7 +110,7 @@ fn main() { let mut artifact_path = None; for message in Message::parse_stream(output.stdout.as_slice()) { if let Message::CompilerArtifact(artifact) = message.unwrap() { - if artifact.target.kind.contains(&"proc-macro".to_string()) + if artifact.target.kind.contains(&cargo_metadata::TargetKind::ProcMacro) && (artifact.package_id.repr.starts_with(&repr) || artifact.package_id.repr == pkgid) { diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml index 376737cec677a..1fb13832720e6 100644 --- a/src/tools/rust-analyzer/crates/profile/Cargo.toml +++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml @@ -13,7 +13,7 @@ rust-version.workspace = true [dependencies] cfg-if = "1.0.0" -jemalloc-ctl = { version = "0.5.0", package = "tikv-jemalloc-ctl", optional = true } +jemalloc-ctl = { version = "0.5.4", package = "tikv-jemalloc-ctl", optional = true } [target.'cfg(all(target_os = "linux", not(target_env = "ohos")))'.dependencies] perf-event = "=0.4.7" diff --git a/src/tools/rust-analyzer/crates/project-model/Cargo.toml b/src/tools/rust-analyzer/crates/project-model/Cargo.toml index 83def0e6b2a91..64ea75922fbe4 100644 --- a/src/tools/rust-analyzer/crates/project-model/Cargo.toml +++ b/src/tools/rust-analyzer/crates/project-model/Cargo.toml @@ -34,7 +34,7 @@ stdx.workspace = true toolchain.workspace = true [dev-dependencies] -expect-test = "1.4.0" +expect-test = "1.5.1" [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs index aa0099d0e57e3..631787bf8e6fa 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs @@ -343,7 +343,12 @@ impl WorkspaceBuildScripts { Message::CompilerArtifact(message) => { with_output_for(&message.package_id.repr, &mut |name, data| { progress(format!("building proc-macros: {name}")); - if message.target.kind.iter().any(|k| k == "proc-macro") { + if message + .target + .kind + .iter() + .any(|k| *k == cargo_metadata::TargetKind::ProcMacro) + { // Skip rmeta file if let Some(filename) = message.filenames.iter().find(|file| is_dylib(file)) diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 6a932d21f77f0..971193229a34e 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -232,16 +232,20 @@ pub enum TargetKind { } impl TargetKind { - fn new(kinds: &[String]) -> TargetKind { + fn new(kinds: &[cargo_metadata::TargetKind]) -> TargetKind { for kind in kinds { - return match kind.as_str() { - "bin" => TargetKind::Bin, - "test" => TargetKind::Test, - "bench" => TargetKind::Bench, - "example" => TargetKind::Example, - "custom-build" => TargetKind::BuildScript, - "proc-macro" => TargetKind::Lib { is_proc_macro: true }, - _ if kind.contains("lib") => TargetKind::Lib { is_proc_macro: false }, + return match kind { + cargo_metadata::TargetKind::Bin => TargetKind::Bin, + cargo_metadata::TargetKind::Test => TargetKind::Test, + cargo_metadata::TargetKind::Bench => TargetKind::Bench, + cargo_metadata::TargetKind::Example => TargetKind::Example, + cargo_metadata::TargetKind::CustomBuild => TargetKind::BuildScript, + cargo_metadata::TargetKind::ProcMacro => TargetKind::Lib { is_proc_macro: true }, + cargo_metadata::TargetKind::Lib + | cargo_metadata::TargetKind::DyLib + | cargo_metadata::TargetKind::CDyLib + | cargo_metadata::TargetKind::StaticLib + | cargo_metadata::TargetKind::RLib => TargetKind::Lib { is_proc_macro: false }, _ => continue, }; } @@ -476,7 +480,7 @@ impl CargoWorkspace { cargo_metadata::Edition::E2015 => Edition::Edition2015, cargo_metadata::Edition::E2018 => Edition::Edition2018, cargo_metadata::Edition::E2021 => Edition::Edition2021, - cargo_metadata::Edition::_E2024 => Edition::Edition2024, + cargo_metadata::Edition::E2024 => Edition::Edition2024, _ => { tracing::error!("Unsupported edition `{:?}`", edition); Edition::CURRENT diff --git a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml index 116028b5ba6dd..ec37619751f68 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml +++ b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml @@ -18,5 +18,5 @@ quote = "1.0" syn = { version = "2.0", features = ["full", "extra-traits"] } [dev-dependencies] -expect-test = "1.5.0" +expect-test = "1.5.1" salsa.workspace = true diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index d47074198fd70..af7b4e676c859 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml @@ -22,34 +22,34 @@ path = "src/bin/main.rs" anyhow.workspace = true base64 = "0.22" crossbeam-channel.workspace = true -dirs = "5.0.1" +dirs = "6.0.0" dissimilar.workspace = true ide-completion.workspace = true indexmap.workspace = true itertools.workspace = true -scip = "0.5.1" +scip = "0.5.2" lsp-types = { version = "=0.95.0", features = ["proposed"] } -parking_lot = "0.12.1" -xflags = "0.3.0" -oorandom = "11.1.3" +parking_lot = "0.12.3" +xflags = "0.3.2" +oorandom = "11.1.5" rayon.workspace = true rustc-hash.workspace = true serde_json = { workspace = true, features = ["preserve_order"] } serde.workspace = true serde_derive.workspace = true tenthash = "1.0.0" -num_cpus = "1.15.0" -mimalloc = { version = "0.1.30", default-features = false, optional = true } +num_cpus = "1.16.0" +mimalloc = { version = "0.1.44", default-features = false, optional = true } lsp-server.workspace = true tracing.workspace = true tracing-subscriber.workspace = true tracing-tree.workspace = true triomphe.workspace = true -toml = "0.8.8" +toml = "0.8.20" nohash-hasher.workspace = true -walkdir = "2.3.2" +walkdir = "2.5.0" semver.workspace = true -memchr = "2.7.1" +memchr = "2.7.4" cargo_metadata.workspace = true process-wrap.workspace = true @@ -81,10 +81,10 @@ windows-sys = { version = "0.59", features = [ ] } [target.'cfg(not(target_env = "msvc"))'.dependencies] -jemallocator = { version = "0.5.0", package = "tikv-jemallocator", optional = true } +jemallocator = { version = "0.5.4", package = "tikv-jemallocator", optional = true } [dev-dependencies] -expect-test = "1.4.0" +expect-test = "1.5.1" xshell.workspace = true test-utils.workspace = true diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs index a09d96d16296b..9b1463b1126bf 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs @@ -258,7 +258,7 @@ pub(crate) fn fetch_native_diagnostics( for (file_id, group) in odd_ones .into_iter() .sorted_by_key(|it| it.range.file_id) - .group_by(|it| it.range.file_id) + .chunk_by(|it| it.range.file_id) .into_iter() { if !subscriptions.contains(&file_id) { diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml index f6a5dedfda2c2..76033308fe58b 100644 --- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml +++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -backtrace = { version = "0.3.67", optional = true } +backtrace = { version = "0.3.74", optional = true } jod-thread = "0.1.2" crossbeam-channel.workspace = true itertools.workspace = true diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 7db1a4e4ba103..2e902086367b1 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -27,8 +27,8 @@ stdx.workspace = true [dev-dependencies] rayon.workspace = true -expect-test = "1.4.0" -rustc_apfloat = "0.2.0" +expect-test = "1.5.1" +rustc_apfloat = "0.2.2" test-utils.workspace = true diff --git a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml index f25512b2b7e12..c27e850ce7feb 100644 --- a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml +++ b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml @@ -13,7 +13,7 @@ rust-version.workspace = true [dependencies] # Avoid adding deps here, this crate is widely used in tests it should compile fast! -dissimilar = "1.0.7" +dissimilar = "1.0.10" text-size.workspace = true rustc-hash.workspace = true diff --git a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml index 38daacdf951a7..315a3a2890f19 100644 --- a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml +++ b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -home = "0.5.4" +home = "0.5.11" camino.workspace = true [lints] diff --git a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml index 48b4d22de2f0b..9b32ee17abcf3 100644 --- a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml +++ b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml @@ -13,7 +13,7 @@ rust-version.workspace = true [dependencies] tracing.workspace = true -walkdir = "2.3.2" +walkdir = "2.5.0" crossbeam-channel.workspace = true notify = "8.0.0" rayon = "1.10.0" diff --git a/src/tools/rust-analyzer/lib/line-index/Cargo.toml b/src/tools/rust-analyzer/lib/line-index/Cargo.toml index f15c2e39372da..81cd364cc22b0 100644 --- a/src/tools/rust-analyzer/lib/line-index/Cargo.toml +++ b/src/tools/rust-analyzer/lib/line-index/Cargo.toml @@ -11,7 +11,7 @@ text-size = "1.1.1" nohash-hasher = "0.2.0" [dev-dependencies] -oorandom = "11.1.3" +oorandom = "11.1.5" [lints] workspace = true diff --git a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml index 39b931561bda8..1dc6d3ce5db8f 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml +++ b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml @@ -7,15 +7,15 @@ repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-ser edition = "2024" [dependencies] -log = "0.4.17" -serde_json = "1.0.108" -serde = { version = "1.0.216" } -serde_derive = { version = "1.0.216" } +log = "0.4.26" +serde_json = "1.0.140" +serde = { version = "1.0.219" } +serde_derive = { version = "1.0.219" } crossbeam-channel.workspace = true [dev-dependencies] lsp-types = "=0.95" -ctrlc = "3.4.1" +ctrlc = "3.4.5" [lints] workspace = true diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml index 01a561dcb9f38..41c38edc0678b 100644 --- a/src/tools/rust-analyzer/xtask/Cargo.toml +++ b/src/tools/rust-analyzer/xtask/Cargo.toml @@ -8,16 +8,16 @@ rust-version.workspace = true [dependencies] anyhow.workspace = true -directories = "5.0" -flate2 = "1.0.24" -write-json = "0.1.2" +directories = "6.0" +flate2 = "1.1.0" +write-json = "0.1.4" xshell.workspace = true -xflags = "0.3.0" +xflags = "0.3.2" time = { version = "0.3", default-features = false } -zip = { version = "0.6", default-features = false, features = ["deflate", "time"] } +zip = { version = "2.4", default-features = false, features = ["deflate", "time"] } stdx.workspace = true -proc-macro2 = "1.0.93" -quote = "1.0.20" +proc-macro2 = "1.0.94" +quote = "1.0.40" ungrammar = "1.16.1" either.workspace = true itertools.workspace = true diff --git a/src/tools/rust-analyzer/xtask/src/dist.rs b/src/tools/rust-analyzer/xtask/src/dist.rs index b43639242d0db..35ae7965f330b 100644 --- a/src/tools/rust-analyzer/xtask/src/dist.rs +++ b/src/tools/rust-analyzer/xtask/src/dist.rs @@ -8,7 +8,7 @@ use std::{ use flate2::{Compression, write::GzEncoder}; use time::OffsetDateTime; use xshell::{Shell, cmd}; -use zip::{DateTime, ZipWriter, write::FileOptions}; +use zip::{DateTime, ZipWriter, write::SimpleFileOptions}; use crate::{ date_iso, @@ -125,7 +125,7 @@ fn zip(src_path: &Path, symbols_path: Option<&PathBuf>, dest_path: &Path) -> any let mut writer = ZipWriter::new(BufWriter::new(file)); writer.start_file( src_path.file_name().unwrap().to_str().unwrap(), - FileOptions::default() + SimpleFileOptions::default() .last_modified_time( DateTime::try_from(OffsetDateTime::from(std::fs::metadata(src_path)?.modified()?)) .unwrap(), @@ -139,7 +139,7 @@ fn zip(src_path: &Path, symbols_path: Option<&PathBuf>, dest_path: &Path) -> any if let Some(symbols_path) = symbols_path { writer.start_file( symbols_path.file_name().unwrap().to_str().unwrap(), - FileOptions::default() + SimpleFileOptions::default() .last_modified_time( DateTime::try_from(OffsetDateTime::from( std::fs::metadata(src_path)?.modified()?, From 63e7815390c420c16e1dde7efa919cc15e15afec Mon Sep 17 00:00:00 2001 From: alexey semenyuk Date: Mon, 10 Mar 2025 15:11:29 +0500 Subject: [PATCH 0238/2248] Fix example for unconditional_recursion --- clippy_lints/src/unconditional_recursion.rs | 28 ++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs index a443043bef902..392a9c18a5f37 100644 --- a/clippy_lints/src/unconditional_recursion.rs +++ b/clippy_lints/src/unconditional_recursion.rs @@ -23,8 +23,8 @@ declare_clippy_lint! { /// implementations. /// /// ### Why is this bad? - /// This is a hard to find infinite recursion that will crash any code - /// using it. + /// Infinite recursion in trait implementation will either cause crashes + /// or result in an infinite loop, and it is hard to detect. /// /// ### Example /// ```no_run @@ -39,9 +39,31 @@ declare_clippy_lint! { /// } /// } /// ``` + /// /// Use instead: /// - /// In such cases, either use `#[derive(PartialEq)]` or don't implement it. + /// ```no_run + /// #[derive(PartialEq)] + /// enum Foo { + /// A, + /// B, + /// } + /// ``` + /// + /// As an alternative, rewrite the logic without recursion: + /// + /// ```no_run + /// enum Foo { + /// A, + /// B, + /// } + /// + /// impl PartialEq for Foo { + /// fn eq(&self, other: &Self) -> bool { + /// matches!((self, other), (Foo::A, Foo::A) | (Foo::B, Foo::B)) + /// } + /// } + /// ``` #[clippy::version = "1.77.0"] pub UNCONDITIONAL_RECURSION, suspicious, From 6fc2b1db368e693bbea563a83b62c8bd2122dc7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sun, 23 Mar 2025 13:44:52 +0200 Subject: [PATCH 0239/2248] Use zip/deflate-flate2 to avoid BSL-1.0 dep --- src/tools/rust-analyzer/Cargo.lock | 33 ------------------------ src/tools/rust-analyzer/xtask/Cargo.toml | 2 +- 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 4a01a658576b7..5fb6cff0e26e0 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -129,12 +129,6 @@ dependencies = [ "loom", ] -[[package]] -name = "bumpalo" -version = "3.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - [[package]] name = "camino" version = "1.1.9" @@ -1219,12 +1213,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "lockfree-object-pool" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" - [[package]] name = "log" version = "0.4.26" @@ -2196,12 +2184,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - [[package]] name = "smallvec" version = "1.14.0" @@ -3252,19 +3234,4 @@ dependencies = [ "memchr", "thiserror 2.0.12", "time", - "zopfli", -] - -[[package]] -name = "zopfli" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" -dependencies = [ - "bumpalo", - "crc32fast", - "lockfree-object-pool", - "log", - "once_cell", - "simd-adler32", ] diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml index 41c38edc0678b..6195de5d20255 100644 --- a/src/tools/rust-analyzer/xtask/Cargo.toml +++ b/src/tools/rust-analyzer/xtask/Cargo.toml @@ -14,7 +14,7 @@ write-json = "0.1.4" xshell.workspace = true xflags = "0.3.2" time = { version = "0.3", default-features = false } -zip = { version = "2.4", default-features = false, features = ["deflate", "time"] } +zip = { version = "2.4", default-features = false, features = ["deflate-flate2", "flate2", "time"] } stdx.workspace = true proc-macro2 = "1.0.94" quote = "1.0.40" From d8dff61275fba20d8440a8373f062b3809fc2dcd Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Fri, 21 Mar 2025 23:53:40 +0900 Subject: [PATCH 0240/2248] set concurrency for the `deploy` job --- .github/workflows/deploy.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b42f3e7712f10..ede19c11257ee 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -8,6 +8,10 @@ on: tags: - rust-1.** +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false + env: TARGET_BRANCH: 'gh-pages' SHA: '${{ github.sha }}' From 3786c07463bc777b310de71adef9d3e75196ea09 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Sun, 23 Mar 2025 21:09:28 +0900 Subject: [PATCH 0241/2248] remove the notation of the `deploy` job --- book/src/development/infrastructure/release.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/book/src/development/infrastructure/release.md b/book/src/development/infrastructure/release.md index 8b080c099b81c..a429e0d953c46 100644 --- a/book/src/development/infrastructure/release.md +++ b/book/src/development/infrastructure/release.md @@ -88,9 +88,6 @@ git push upstream stable After updating the `stable` branch, tag the HEAD commit and push it to the Clippy repo. -> Note: Only push the tag once the Deploy GitHub action of the `beta` branch is -> finished. Otherwise the deploy for the tag might fail. - ```bash git tag rust-1.XX.0 # XX should be exchanged with the corresponding version git push upstream rust-1.XX.0 # `upstream` is the `rust-lang/rust-clippy` remote From 762c01eb24c7bda831afb4bdd095b224e39ef515 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Mon, 24 Mar 2025 02:34:24 +0900 Subject: [PATCH 0242/2248] fix: Yet another false positive invalid cast diagnostic --- .../crates/hir-ty/src/infer/cast.rs | 19 ++-- .../crates/hir-ty/src/infer/unify.rs | 95 ++++++++++++++++--- .../src/handlers/invalid_cast.rs | 46 ++++++++- 3 files changed, 134 insertions(+), 26 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs index d3de86f038721..0670a4ec3df11 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs @@ -50,7 +50,7 @@ impl CastTy { None } } - TyKind::Raw(m, ty) => Some(Self::Ptr(table.resolve_ty_shallow(ty), *m)), + TyKind::Raw(m, ty) => Some(Self::Ptr(ty.clone(), *m)), TyKind::Function(_) => Some(Self::FnPtr), _ => None, } @@ -105,9 +105,8 @@ impl CastCheck { F: FnMut(ExprId, Vec), G: FnMut(ExprId), { - table.resolve_obligations_as_possible(); - self.expr_ty = table.resolve_ty_shallow(&self.expr_ty); - self.cast_ty = table.resolve_ty_shallow(&self.cast_ty); + self.expr_ty = table.eagerly_normalize_and_resolve_shallow_in(self.expr_ty.clone()); + self.cast_ty = table.eagerly_normalize_and_resolve_shallow_in(self.cast_ty.clone()); if self.expr_ty.contains_unknown() || self.cast_ty.contains_unknown() { return Ok(()); @@ -153,7 +152,7 @@ impl CastCheck { (None, Some(t_cast)) => match self.expr_ty.kind(Interner) { TyKind::FnDef(..) => { let sig = self.expr_ty.callable_sig(table.db).expect("FnDef had no sig"); - let sig = table.normalize_associated_types_in(sig); + let sig = table.eagerly_normalize_and_resolve_shallow_in(sig); let fn_ptr = TyKind::Function(sig.to_fn_ptr()).intern(Interner); if let Ok((adj, _)) = table.coerce(&self.expr_ty, &fn_ptr, CoerceNever::Yes) { @@ -165,7 +164,6 @@ impl CastCheck { (CastTy::FnPtr, t_cast) } TyKind::Ref(mutbl, _, inner_ty) => { - let inner_ty = table.resolve_ty_shallow(inner_ty); return match t_cast { CastTy::Int(_) | CastTy::Float => match inner_ty.kind(Interner) { TyKind::Scalar( @@ -180,13 +178,13 @@ impl CastCheck { }, // array-ptr-cast CastTy::Ptr(t, m) => { - let t = table.resolve_ty_shallow(&t); + let t = table.eagerly_normalize_and_resolve_shallow_in(t); if !table.is_sized(&t) { return Err(CastError::IllegalCast); } self.check_ref_cast( table, - &inner_ty, + inner_ty, *mutbl, &t, m, @@ -359,7 +357,7 @@ impl CastCheck { } } -#[derive(PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq)] enum PointerKind { // thin pointer Thin, @@ -373,8 +371,7 @@ enum PointerKind { } fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result, ()> { - let ty = table.resolve_ty_shallow(ty); - let ty = table.normalize_associated_types_in(ty); + let ty = table.eagerly_normalize_and_resolve_shallow_in(ty.clone()); if table.is_sized(&ty) { return Ok(Some(PointerKind::Thin)); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 903097ee2f8f7..67796b96962a2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -364,6 +364,64 @@ impl<'a> InferenceTable<'a> { ) } + /// Works almost same as [`Self::normalize_associated_types_in`], but this also resolves shallow + /// the inference variables + pub(crate) fn eagerly_normalize_and_resolve_shallow_in(&mut self, ty: T) -> T + where + T: HasInterner + TypeFoldable, + { + fn eagerly_resolve_ty( + table: &mut InferenceTable<'_>, + ty: Ty, + mut tys: SmallVec<[Ty; N]>, + ) -> Ty { + if tys.contains(&ty) { + return ty; + } + tys.push(ty.clone()); + + match ty.kind(Interner) { + TyKind::Alias(AliasTy::Projection(proj_ty)) => { + let ty = table.normalize_projection_ty(proj_ty.clone()); + eagerly_resolve_ty(table, ty, tys) + } + TyKind::InferenceVar(..) => { + let ty = table.resolve_ty_shallow(&ty); + eagerly_resolve_ty(table, ty, tys) + } + _ => ty, + } + } + + fold_tys_and_consts( + ty, + |e, _| match e { + Either::Left(ty) => { + Either::Left(eagerly_resolve_ty::<8>(self, ty, SmallVec::new())) + } + Either::Right(c) => Either::Right(match &c.data(Interner).value { + chalk_ir::ConstValue::Concrete(cc) => match &cc.interned { + crate::ConstScalar::UnevaluatedConst(c_id, subst) => { + // FIXME: same as `normalize_associated_types_in` + if subst.len(Interner) == 0 { + if let Ok(eval) = self.db.const_eval(*c_id, subst.clone(), None) { + eval + } else { + unknown_const(c.data(Interner).ty.clone()) + } + } else { + unknown_const(c.data(Interner).ty.clone()) + } + } + _ => c, + }, + _ => c, + }), + }, + DebruijnIndex::INNERMOST, + ) + } + pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { let var = self.new_type_var(); let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; @@ -918,7 +976,26 @@ impl<'a> InferenceTable<'a> { /// Check if given type is `Sized` or not pub(crate) fn is_sized(&mut self, ty: &Ty) -> bool { + fn short_circuit_trivial_tys(ty: &Ty) -> Option { + match ty.kind(Interner) { + TyKind::Scalar(..) + | TyKind::Ref(..) + | TyKind::Raw(..) + | TyKind::Never + | TyKind::FnDef(..) + | TyKind::Array(..) + | TyKind::Function(..) => Some(true), + TyKind::Slice(..) | TyKind::Str | TyKind::Dyn(..) => Some(false), + _ => None, + } + } + let mut ty = ty.clone(); + ty = self.eagerly_normalize_and_resolve_shallow_in(ty); + if let Some(sized) = short_circuit_trivial_tys(&ty) { + return sized; + } + { let mut structs = SmallVec::<[_; 8]>::new(); // Must use a loop here and not recursion because otherwise users will conduct completely @@ -937,26 +1014,16 @@ impl<'a> InferenceTable<'a> { // Structs can have DST as its last field and such cases are not handled // as unsized by the chalk, so we do this manually. ty = last_field_ty; + ty = self.eagerly_normalize_and_resolve_shallow_in(ty); + if let Some(sized) = short_circuit_trivial_tys(&ty) { + return sized; + } } else { break; }; } } - // Early return for some obvious types - if matches!( - ty.kind(Interner), - TyKind::Scalar(..) - | TyKind::Ref(..) - | TyKind::Raw(..) - | TyKind::Never - | TyKind::FnDef(..) - | TyKind::Array(..) - | TyKind::Function(_) - ) { - return true; - } - let Some(sized) = self .db .lang_item(self.trait_env.krate, LangItem::Sized) diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs index 82cd1f2fde6db..b56255b1fde42 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs @@ -440,8 +440,9 @@ fn main() { q as *const [i32]; //^^^^^^^^^^^^^^^^^ error: cannot cast thin pointer `*const i32` to fat pointer `*const [i32]` + // FIXME: This should emit diagnostics but disabled to prevent many false positives let t: *mut (dyn Trait + 'static) = 0 as *mut _; - //^^^^^^^^^^^ error: cannot cast `usize` to a fat pointer `*mut _` + let mut fail: *const str = 0 as *const str; //^^^^^^^^^^^^^^^ error: cannot cast `usize` to a fat pointer `*const str` let mut fail2: *const str = 0isize as *const str; @@ -1161,6 +1162,49 @@ struct ZerocopyKnownLayoutMaybeUninit(<::Type as KnownLayout> fn test(ptr: *mut [u8]) -> *mut ZerocopyKnownLayoutMaybeUninit { ptr as *mut _ } +"#, + ); + } + + #[test] + fn regression_19431() { + check_diagnostics( + r#" +//- minicore: coerce_unsized +struct Dst([u8]); + +struct Struct { + body: Dst, +} + +trait Field { + type Type: ?Sized; +} + +impl Field for Struct { + type Type = Dst; +} + +trait KnownLayout { + type MaybeUninit: ?Sized; + type PointerMetadata; +} + +impl KnownLayout for [T] { + type MaybeUninit = [T]; + type PointerMetadata = usize; +} + +impl KnownLayout for Dst { + type MaybeUninit = Dst; + type PointerMetadata = <[u8] as KnownLayout>::PointerMetadata; +} + +struct ZerocopyKnownLayoutMaybeUninit(<::Type as KnownLayout>::MaybeUninit); + +fn test(ptr: *mut ZerocopyKnownLayoutMaybeUninit) -> *mut <::Type as KnownLayout>::MaybeUninit { + ptr as *mut _ +} "#, ); } From 6948343b9fd4855377fd68c93b9c027d525df590 Mon Sep 17 00:00:00 2001 From: Hadrien Eyraud Date: Thu, 9 Jan 2025 18:39:40 +0100 Subject: [PATCH 0243/2248] 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 0244/2248] 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 88b590bf4626df68b73fdb03840c7ce616ac5929 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Sat, 22 Feb 2025 19:33:39 -0500 Subject: [PATCH 0245/2248] `lint-inconsistent-...` -> `check-inconsistent-...` --- CHANGELOG.md | 2 +- book/src/lint_configuration.md | 54 +++++++++---------- clippy.toml | 2 +- clippy_config/src/conf.rs | 40 ++++++++------ .../src/inconsistent_struct_constructor.rs | 6 +-- .../clippy.toml | 2 +- .../toml_unknown_key/conf_unknown_key.stderr | 3 ++ 7 files changed, 59 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3caf78581c1c3..3e6f00e857f70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6347,6 +6347,7 @@ Released 2018-09-13 [`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types [`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish [`check-incompatible-msrv-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-incompatible-msrv-in-tests +[`check-inconsistent-struct-field-initializers`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-inconsistent-struct-field-initializers [`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items [`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold [`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros @@ -6364,7 +6365,6 @@ Released 2018-09-13 [`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability [`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold [`lint-commented-code`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-commented-code -[`lint-inconsistent-struct-field-initializers`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-inconsistent-struct-field-initializers [`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold [`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else [`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 36f3985fc0281..859b2827b329f 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -425,6 +425,33 @@ Whether to check MSRV compatibility in `#[test]` and `#[cfg(test)]` code. * [`incompatible_msrv`](https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv) +## `check-inconsistent-struct-field-initializers` +Whether to suggest reordering constructor fields when initializers are present. + +Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the +suggested code would compile, it can change semantics if the initializer expressions have side effects. The +following example [from rust-clippy#11846] shows how the suggestion can run into borrow check errors: + +```rust +struct MyStruct { + vector: Vec, + length: usize +} +fn main() { + let vector = vec![1,2,3]; + MyStruct { length: vector.len(), vector}; +} +``` + +[from rust-clippy#11846]: https://github.com/rust-lang/rust-clippy/issues/11846#issuecomment-1820747924 + +**Default Value:** `false` + +--- +**Affected lints:** +* [`inconsistent_struct_constructor`](https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor) + + ## `check-private-items` Whether to also run the listed lints on private items. @@ -624,33 +651,6 @@ that would be collapsed. * [`collapsible_if`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if) -## `lint-inconsistent-struct-field-initializers` -Whether to suggest reordering constructor fields when initializers are present. - -Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the -suggested code would compile, it can change semantics if the initializer expressions have side effects. The -following example [from rust-clippy#11846] shows how the suggestion can run into borrow check errors: - -```rust -struct MyStruct { - vector: Vec, - length: usize -} -fn main() { - let vector = vec![1,2,3]; - MyStruct { length: vector.len(), vector}; -} -``` - -[from rust-clippy#11846]: https://github.com/rust-lang/rust-clippy/issues/11846#issuecomment-1820747924 - -**Default Value:** `false` - ---- -**Affected lints:** -* [`inconsistent_struct_constructor`](https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor) - - ## `literal-representation-threshold` The lower bound for linting decimal literals diff --git a/clippy.toml b/clippy.toml index f4789c9d03035..7872933552b43 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1,6 +1,6 @@ avoid-breaking-exported-api = false -lint-inconsistent-struct-field-initializers = true +check-inconsistent-struct-field-initializers = true [[disallowed-methods]] path = "rustc_lint::context::LintContext::lint" diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index eeb462dedc974..929e9c679ea88 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -474,6 +474,26 @@ define_Conf! { /// Whether to check MSRV compatibility in `#[test]` and `#[cfg(test)]` code. #[lints(incompatible_msrv)] check_incompatible_msrv_in_tests: bool = false, + /// Whether to suggest reordering constructor fields when initializers are present. + /// + /// Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the + /// suggested code would compile, it can change semantics if the initializer expressions have side effects. The + /// following example [from rust-clippy#11846] shows how the suggestion can run into borrow check errors: + /// + /// ```rust + /// struct MyStruct { + /// vector: Vec, + /// length: usize + /// } + /// fn main() { + /// let vector = vec![1,2,3]; + /// MyStruct { length: vector.len(), vector}; + /// } + /// ``` + /// + /// [from rust-clippy#11846]: https://github.com/rust-lang/rust-clippy/issues/11846#issuecomment-1820747924 + #[lints(inconsistent_struct_constructor)] + check_inconsistent_struct_field_initializers: bool = false, /// Whether to also run the listed lints on private items. #[lints(missing_errors_doc, missing_panics_doc, missing_safety_doc, unnecessary_safety_doc)] check_private_items: bool = false, @@ -554,24 +574,10 @@ define_Conf! { #[lints(collapsible_if)] lint_commented_code: bool = false, /// Whether to suggest reordering constructor fields when initializers are present. + /// DEPRECATED CONFIGURATION: lint-inconsistent-struct-field-initializers /// - /// Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the - /// suggested code would compile, it can change semantics if the initializer expressions have side effects. The - /// following example [from rust-clippy#11846] shows how the suggestion can run into borrow check errors: - /// - /// ```rust - /// struct MyStruct { - /// vector: Vec, - /// length: usize - /// } - /// fn main() { - /// let vector = vec![1,2,3]; - /// MyStruct { length: vector.len(), vector}; - /// } - /// ``` - /// - /// [from rust-clippy#11846]: https://github.com/rust-lang/rust-clippy/issues/11846#issuecomment-1820747924 - #[lints(inconsistent_struct_constructor)] + /// Use the `check-inconsistent-struct-field-initializers` configuration instead. + #[conf_deprecated("Please use `check-inconsistent-struct-field-initializers` instead", check_inconsistent_struct_field_initializers)] lint_inconsistent_struct_field_initializers: bool = false, /// The lower bound for linting decimal literals #[lints(decimal_literal_representation)] diff --git a/clippy_lints/src/inconsistent_struct_constructor.rs b/clippy_lints/src/inconsistent_struct_constructor.rs index e1dd7872b9d48..e6129757e560f 100644 --- a/clippy_lints/src/inconsistent_struct_constructor.rs +++ b/clippy_lints/src/inconsistent_struct_constructor.rs @@ -65,13 +65,13 @@ declare_clippy_lint! { } pub struct InconsistentStructConstructor { - lint_inconsistent_struct_field_initializers: bool, + check_inconsistent_struct_field_initializers: bool, } impl InconsistentStructConstructor { pub fn new(conf: &'static Conf) -> Self { Self { - lint_inconsistent_struct_field_initializers: conf.lint_inconsistent_struct_field_initializers, + check_inconsistent_struct_field_initializers: conf.check_inconsistent_struct_field_initializers, } } } @@ -86,7 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor { let all_fields_are_shorthand = fields.iter().all(|f| f.is_shorthand); let applicability = if all_fields_are_shorthand { Applicability::MachineApplicable - } else if self.lint_inconsistent_struct_field_initializers { + } else if self.check_inconsistent_struct_field_initializers { Applicability::MaybeIncorrect } else { return; diff --git a/tests/ui-toml/toml_inconsistent_struct_constructor/clippy.toml b/tests/ui-toml/toml_inconsistent_struct_constructor/clippy.toml index f43c9d97e825d..3cb8523562a8f 100644 --- a/tests/ui-toml/toml_inconsistent_struct_constructor/clippy.toml +++ b/tests/ui-toml/toml_inconsistent_struct_constructor/clippy.toml @@ -1 +1 @@ -lint-inconsistent-struct-field-initializers = true +check-inconsistent-struct-field-initializers = true diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index de0eefc422e70..cd2c849909258 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -32,6 +32,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect blacklisted-names cargo-ignore-publish check-incompatible-msrv-in-tests + check-inconsistent-struct-field-initializers check-private-items cognitive-complexity-threshold cyclomatic-complexity-threshold @@ -126,6 +127,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect blacklisted-names cargo-ignore-publish check-incompatible-msrv-in-tests + check-inconsistent-struct-field-initializers check-private-items cognitive-complexity-threshold cyclomatic-complexity-threshold @@ -220,6 +222,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni blacklisted-names cargo-ignore-publish check-incompatible-msrv-in-tests + check-inconsistent-struct-field-initializers check-private-items cognitive-complexity-threshold cyclomatic-complexity-threshold From 969b5ad65c393ba1e7e8ca2e18d6030867ef42c3 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Sat, 22 Feb 2025 19:34:30 -0500 Subject: [PATCH 0246/2248] Don't suggests deprecated congurations --- clippy_config/src/conf.rs | 18 +++++++++++++++++- .../toml_unknown_key/conf_unknown_key.stderr | 9 --------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 929e9c679ea88..1b9ea464dc3c6 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -991,7 +991,23 @@ impl serde::de::Error for FieldError { // set and allows it. use fmt::Write; - let mut expected = expected.to_vec(); + let metadata = get_configuration_metadata(); + let deprecated = metadata + .iter() + .filter_map(|conf| { + if conf.deprecation_reason.is_some() { + Some(conf.name.as_str()) + } else { + None + } + }) + .collect::>(); + + let mut expected = expected + .iter() + .copied() + .filter(|name| !deprecated.contains(name)) + .collect::>(); expected.sort_unstable(); let (rows, column_widths) = calculate_dimensions(&expected); diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index cd2c849909258..f2eaa66a4ae41 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -29,13 +29,11 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect array-size-threshold avoid-breaking-exported-api await-holding-invalid-types - blacklisted-names cargo-ignore-publish check-incompatible-msrv-in-tests check-inconsistent-struct-field-initializers check-private-items cognitive-complexity-threshold - cyclomatic-complexity-threshold disallowed-macros disallowed-methods disallowed-names @@ -51,7 +49,6 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect ignore-interior-mutability large-error-threshold lint-commented-code - lint-inconsistent-struct-field-initializers literal-representation-threshold matches-for-let-else max-fn-params-bools @@ -124,13 +121,11 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect array-size-threshold avoid-breaking-exported-api await-holding-invalid-types - blacklisted-names cargo-ignore-publish check-incompatible-msrv-in-tests check-inconsistent-struct-field-initializers check-private-items cognitive-complexity-threshold - cyclomatic-complexity-threshold disallowed-macros disallowed-methods disallowed-names @@ -146,7 +141,6 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect ignore-interior-mutability large-error-threshold lint-commented-code - lint-inconsistent-struct-field-initializers literal-representation-threshold matches-for-let-else max-fn-params-bools @@ -219,13 +213,11 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni array-size-threshold avoid-breaking-exported-api await-holding-invalid-types - blacklisted-names cargo-ignore-publish check-incompatible-msrv-in-tests check-inconsistent-struct-field-initializers check-private-items cognitive-complexity-threshold - cyclomatic-complexity-threshold disallowed-macros disallowed-methods disallowed-names @@ -241,7 +233,6 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni ignore-interior-mutability large-error-threshold lint-commented-code - lint-inconsistent-struct-field-initializers literal-representation-threshold matches-for-let-else max-fn-params-bools From 5100bfd57a77c3cf635a88835a10a70801bc25cb Mon Sep 17 00:00:00 2001 From: Prajwal S N Date: Mon, 24 Mar 2025 01:07:35 +0530 Subject: [PATCH 0247/2248] fix(ide-assists): `let else` to `if let else` Signed-off-by: Prajwal S N --- .../src/handlers/replace_let_with_if_let.rs | 49 ++++++++++++++++--- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs index a2dcbf948d8de..fd17231a7b664 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs @@ -45,19 +45,31 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext<'_> let mut editor = builder.make_editor(let_stmt.syntax()); let make = SyntaxFactory::new(); let ty = ctx.sema.type_of_expr(&init); - let happy_variant = ty - .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.adjusted())) - .map(|it| it.happy_case()); - let pat = match happy_variant { - None => original_pat, - Some(var_name) => { - make.tuple_struct_pat(make.ident_path(var_name), [original_pat]).into() + let pat = if let_stmt.let_else().is_some() { + // Do not add the wrapper type that implements `Try`, + // since the statement already wraps the pattern. + original_pat + } else { + let happy_variant = ty + .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.adjusted())) + .map(|it| it.happy_case()); + match happy_variant { + None => original_pat, + Some(var_name) => { + make.tuple_struct_pat(make.ident_path(var_name), [original_pat]).into() + } } }; let block = make.block_expr([], None); block.indent(IndentLevel::from_node(let_stmt.syntax())); - let if_expr = make.expr_if(make.expr_let(pat, init).into(), block, None); + let if_expr = make.expr_if( + make.expr_let(pat, init).into(), + block, + let_stmt + .let_else() + .and_then(|let_else| let_else.block_expr().map(ast::ElseBranch::from)), + ); let if_stmt = make.expr_stmt(if_expr.into()); editor.replace(let_stmt.syntax(), if_stmt.syntax()); @@ -90,6 +102,27 @@ enum E { X(T), Y(T) } fn main() { if let x = E::X(92) { } +} + ", + ) + } + + #[test] + fn replace_let_else() { + check_assist( + replace_let_with_if_let, + r" +//- minicore: option +fn main() { + let a = Some(1); + $0let Some(_) = a else { unreachable!() }; +} + ", + r" +fn main() { + let a = Some(1); + if let Some(_) = a { + } else { unreachable!() } } ", ) From de3aa1d9b1e0d780b999b2e4fd5ded8fa1072a41 Mon Sep 17 00:00:00 2001 From: Aaron Ang Date: Thu, 20 Feb 2025 23:18:52 -0800 Subject: [PATCH 0248/2248] Add new lint `manual_dangling_ptr` --- CHANGELOG.md | 1 + clippy_lints/src/casts/manual_dangling_ptr.rs | 82 +++++++++++++++++++ clippy_lints/src/casts/mod.rs | 32 ++++++++ clippy_lints/src/declared_lints.rs | 1 + clippy_utils/src/msrvs.rs | 2 +- clippy_utils/src/paths.rs | 1 + tests/ui/manual_dangling_ptr.fixed | 44 ++++++++++ tests/ui/manual_dangling_ptr.rs | 44 ++++++++++ tests/ui/manual_dangling_ptr.stderr | 65 +++++++++++++++ 9 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/casts/manual_dangling_ptr.rs create mode 100644 tests/ui/manual_dangling_ptr.fixed create mode 100644 tests/ui/manual_dangling_ptr.rs create mode 100644 tests/ui/manual_dangling_ptr.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 3caf78581c1c3..77c397f04c6e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5790,6 +5790,7 @@ Released 2018-09-13 [`manual_c_str_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals [`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp [`manual_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_contains +[`manual_dangling_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_dangling_ptr [`manual_div_ceil`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil [`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter [`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map diff --git a/clippy_lints/src/casts/manual_dangling_ptr.rs b/clippy_lints/src/casts/manual_dangling_ptr.rs new file mode 100644 index 0000000000000..8ace27eca895e --- /dev/null +++ b/clippy_lints/src/casts/manual_dangling_ptr.rs @@ -0,0 +1,82 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::SpanRangeExt; +use clippy_utils::ty::is_normalizable; +use clippy_utils::{expr_or_init, match_def_path, path_def_id, paths, std_or_core}; +use rustc_ast::LitKind; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, Ty, TyKind}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::MANUAL_DANGLING_PTR; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>) { + if let TyKind::Ptr(ref ptr_ty) = to.kind { + let init_expr = expr_or_init(cx, from); + if is_expr_const_aligned(cx, init_expr, ptr_ty.ty) + && let Some(std_or_core) = std_or_core(cx) + { + let sugg_fn = match ptr_ty.mutbl { + Mutability::Not => "ptr::dangling", + Mutability::Mut => "ptr::dangling_mut", + }; + + let sugg = if let TyKind::Infer(()) = ptr_ty.ty.kind { + format!("{std_or_core}::{sugg_fn}()") + } else if let Some(mut_ty_snip) = ptr_ty.ty.span.get_source_text(cx) { + format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()") + } else { + return; + }; + + span_lint_and_sugg( + cx, + MANUAL_DANGLING_PTR, + expr.span, + "manual creation of a dangling pointer", + "use", + sugg, + Applicability::MachineApplicable, + ); + } + } +} + +// Checks if the given expression is a call to `align_of` whose generic argument matches the target +// type, or a positive constant literal that matches the target type's alignment. +fn is_expr_const_aligned(cx: &LateContext<'_>, expr: &Expr<'_>, to: &Ty<'_>) -> bool { + match expr.kind { + ExprKind::Call(fun, _) => is_align_of_call(cx, fun, to), + ExprKind::Lit(lit) => is_literal_aligned(cx, lit, to), + _ => false, + } +} + +fn is_align_of_call(cx: &LateContext<'_>, fun: &Expr<'_>, to: &Ty<'_>) -> bool { + if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind + && let Some(fun_id) = path_def_id(cx, fun) + && match_def_path(cx, fun_id, &paths::ALIGN_OF) + && let Some(args) = path.segments.last().and_then(|seg| seg.args) + && let [GenericArg::Type(generic_ty)] = args.args + { + let typeck = cx.typeck_results(); + return typeck.node_type(generic_ty.hir_id) == typeck.node_type(to.hir_id); + } + false +} + +fn is_literal_aligned(cx: &LateContext<'_>, lit: &Spanned, to: &Ty<'_>) -> bool { + let LitKind::Int(val, _) = lit.node else { return false }; + if val == 0 { + return false; + } + let to_mid_ty = cx.typeck_results().node_type(to.hir_id); + is_normalizable(cx, cx.param_env, to_mid_ty) + && cx + .tcx + .layout_of(cx.typing_env().as_query_input(to_mid_ty)) + .is_ok_and(|layout| { + let align = u128::from(layout.align.abi.bytes()); + u128::from(val) <= align + }) +} diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index dc2a1fa85bf5c..38352977bde64 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -17,6 +17,7 @@ mod char_lit_as_u8; mod fn_to_numeric_cast; mod fn_to_numeric_cast_any; mod fn_to_numeric_cast_with_truncation; +mod manual_dangling_ptr; mod ptr_as_ptr; mod ptr_cast_constness; mod ref_as_ptr; @@ -759,6 +760,32 @@ declare_clippy_lint! { "detects `as *mut _` and `as *const _` conversion" } +declare_clippy_lint! { + /// ### What it does + /// Checks for casts of small constant literals or `mem::align_of` results to raw pointers. + /// + /// ### Why is this bad? + /// This creates a dangling pointer and is better expressed as + /// {`std`, `core`}`::ptr::`{`dangling`, `dangling_mut`}. + /// + /// ### Example + /// ```no_run + /// let ptr = 4 as *const u32; + /// let aligned = std::mem::align_of::() as *const u32; + /// let mut_ptr: *mut i64 = 8 as *mut _; + /// ``` + /// Use instead: + /// ```no_run + /// let ptr = std::ptr::dangling::(); + /// let aligned = std::ptr::dangling::(); + /// let mut_ptr: *mut i64 = std::ptr::dangling_mut(); + /// ``` + #[clippy::version = "1.87.0"] + pub MANUAL_DANGLING_PTR, + style, + "casting small constant literals to pointers to create dangling pointers" +} + pub struct Casts { msrv: Msrv, } @@ -795,6 +822,7 @@ impl_lint_pass!(Casts => [ ZERO_PTR, REF_AS_PTR, AS_POINTER_UNDERSCORE, + MANUAL_DANGLING_PTR, ]); impl<'tcx> LateLintPass<'tcx> for Casts { @@ -823,6 +851,10 @@ impl<'tcx> LateLintPass<'tcx> for Casts { fn_to_numeric_cast_with_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to); zero_ptr::check(cx, expr, cast_from_expr, cast_to_hir); + if self.msrv.meets(cx, msrvs::MANUAL_DANGLING_PTR) { + manual_dangling_ptr::check(cx, expr, cast_from_expr, cast_to_hir); + } + if cast_to.is_numeric() { cast_possible_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to, cast_to_hir.span); if cast_from.is_numeric() { diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index a9b6b369c4c39..3bf7da43fce37 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -97,6 +97,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::casts::FN_TO_NUMERIC_CAST_INFO, crate::casts::FN_TO_NUMERIC_CAST_ANY_INFO, crate::casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION_INFO, + crate::casts::MANUAL_DANGLING_PTR_INFO, crate::casts::PTR_AS_PTR_INFO, crate::casts::PTR_CAST_CONSTNESS_INFO, crate::casts::REF_AS_PTR_INFO, diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 86f4f190b950a..ab60fefddb447 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -24,7 +24,7 @@ macro_rules! msrv_aliases { msrv_aliases! { 1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT } 1,85,0 { UINT_FLOAT_MIDPOINT } - 1,84,0 { CONST_OPTION_AS_SLICE } + 1,84,0 { CONST_OPTION_AS_SLICE, MANUAL_DANGLING_PTR } 1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY, CONST_MUT_REFS, CONST_UNWRAP } 1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP } 1,81,0 { LINT_REASONS_STABILIZATION, ERROR_IN_CORE, EXPLICIT_SELF_TYPE_ELISION } diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 51d06ad9b1aa5..a960a65ead2ff 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -30,6 +30,7 @@ pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"] pub const CHAR_IS_ASCII: [&str; 5] = ["core", "char", "methods", "", "is_ascii"]; pub const IO_ERROR_NEW: [&str; 5] = ["std", "io", "error", "Error", "new"]; pub const IO_ERRORKIND_OTHER: [&str; 5] = ["std", "io", "error", "ErrorKind", "Other"]; +pub const ALIGN_OF: [&str; 3] = ["core", "mem", "align_of"]; // Paths in clippy itself pub const MSRV_STACK: [&str; 3] = ["clippy_utils", "msrvs", "MsrvStack"]; diff --git a/tests/ui/manual_dangling_ptr.fixed b/tests/ui/manual_dangling_ptr.fixed new file mode 100644 index 0000000000000..b6afe7898906c --- /dev/null +++ b/tests/ui/manual_dangling_ptr.fixed @@ -0,0 +1,44 @@ +#![warn(clippy::manual_dangling_ptr)] +use std::mem; + +pub fn foo(_const: *const f32, _mut: *mut i32) {} + +fn main() { + let _: *const u8 = std::ptr::dangling(); + //~^ manual_dangling_ptr + let _ = std::ptr::dangling::(); + //~^ manual_dangling_ptr + let _ = std::ptr::dangling_mut::(); + //~^ manual_dangling_ptr + + let _ = std::ptr::dangling::(); + //~^ manual_dangling_ptr + let _ = std::ptr::dangling::(); + //~^ manual_dangling_ptr + let _ = std::ptr::dangling::(); + //~^ manual_dangling_ptr + + foo(std::ptr::dangling(), std::ptr::dangling_mut()); + //~^ manual_dangling_ptr + //~| manual_dangling_ptr +} + +fn should_not_lint() { + let _ = 0x10 as *mut i32; + let _ = mem::align_of::() as *const u8; + + foo(0 as _, 0 as _); +} + +#[clippy::msrv = "1.83"] +fn _msrv_1_83() { + // `{core, std}::ptr::dangling` was stabilized in 1.84. Do not lint this + foo(4 as *const _, 4 as *mut _); +} + +#[clippy::msrv = "1.84"] +fn _msrv_1_84() { + foo(std::ptr::dangling(), std::ptr::dangling_mut()); + //~^ manual_dangling_ptr + //~| manual_dangling_ptr +} diff --git a/tests/ui/manual_dangling_ptr.rs b/tests/ui/manual_dangling_ptr.rs new file mode 100644 index 0000000000000..581ad50113e28 --- /dev/null +++ b/tests/ui/manual_dangling_ptr.rs @@ -0,0 +1,44 @@ +#![warn(clippy::manual_dangling_ptr)] +use std::mem; + +pub fn foo(_const: *const f32, _mut: *mut i32) {} + +fn main() { + let _: *const u8 = 1 as *const _; + //~^ manual_dangling_ptr + let _ = 2 as *const u32; + //~^ manual_dangling_ptr + let _ = 4 as *mut f32; + //~^ manual_dangling_ptr + + let _ = mem::align_of::() as *const u8; + //~^ manual_dangling_ptr + let _ = mem::align_of::() as *const u32; + //~^ manual_dangling_ptr + let _ = mem::align_of::() as *const usize; + //~^ manual_dangling_ptr + + foo(4 as *const _, 4 as *mut _); + //~^ manual_dangling_ptr + //~| manual_dangling_ptr +} + +fn should_not_lint() { + let _ = 0x10 as *mut i32; + let _ = mem::align_of::() as *const u8; + + foo(0 as _, 0 as _); +} + +#[clippy::msrv = "1.83"] +fn _msrv_1_83() { + // `{core, std}::ptr::dangling` was stabilized in 1.84. Do not lint this + foo(4 as *const _, 4 as *mut _); +} + +#[clippy::msrv = "1.84"] +fn _msrv_1_84() { + foo(4 as *const _, 4 as *mut _); + //~^ manual_dangling_ptr + //~| manual_dangling_ptr +} diff --git a/tests/ui/manual_dangling_ptr.stderr b/tests/ui/manual_dangling_ptr.stderr new file mode 100644 index 0000000000000..e3bc9b16b0d93 --- /dev/null +++ b/tests/ui/manual_dangling_ptr.stderr @@ -0,0 +1,65 @@ +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:7:24 + | +LL | let _: *const u8 = 1 as *const _; + | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()` + | + = note: `-D clippy::manual-dangling-ptr` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_dangling_ptr)]` + +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:9:13 + | +LL | let _ = 2 as *const u32; + | ^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` + +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:11:13 + | +LL | let _ = 4 as *mut f32; + | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling_mut::()` + +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:14:13 + | +LL | let _ = mem::align_of::() as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` + +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:16:13 + | +LL | let _ = mem::align_of::() as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` + +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:18:13 + | +LL | let _ = mem::align_of::() as *const usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` + +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:21:9 + | +LL | foo(4 as *const _, 4 as *mut _); + | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()` + +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:21:24 + | +LL | foo(4 as *const _, 4 as *mut _); + | ^^^^^^^^^^^ help: use: `std::ptr::dangling_mut()` + +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:41:9 + | +LL | foo(4 as *const _, 4 as *mut _); + | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()` + +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:41:24 + | +LL | foo(4 as *const _, 4 as *mut _); + | ^^^^^^^^^^^ help: use: `std::ptr::dangling_mut()` + +error: aborting due to 10 previous errors + From 7b1f9d89be8d1f79c75ff667c006d346042e9128 Mon Sep 17 00:00:00 2001 From: Aaron Ang Date: Thu, 20 Feb 2025 23:19:47 -0800 Subject: [PATCH 0249/2248] Update tests files for `manual_dangling_ptr` lint --- tests/ui/transmute.rs | 2 +- tests/ui/transmute_null_to_fn.rs | 1 + tests/ui/transmute_null_to_fn.stderr | 12 ++++++------ tests/ui/transmuting_null.rs | 1 + tests/ui/transmuting_null.stderr | 6 +++--- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 3aecde398dc3f..1ec70db9c3c29 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -59,7 +59,7 @@ fn useless() { let _: *const usize = std::mem::transmute(5_isize); //~^ useless_transmute - let _ = 5_isize as *const usize; + let _ = std::ptr::dangling::(); let _: *const usize = std::mem::transmute(1 + 1usize); //~^ useless_transmute diff --git a/tests/ui/transmute_null_to_fn.rs b/tests/ui/transmute_null_to_fn.rs index e88f05bb662e2..4712374af934f 100644 --- a/tests/ui/transmute_null_to_fn.rs +++ b/tests/ui/transmute_null_to_fn.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] #![warn(clippy::transmute_null_to_fn)] #![allow(clippy::zero_ptr, clippy::missing_transmute_annotations)] +#![allow(clippy::manual_dangling_ptr)] // Easy to lint because these only span one line. fn one_liners() { diff --git a/tests/ui/transmute_null_to_fn.stderr b/tests/ui/transmute_null_to_fn.stderr index f7d80147445d8..b5b0d4ecc7c03 100644 --- a/tests/ui/transmute_null_to_fn.stderr +++ b/tests/ui/transmute_null_to_fn.stderr @@ -1,5 +1,5 @@ error: transmuting a known null pointer into a function pointer - --> tests/ui/transmute_null_to_fn.rs:8:23 + --> tests/ui/transmute_null_to_fn.rs:9:23 | LL | let _: fn() = std::mem::transmute(0 as *const ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior @@ -9,7 +9,7 @@ LL | let _: fn() = std::mem::transmute(0 as *const ()); = help: to override `-D warnings` add `#[allow(clippy::transmute_null_to_fn)]` error: transmuting a known null pointer into a function pointer - --> tests/ui/transmute_null_to_fn.rs:11:23 + --> tests/ui/transmute_null_to_fn.rs:12:23 | LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior @@ -17,7 +17,7 @@ LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>()); = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value error: transmuting a known null pointer into a function pointer - --> tests/ui/transmute_null_to_fn.rs:22:23 + --> tests/ui/transmute_null_to_fn.rs:23:23 | LL | let _: fn() = std::mem::transmute(ZPTR); | ^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior @@ -25,7 +25,7 @@ LL | let _: fn() = std::mem::transmute(ZPTR); = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value error: transmuting a known null pointer into a function pointer - --> tests/ui/transmute_null_to_fn.rs:32:23 + --> tests/ui/transmute_null_to_fn.rs:33:23 | LL | let _: fn() = std::mem::transmute(0 as *const u8 as *const ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior @@ -33,7 +33,7 @@ LL | let _: fn() = std::mem::transmute(0 as *const u8 as *const ()); = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value error: transmuting a known null pointer into a function pointer - --> tests/ui/transmute_null_to_fn.rs:35:23 + --> tests/ui/transmute_null_to_fn.rs:36:23 | LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior @@ -41,7 +41,7 @@ LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value error: transmuting a known null pointer into a function pointer - --> tests/ui/transmute_null_to_fn.rs:38:23 + --> tests/ui/transmute_null_to_fn.rs:39:23 | LL | let _: fn() = std::mem::transmute(ZPTR as *const u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior diff --git a/tests/ui/transmuting_null.rs b/tests/ui/transmuting_null.rs index bcd35bbd4e72a..f3eb5060cd0d3 100644 --- a/tests/ui/transmuting_null.rs +++ b/tests/ui/transmuting_null.rs @@ -3,6 +3,7 @@ #![allow(clippy::zero_ptr)] #![allow(clippy::transmute_ptr_to_ref)] #![allow(clippy::eq_op, clippy::missing_transmute_annotations)] +#![allow(clippy::manual_dangling_ptr)] // Easy to lint because these only span one line. fn one_liners() { diff --git a/tests/ui/transmuting_null.stderr b/tests/ui/transmuting_null.stderr index 84e6e374d5253..c68e4102e405b 100644 --- a/tests/ui/transmuting_null.stderr +++ b/tests/ui/transmuting_null.stderr @@ -1,5 +1,5 @@ error: transmuting a known null pointer into a reference - --> tests/ui/transmuting_null.rs:10:23 + --> tests/ui/transmuting_null.rs:11:23 | LL | let _: &u64 = std::mem::transmute(0 as *const u64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,13 +8,13 @@ LL | let _: &u64 = std::mem::transmute(0 as *const u64); = help: to override `-D warnings` add `#[allow(clippy::transmuting_null)]` error: transmuting a known null pointer into a reference - --> tests/ui/transmuting_null.rs:13:23 + --> tests/ui/transmuting_null.rs:14:23 | LL | let _: &u64 = std::mem::transmute(std::ptr::null::()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmuting a known null pointer into a reference - --> tests/ui/transmuting_null.rs:24:23 + --> tests/ui/transmuting_null.rs:25:23 | LL | let _: &u64 = std::mem::transmute(ZPTR); | ^^^^^^^^^^^^^^^^^^^^^^^^^ From 25900c2768b0b3e3d55a531c9aeb27edaccb92d1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 23 Mar 2025 22:21:41 +0100 Subject: [PATCH 0250/2248] Tweak integer to string conversion test a bit to be future-proof --- library/alloctests/tests/num.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloctests/tests/num.rs b/library/alloctests/tests/num.rs index c9c0cd09ff6ab..3c76e68c60640 100644 --- a/library/alloctests/tests/num.rs +++ b/library/alloctests/tests/num.rs @@ -3,9 +3,9 @@ use std::str::FromStr; fn assert_nb(value: Int) { let s = value.to_string(); - let s2 = format!("{}", value); + let s2 = format!("s: {}.", value); - assert_eq!(s, s2); + assert_eq!(format!("s: {s}."), s2); let Ok(ret) = Int::from_str(&s) else { panic!("failed to convert into to string"); }; From e89c84913690bad837b658ade502cb0af7df768b Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 17 Mar 2025 20:40:01 +0800 Subject: [PATCH 0251/2248] Clean up librustdoc::html::render to be better encapsulated Signed-off-by: xizheyin --- src/librustdoc/formats/cache.rs | 14 ++--- src/librustdoc/html/render/mod.rs | 93 ++++++++++++++++++++----------- 2 files changed, 68 insertions(+), 39 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 2648641e53e75..2a612fa9b8cda 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -574,20 +574,20 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It ); let aliases = item.attrs.get_doc_aliases(); let deprecation = item.deprecation(tcx); - let index_item = IndexItem { - ty: item.type_(), - defid: Some(defid), + let index_item = IndexItem::new( + item.type_(), + Some(defid), name, path, desc, - parent: parent_did, - parent_idx: None, - exact_path: None, + parent_did, + None, + None, impl_id, search_type, aliases, deprecation, - }; + ); cache.search_index.push(index_item); } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 2237e0f987bc5..b9a2e65b09076 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -13,6 +13,9 @@ //! is cloned per-thread and contains information about what is currently being //! rendered. //! +//! The main entry point to the rendering system is the implementation of +//! `FormatRenderer` on `Context`. +//! //! In order to speed up rendering (mostly because of markdown rendering), the //! rendering process has been parallelized. This parallelization is only //! exposed through the `crate` method on the context, and then also from the @@ -90,7 +93,7 @@ pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display { /// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// impl. #[derive(Copy, Clone, Debug)] -pub(crate) enum AssocItemRender<'a> { +enum AssocItemRender<'a> { All, DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool }, } @@ -98,7 +101,7 @@ pub(crate) enum AssocItemRender<'a> { /// For different handling of associated items from the Deref target of a type rather than the type /// itself. #[derive(Copy, Clone, PartialEq)] -pub(crate) enum RenderMode { +enum RenderMode { Normal, ForDeref { mut_: bool }, } @@ -110,23 +113,55 @@ pub(crate) enum RenderMode { /// by hand to a large JS file at the end of cache-creation. #[derive(Debug)] pub(crate) struct IndexItem { - pub(crate) ty: ItemType, - pub(crate) defid: Option, - pub(crate) name: Symbol, - pub(crate) path: String, - pub(crate) desc: String, - pub(crate) parent: Option, - pub(crate) parent_idx: Option, - pub(crate) exact_path: Option, - pub(crate) impl_id: Option, - pub(crate) search_type: Option, - pub(crate) aliases: Box<[Symbol]>, - pub(crate) deprecation: Option, + ty: ItemType, + defid: Option, + name: Symbol, + path: String, + desc: String, + parent: Option, + parent_idx: Option, + exact_path: Option, + impl_id: Option, + search_type: Option, + aliases: Box<[Symbol]>, + deprecation: Option, +} + +impl IndexItem { + pub fn new( + ty: ItemType, + defid: Option, + name: Symbol, + path: String, + desc: String, + parent: Option, + parent_idx: Option, + exact_path: Option, + impl_id: Option, + search_type: Option, + aliases: Box<[Symbol]>, + deprecation: Option, + ) -> Self { + Self { + ty, + defid, + name, + path, + desc, + parent, + parent_idx, + exact_path, + impl_id, + search_type, + aliases, + deprecation, + } + } } /// A type used for the search index. #[derive(Debug, Eq, PartialEq)] -pub(crate) struct RenderType { +struct RenderType { id: Option, generics: Option>, bindings: Option)>>, @@ -137,7 +172,7 @@ impl RenderType { // The contents of the lists are always integers in self-terminating hex // form, handled by `RenderTypeId::write_to_string`, so no commas are // needed to separate the items. - pub fn write_to_string(&self, string: &mut String) { + fn write_to_string(&self, string: &mut String) { fn write_optional_id(id: Option, string: &mut String) { // 0 is a sentinel, everything else is one-indexed match id { @@ -177,7 +212,7 @@ impl RenderType { } #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub(crate) enum RenderTypeId { +enum RenderTypeId { DefId(DefId), Primitive(clean::PrimitiveType), AssociatedType(Symbol), @@ -186,7 +221,7 @@ pub(crate) enum RenderTypeId { } impl RenderTypeId { - pub fn write_to_string(&self, string: &mut String) { + fn write_to_string(&self, string: &mut String) { let id: i32 = match &self { // 0 is a sentinel, everything else is one-indexed // concrete type @@ -209,7 +244,7 @@ pub(crate) struct IndexItemFunctionType { } impl IndexItemFunctionType { - pub fn write_to_string<'a>( + fn write_to_string<'a>( &'a self, string: &mut String, backref_queue: &mut VecDeque<&'a IndexItemFunctionType>, @@ -309,7 +344,7 @@ impl ItemEntry { } impl ItemEntry { - pub(crate) fn print(&self) -> impl fmt::Display { + fn print(&self) -> impl fmt::Display { fmt::from_fn(move |f| write!(f, "
{}", self.url, Escape(&self.name))) } } @@ -760,7 +795,7 @@ fn short_item_info( // Render the list of items inside one of the sections "Trait Implementations", // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). -pub(crate) fn render_impls( +fn render_impls( cx: &Context<'_>, mut w: impl Write, impls: &[&Impl], @@ -1201,7 +1236,7 @@ impl<'a> AssocItemLink<'a> { } } -pub fn write_section_heading( +fn write_section_heading( title: &str, id: &str, extra_class: Option<&str>, @@ -1226,7 +1261,7 @@ fn write_impl_section_heading(title: &str, id: &str) -> impl fmt::Display { write_section_heading(title, id, None, "") } -pub(crate) fn render_all_impls( +fn render_all_impls( mut w: impl Write, cx: &Context<'_>, containing_item: &clean::Item, @@ -1473,10 +1508,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> } } -pub(crate) fn notable_traits_button( - ty: &clean::Type, - cx: &Context<'_>, -) -> Option { +fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option { if ty.is_unit() { // Very common fast path. return None; @@ -1588,10 +1620,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { (format!("{:#}", ty.print(cx)), out) } -pub(crate) fn notable_traits_json<'a>( - tys: impl Iterator, - cx: &Context<'_>, -) -> String { +fn notable_traits_json<'a>(tys: impl Iterator, cx: &Context<'_>) -> String { let mut mp: Vec<(String, String)> = tys.map(|ty| notable_traits_decl(ty, cx)).collect(); mp.sort_by(|(name1, _html1), (name2, _html2)| name1.cmp(name2)); struct NotableTraitsMap(Vec<(String, String)>); @@ -2171,7 +2200,7 @@ fn render_rightside( }) } -pub(crate) fn render_impl_summary( +fn render_impl_summary( cx: &Context<'_>, i: &Impl, parent: &clean::Item, From c1f5597210675e4247bbf057a0c8255ef72eee8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 24 Mar 2025 08:28:52 +0200 Subject: [PATCH 0252/2248] Drop rustc_hashes dependency --- src/tools/rust-analyzer/Cargo.toml | 1 - src/tools/rust-analyzer/crates/hir-def/src/lib.rs | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 03ecc8f2741e3..416269a967800 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -85,7 +85,6 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } edition = { path = "./crates/edition", version = "0.0.0" } -ra-ap-rustc_hashes = { version = "0.100", default-features = false } ra-ap-rustc_lexer = { version = "0.100", default-features = false } ra-ap-rustc_parse_format = { version = "0.100", default-features = false } ra-ap-rustc_index = { version = "0.100", default-features = false } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index fad0b56f336bc..4601960c7efb2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -18,9 +18,6 @@ extern crate ra_ap_rustc_parse_format as rustc_parse_format; #[cfg(feature = "in-rust-tree")] extern crate rustc_abi; -#[cfg(feature = "in-rust-tree")] -extern crate rustc_hashes; - #[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_abi as rustc_abi; From e2b9aab8a35bf5cab12717487449b8bf7e4d184e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 24 Mar 2025 08:40:04 +0200 Subject: [PATCH 0253/2248] Add missing syn feature --- src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml index 116028b5ba6dd..e07406df1acf8 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml +++ b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml @@ -15,7 +15,7 @@ proc-macro = true [dependencies] proc-macro2 = "1.0" quote = "1.0" -syn = { version = "2.0", features = ["full", "extra-traits"] } +syn = { version = "2.0", features = ["full", "extra-traits", "visit-mut"] } [dev-dependencies] expect-test = "1.5.0" From 6b9625dc0a8d5d673dbfdbeb0ad778eca062265b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 22 Mar 2025 21:04:36 +0100 Subject: [PATCH 0254/2248] chore: Cleanup vscode extension output channels --- .../docs/book/src/contributing/README.md | 9 ++++++--- src/tools/rust-analyzer/editors/code/package.json | 5 ----- .../rust-analyzer/editors/code/src/config.ts | 1 - src/tools/rust-analyzer/editors/code/src/ctx.ts | 4 ++-- src/tools/rust-analyzer/editors/code/src/debug.ts | 15 ++++----------- .../rust-analyzer/editors/code/src/toolchain.ts | 7 +++---- src/tools/rust-analyzer/editors/code/src/util.ts | 2 +- 7 files changed, 16 insertions(+), 27 deletions(-) diff --git a/src/tools/rust-analyzer/docs/book/src/contributing/README.md b/src/tools/rust-analyzer/docs/book/src/contributing/README.md index 9e1cdb08893fc..05286b5429244 100644 --- a/src/tools/rust-analyzer/docs/book/src/contributing/README.md +++ b/src/tools/rust-analyzer/docs/book/src/contributing/README.md @@ -140,9 +140,10 @@ By default, log goes to stderr, but the stderr itself is processed by VS Code. `--log-file ` CLI argument allows logging to file. Setting the `RA_LOG_FILE=` environment variable will also log to file, it will also override `--log-file`. -To see stderr in the running VS Code instance, go to the "Output" tab of the panel and select `Rust Analyzer Client`. +To see the server stderr output in the running VS Code instance, go to the "Output" tab of the panel +and select `rust-analyzer Language Server`. This shows `eprintln!` as well. -Note that `stdout` is used for the actual protocol, so `println!` will break things. +Note that `stdout` is used by LSP messages, so using `println!`—or anything that writes to `stdout`—will break rust-analyzer! To log all communication between the server and the client, there are two choices: @@ -153,9 +154,11 @@ To log all communication between the server and the client, there are two choice ``` * You can log on the client side, by the `rust-analyzer: Toggle LSP Logs` command or enabling `"rust-analyzer.trace.server": "verbose"` workspace setting. - These logs are shown in a separate tab in the output and could be used with LSP inspector. + These logs are shown in a separate tab named `rust-analyzer LSP Trace` in the output and could be used with LSP inspector. Kudos to [@DJMcNab](https://github.com/DJMcNab) for setting this awesome infra up! +Finally there are the logs of the VSCode extension itself which go into the `rust-analyzer Extension` output tab. + There are also several VS Code commands which might be of interest: * `rust-analyzer: Status` shows some memory-usage statistics. diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 11732ddd3e638..55477b7115447 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -606,11 +606,6 @@ "/rustc/": "${env:USERPROFILE}/.rustup/toolchains//lib/rustlib/src/rust" } }, - "rust-analyzer.debug.openDebugPane": { - "markdownDescription": "Whether to open up the `Debug Panel` on debugging start.", - "type": "boolean", - "default": false - }, "rust-analyzer.debug.buildBeforeRestart": { "markdownDescription": "Whether to rebuild the project modules before debugging the same test again", "type": "boolean", diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts index 896b3c10cbf5d..9b8ac666ce0ee 100644 --- a/src/tools/rust-analyzer/editors/code/src/config.ts +++ b/src/tools/rust-analyzer/editors/code/src/config.ts @@ -323,7 +323,6 @@ export class Config { return { engine: this.get("debug.engine"), engineSettings: this.get("debug.engineSettings") ?? {}, - openDebugPane: this.get("debug.openDebugPane"), buildBeforeRestart: this.get("debug.buildBeforeRestart"), sourceFileMap: sourceFileMap, }; diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts index 37a2ee236915c..1149523622313 100644 --- a/src/tools/rust-analyzer/editors/code/src/ctx.ts +++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts @@ -190,11 +190,11 @@ export class Ctx implements RustAnalyzerExtensionApi { } if (!this.traceOutputChannel) { - this.traceOutputChannel = new LazyOutputChannel("Rust Analyzer Language Server Trace"); + this.traceOutputChannel = new LazyOutputChannel("rust-analyzer LSP Trace"); this.pushExtCleanup(this.traceOutputChannel); } if (!this.outputChannel) { - this.outputChannel = vscode.window.createOutputChannel("Rust Analyzer Language Server"); + this.outputChannel = vscode.window.createOutputChannel("rust-analyzer Language Server"); this.pushExtCleanup(this.outputChannel); } diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts index 72a9aabc04342..04211d77e779f 100644 --- a/src/tools/rust-analyzer/editors/code/src/debug.ts +++ b/src/tools/rust-analyzer/editors/code/src/debug.ts @@ -6,11 +6,9 @@ import type * as ra from "./lsp_ext"; import { Cargo } from "./toolchain"; import type { Ctx } from "./ctx"; import { createTaskFromRunnable, prepareEnv } from "./run"; -import { execute, isCargoRunnableArgs, unwrapUndefinable } from "./util"; +import { execute, isCargoRunnableArgs, unwrapUndefinable, log } from "./util"; import type { Config } from "./config"; -const debugOutput = vscode.window.createOutputChannel("Debug"); - // Here we want to keep track on everything that's currently running const activeDebugSessionIds: string[] = []; @@ -56,15 +54,14 @@ export async function startDebugSession(ctx: Ctx, runnable: ra.Runnable): Promis if (-1 !== index) { debugConfig = configurations[index]; message = " (from launch.json)"; - debugOutput.clear(); } else { debugConfig = await getDebugConfiguration(ctx.config, runnable); } if (!debugConfig) return false; - debugOutput.appendLine(`Launching debug configuration${message}:`); - debugOutput.appendLine(JSON.stringify(debugConfig, null, 2)); + log.debug(`Launching debug configuration${message}:`); + log.debug(JSON.stringify(debugConfig, null, 2)); return vscode.debug.startDebugging(undefined, debugConfig); } @@ -118,10 +115,6 @@ async function getDebugConfiguration( return; } - debugOutput.clear(); - if (config.debug.openDebugPane) { - debugOutput.show(true); - } // folder exists or RA is not active. const workspaceFolders = vscode.workspace.workspaceFolders!; @@ -321,7 +314,7 @@ async function getDebugExecutable( runnableArgs: ra.CargoRunnableArgs, env: Record, ): Promise { - const cargo = new Cargo(runnableArgs.workspaceRoot || ".", debugOutput, env); + const cargo = new Cargo(runnableArgs.workspaceRoot || ".", env); const executable = await cargo.executableFromArgs(runnableArgs); // if we are here, there were no compilation errors. diff --git a/src/tools/rust-analyzer/editors/code/src/toolchain.ts b/src/tools/rust-analyzer/editors/code/src/toolchain.ts index bb06144295314..a859ce6ff0070 100644 --- a/src/tools/rust-analyzer/editors/code/src/toolchain.ts +++ b/src/tools/rust-analyzer/editors/code/src/toolchain.ts @@ -37,7 +37,6 @@ interface CompilerMessage { export class Cargo { constructor( readonly rootFolder: string, - readonly output: vscode.OutputChannel, readonly env: Record, ) {} @@ -93,14 +92,14 @@ export class Cargo { }); } } else if (message.reason === "compiler-message") { - this.output.append(message.message.rendered); + log.info(message.message.rendered); } }, - (stderr) => this.output.append(stderr), + (stderr) => log.error(stderr), env, ); } catch (err) { - this.output.show(true); + log.error(`Cargo invocation has failed: ${err}`); throw new Error(`Cargo invocation has failed: ${err}`); } diff --git a/src/tools/rust-analyzer/editors/code/src/util.ts b/src/tools/rust-analyzer/editors/code/src/util.ts index 93c7bf8d73e7b..4b3a6970db514 100644 --- a/src/tools/rust-analyzer/editors/code/src/util.ts +++ b/src/tools/rust-analyzer/editors/code/src/util.ts @@ -18,7 +18,7 @@ export type Env = { }; class Log { - private readonly output = vscode.window.createOutputChannel("Rust Analyzer Client", { + private readonly output = vscode.window.createOutputChannel("rust-analyzer Extension", { log: true, }); From a41c4dcddd2dfb0b3feae037487af9f8dba10059 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 24 Mar 2025 07:22:16 +0100 Subject: [PATCH 0255/2248] fix: Fix closure return inlayhints using macro ranges --- .../crates/ide/src/inlay_hints/closure_ret.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs index 0014c8127de00..f9b21c672dc9e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs @@ -35,8 +35,9 @@ pub(super) fn hints( let param_list = closure.param_list()?; - let closure = sema.descend_node_into_attributes(closure).pop()?; - let ty = sema.type_of_expr(&ast::Expr::ClosureExpr(closure.clone()))?.adjusted(); + let resolve_parent = Some(closure.syntax().text_range()); + let descended_closure = sema.descend_node_into_attributes(closure.clone()).pop()?; + let ty = sema.type_of_expr(&ast::Expr::ClosureExpr(descended_closure.clone()))?.adjusted(); let callable = ty.as_callable(sema.db)?; let ty = callable.return_type(); if arrow.is_none() && ty.is_unit() { @@ -52,7 +53,7 @@ pub(super) fn hints( ty_to_text_edit( sema, config, - closure.syntax(), + descended_closure.syntax(), &ty, arrow .as_ref() @@ -70,7 +71,7 @@ pub(super) fn hints( let mut builder = TextEdit::builder(); let insert_pos = param_list.syntax().text_range().end(); - let rendered = match sema.scope(closure.syntax()).and_then(|scope| { + let rendered = match sema.scope(descended_closure.syntax()).and_then(|scope| { ty.display_source_code(scope.db, scope.module().into(), false).ok() }) { Some(rendered) => rendered, @@ -95,7 +96,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: false, pad_right: false, - resolve_parent: Some(closure.syntax().text_range()), + resolve_parent, }); Some(()) } From 962329fd9df44abb9dbf89223014a3b1ad50c300 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 24 Mar 2025 08:35:24 +0100 Subject: [PATCH 0256/2248] Rename `Sugg::maybe_par()` into `Sugg::maybe_paren()` "paren" is used throughout the Clippy codebase as an abbreviation for "parentheses". --- clippy_lints/src/assigning_clones.rs | 6 ++-- clippy_lints/src/bool_to_int_with_if.rs | 2 +- .../src/casts/cast_abs_to_unsigned.rs | 2 +- clippy_lints/src/casts/cast_lossless.rs | 2 +- .../src/casts/cast_possible_truncation.rs | 2 +- clippy_lints/src/casts/ptr_as_ptr.rs | 2 +- clippy_lints/src/casts/ptr_cast_constness.rs | 2 +- clippy_lints/src/comparison_chain.rs | 2 +- clippy_lints/src/floating_point_arithmetic.rs | 28 +++++++++---------- clippy_lints/src/format.rs | 2 +- clippy_lints/src/from_str_radix_10.rs | 2 +- clippy_lints/src/if_then_some_else_none.rs | 2 +- clippy_lints/src/implicit_saturating_sub.rs | 2 +- clippy_lints/src/instant_subtraction.rs | 2 +- clippy_lints/src/len_zero.rs | 4 +-- clippy_lints/src/loops/for_kv_map.rs | 2 +- clippy_lints/src/loops/manual_memcpy.rs | 14 ++++++++-- clippy_lints/src/loops/utils.rs | 6 ++-- clippy_lints/src/manual_assert.rs | 2 +- clippy_lints/src/manual_clamp.rs | 2 +- clippy_lints/src/manual_div_ceil.rs | 2 +- clippy_lints/src/manual_is_ascii_check.rs | 2 +- clippy_lints/src/manual_rotate.rs | 2 +- clippy_lints/src/manual_unwrap_or_default.rs | 2 +- clippy_lints/src/matches/manual_ok_err.rs | 2 +- clippy_lints/src/matches/manual_unwrap_or.rs | 2 +- .../src/matches/redundant_pattern_match.rs | 6 ++-- clippy_lints/src/mem_replace.rs | 4 +-- .../methods/from_iter_instead_of_collect.rs | 2 +- clippy_lints/src/methods/manual_str_repeat.rs | 2 +- .../map_with_unused_argument_over_ranges.rs | 2 +- .../src/methods/unnecessary_map_or.rs | 4 +-- clippy_lints/src/needless_bool.rs | 2 +- .../operators/float_equality_without_abs.rs | 2 +- .../src/operators/verbose_bit_mask.rs | 2 +- clippy_lints/src/option_if_let_else.rs | 2 +- clippy_lints/src/partialeq_to_none.rs | 2 +- clippy_lints/src/ptr.rs | 4 +-- clippy_lints/src/ranges.rs | 8 +++--- clippy_lints/src/redundant_closure_call.rs | 2 +- clippy_lints/src/swap.rs | 2 +- .../src/transmute/transmute_float_to_int.rs | 2 +- .../src/transmute/transmute_ptr_to_ptr.rs | 4 +-- .../src/transmute/transmute_ptr_to_ref.rs | 4 +-- clippy_lints/src/useless_conversion.rs | 2 +- clippy_utils/src/sugg.rs | 10 +++---- 46 files changed, 89 insertions(+), 79 deletions(-) diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index ab34af7c31745..bf376eea70dcd 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -243,7 +243,7 @@ fn build_sugg<'tcx>( // `lhs = self_expr.clone();` -> `lhs.clone_from(self_expr)` Sugg::hir_with_applicability(cx, lhs, "_", app) } - .maybe_par(); + .maybe_paren(); // Determine whether we need to reference the argument to clone_from(). let clone_receiver_type = cx.typeck_results().expr_ty(fn_arg); @@ -284,7 +284,7 @@ fn build_sugg<'tcx>( let rhs_sugg = if let ExprKind::Unary(hir::UnOp::Deref, ref_expr) = lhs.kind { // `*lhs = rhs.to_owned()` -> `rhs.clone_into(lhs)` // `*lhs = ToOwned::to_owned(rhs)` -> `ToOwned::clone_into(rhs, lhs)` - let sugg = Sugg::hir_with_applicability(cx, ref_expr, "_", app).maybe_par(); + let sugg = Sugg::hir_with_applicability(cx, ref_expr, "_", app).maybe_paren(); let inner_type = cx.typeck_results().expr_ty(ref_expr); // If after unwrapping the dereference, the type is not a mutable reference, we add &mut to make it // deref to a mutable reference. @@ -296,7 +296,7 @@ fn build_sugg<'tcx>( } else { // `lhs = rhs.to_owned()` -> `rhs.clone_into(&mut lhs)` // `lhs = ToOwned::to_owned(rhs)` -> `ToOwned::clone_into(rhs, &mut lhs)` - Sugg::hir_with_applicability(cx, lhs, "_", app).maybe_par().mut_addr() + Sugg::hir_with_applicability(cx, lhs, "_", app).maybe_paren().mut_addr() }; match call_kind { diff --git a/clippy_lints/src/bool_to_int_with_if.rs b/clippy_lints/src/bool_to_int_with_if.rs index 612712d16843c..876ceef8c32b8 100644 --- a/clippy_lints/src/bool_to_int_with_if.rs +++ b/clippy_lints/src/bool_to_int_with_if.rs @@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolToIntWithIf { s }; - let into_snippet = snippet.clone().maybe_par(); + let into_snippet = snippet.clone().maybe_paren(); let as_snippet = snippet.as_ty(ty); span_lint_and_then( diff --git a/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/clippy_lints/src/casts/cast_abs_to_unsigned.rs index 8b3529e84fc6e..164d3540253a0 100644 --- a/clippy_lints/src/casts/cast_abs_to_unsigned.rs +++ b/clippy_lints/src/casts/cast_abs_to_unsigned.rs @@ -36,7 +36,7 @@ pub(super) fn check( span, format!("casting the result of `{cast_from}::abs()` to {cast_to}"), "replace with", - format!("{}.unsigned_abs()", Sugg::hir(cx, receiver, "..").maybe_par()), + format!("{}.unsigned_abs()", Sugg::hir(cx, receiver, "..").maybe_paren()), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs index 3ae43732dc03f..0f066fae11844 100644 --- a/clippy_lints/src/casts/cast_lossless.rs +++ b/clippy_lints/src/casts/cast_lossless.rs @@ -42,7 +42,7 @@ pub(super) fn check( diag.span_suggestion_verbose( expr.span, "use `Into::into` instead", - format!("{}.into()", from_sugg.maybe_par()), + format!("{}.into()", from_sugg.maybe_paren()), applicability, ); }, diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index ca973f4bb1aae..b28ac8dc971da 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -185,7 +185,7 @@ fn offer_suggestion( ) { let cast_to_snip = snippet(cx, cast_to_span, ".."); let suggestion = if cast_to_snip == "_" { - format!("{}.try_into()", Sugg::hir(cx, cast_expr, "..").maybe_par()) + format!("{}.try_into()", Sugg::hir(cx, cast_expr, "..").maybe_paren()) } else { format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, "..")) }; diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs index d57e391b55d54..6f944914b8fd6 100644 --- a/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/clippy_lints/src/casts/ptr_as_ptr.rs @@ -81,7 +81,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Msrv) { ( "try `pointer::cast`, a safer alternative", - format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_par()), + format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_paren()), ) }; diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index cad9c1df273f0..18e32c5c8a167 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -65,7 +65,7 @@ pub(super) fn check<'tcx>( expr.span, "`as` casting between raw pointers while changing only its constness", format!("try `pointer::cast_{constness}`, a safer alternative"), - format!("{}.cast_{constness}()", sugg.maybe_par()), + format!("{}.cast_{constness}()", sugg.maybe_paren()), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index 0e7f01e44b049..9c3009a86cdc0 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -125,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain { let ExprKind::Binary(_, lhs, rhs) = conds[0].kind else { unreachable!(); }; - let lhs = Sugg::hir(cx, lhs, "..").maybe_par(); + let lhs = Sugg::hir(cx, lhs, "..").maybe_paren(); let rhs = Sugg::hir(cx, rhs, "..").addr(); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index daa199779e3cb..92b607c87d75f 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -154,7 +154,7 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su }; } - suggestion.maybe_par() + suggestion.maybe_paren() } fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { @@ -165,7 +165,7 @@ fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, ar expr.span, "logarithm for bases 2, 10 and e can be computed more accurately", "consider using", - format!("{}.{method}()", Sugg::hir(cx, receiver, "..").maybe_par()), + format!("{}.{method}()", Sugg::hir(cx, receiver, "..").maybe_paren()), Applicability::MachineApplicable, ); } @@ -254,13 +254,13 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: ( SUBOPTIMAL_FLOPS, "square-root of a number can be computed more efficiently and accurately", - format!("{}.sqrt()", Sugg::hir(cx, receiver, "..").maybe_par()), + format!("{}.sqrt()", Sugg::hir(cx, receiver, "..").maybe_paren()), ) } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { ( IMPRECISE_FLOPS, "cube-root of a number can be computed more accurately", - format!("{}.cbrt()", Sugg::hir(cx, receiver, "..").maybe_par()), + format!("{}.cbrt()", Sugg::hir(cx, receiver, "..").maybe_paren()), ) } else if let Some(exponent) = get_integer_from_float_constant(&value) { ( @@ -268,7 +268,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: "exponentiation with integer powers can be computed more efficiently", format!( "{}.powi({})", - Sugg::hir(cx, receiver, "..").maybe_par(), + Sugg::hir(cx, receiver, "..").maybe_paren(), numeric_literal::format(&exponent.to_string(), None, false) ), ) @@ -330,7 +330,7 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: "consider using", format!( "{}.mul_add({}, {})", - Sugg::hir(cx, receiver, "..").maybe_par(), + Sugg::hir(cx, receiver, "..").maybe_paren(), maybe_neg_sugg(receiver, expr.hir_id), maybe_neg_sugg(other_addend, other_addend.hir_id), ), @@ -371,7 +371,7 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option { { return Some(format!( "{}.hypot({})", - Sugg::hir(cx, lmul_lhs, "..").maybe_par(), + Sugg::hir(cx, lmul_lhs, "..").maybe_paren(), Sugg::hir(cx, rmul_lhs, "..") )); } @@ -403,7 +403,7 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option { { return Some(format!( "{}.hypot({})", - Sugg::hir(cx, largs_0, "..").maybe_par(), + Sugg::hir(cx, largs_0, "..").maybe_paren(), Sugg::hir(cx, rargs_0, "..") )); } @@ -449,7 +449,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { expr.span, "(e.pow(x) - 1) can be computed more accurately", "consider using", - format!("{}.exp_m1()", Sugg::hir(cx, self_arg, "..").maybe_par()), + format!("{}.exp_m1()", Sugg::hir(cx, self_arg, "..").maybe_paren()), Applicability::MachineApplicable, ); } @@ -591,11 +591,11 @@ fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) { { let positive_abs_sugg = ( "manual implementation of `abs` method", - format!("{}.abs()", Sugg::hir(cx, body, "..").maybe_par()), + format!("{}.abs()", Sugg::hir(cx, body, "..").maybe_paren()), ); let negative_abs_sugg = ( "manual implementation of negation of `abs` method", - format!("-{}.abs()", Sugg::hir(cx, body, "..").maybe_par()), + format!("-{}.abs()", Sugg::hir(cx, body, "..").maybe_paren()), ); let sugg = if is_testing_positive(cx, cond, body) { if if_expr_positive { @@ -672,7 +672,7 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) { "consider using", format!( "{}.log({})", - Sugg::hir(cx, largs_self, "..").maybe_par(), + Sugg::hir(cx, largs_self, "..").maybe_paren(), Sugg::hir(cx, rargs_self, ".."), ), Applicability::MachineApplicable, @@ -703,7 +703,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) && (F32(180_f32) == lvalue || F64(180_f64) == lvalue) { - let mut proposal = format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..").maybe_par()); + let mut proposal = format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..").maybe_paren()); if let ExprKind::Lit(literal) = mul_lhs.kind && let ast::LitKind::Float(ref value, float_type) = literal.node && float_type == ast::LitFloatType::Unsuffixed @@ -726,7 +726,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { } else if (F32(180_f32) == rvalue || F64(180_f64) == rvalue) && (F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue) { - let mut proposal = format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..").maybe_par()); + let mut proposal = format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..").maybe_paren()); if let ExprKind::Lit(literal) = mul_lhs.kind && let ast::LitKind::Float(ref value, float_type) = literal.node && float_type == ast::LitFloatType::Unsuffixed diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 5e3f6b6a13707..94e66769eb265 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { .into_owned() } else { let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "", &mut applicability); - format!("{}.to_string()", sugg.maybe_par()) + format!("{}.to_string()", sugg.maybe_paren()) }; span_useless_format(cx, call_site, sugg, applicability); } diff --git a/clippy_lints/src/from_str_radix_10.rs b/clippy_lints/src/from_str_radix_10.rs index 7361546153c27..25b087e8484f2 100644 --- a/clippy_lints/src/from_str_radix_10.rs +++ b/clippy_lints/src/from_str_radix_10.rs @@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 { }; let sugg = - Sugg::hir_with_applicability(cx, expr, "", &mut Applicability::MachineApplicable).maybe_par(); + Sugg::hir_with_applicability(cx, expr, "", &mut Applicability::MachineApplicable).maybe_paren(); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs index fbbd33efd02d6..9e94280fc0746 100644 --- a/clippy_lints/src/if_then_some_else_none.rs +++ b/clippy_lints/src/if_then_some_else_none.rs @@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone { |diag| { let mut app = Applicability::MachineApplicable; let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app) - .maybe_par() + .maybe_paren() .to_string(); let arg_snip = snippet_with_context(cx, then_arg.span, ctxt, "[body]", &mut app).0; let method_body = if let Some(first_stmt) = then_block.stmts.first() { diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index cbc3e2ccd5b87..068723cebbfa8 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -239,7 +239,7 @@ fn check_subtraction( // This part of the condition is voluntarily split from the one before to ensure that // if `snippet_opt` fails, it won't try the next conditions. if (!is_in_const_context(cx) || msrv.meets(cx, msrvs::SATURATING_SUB_CONST)) - && let Some(big_expr_sugg) = Sugg::hir_opt(cx, big_expr).map(Sugg::maybe_par) + && let Some(big_expr_sugg) = Sugg::hir_opt(cx, big_expr).map(Sugg::maybe_paren) && let Some(little_expr_sugg) = Sugg::hir_opt(cx, little_expr) { let sugg = format!( diff --git a/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs index 4ae1119ab3a27..91f65d0b79ca0 100644 --- a/clippy_lints/src/instant_subtraction.rs +++ b/clippy_lints/src/instant_subtraction.rs @@ -123,7 +123,7 @@ fn print_manual_instant_elapsed_sugg(cx: &LateContext<'_>, expr: &Expr<'_>, sugg expr.span, "manual implementation of `Instant::elapsed`", "try", - format!("{}.elapsed()", sugg.maybe_par()), + format!("{}.elapsed()", sugg.maybe_paren()), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 72e22ae59d8f4..15c44381debbe 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -180,7 +180,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { let mut applicability = Applicability::MachineApplicable; let lit1 = peel_ref_operators(cx, lt.init); - let lit_str = Sugg::hir_with_context(cx, lit1, lt.span.ctxt(), "_", &mut applicability).maybe_par(); + let lit_str = Sugg::hir_with_context(cx, lit1, lt.span.ctxt(), "_", &mut applicability).maybe_paren(); span_lint_and_sugg( cx, @@ -573,7 +573,7 @@ fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Ex let mut applicability = Applicability::MachineApplicable; let lit1 = peel_ref_operators(cx, lit1); - let lit_str = Sugg::hir_with_context(cx, lit1, span.ctxt(), "_", &mut applicability).maybe_par(); + let lit_str = Sugg::hir_with_context(cx, lit1, span.ctxt(), "_", &mut applicability).maybe_paren(); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/loops/for_kv_map.rs b/clippy_lints/src/loops/for_kv_map.rs index 185d834becafc..a3b8d725af93d 100644 --- a/clippy_lints/src/loops/for_kv_map.rs +++ b/clippy_lints/src/loops/for_kv_map.rs @@ -45,7 +45,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx "use the corresponding method", vec![ (pat_span, snippet(cx, new_pat_span, kind).into_owned()), - (arg_span, format!("{}.{kind}s{mutbl}()", map.maybe_par())), + (arg_span, format!("{}.{kind}s{mutbl}()", map.maybe_paren())), ], Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs index 701567a7d84e7..39af596878178 100644 --- a/clippy_lints/src/loops/manual_memcpy.rs +++ b/clippy_lints/src/loops/manual_memcpy.rs @@ -184,7 +184,12 @@ fn build_manual_memcpy_suggestion<'tcx>( { dst_base_str } else { - format!("{dst_base_str}[{}..{}]", dst_offset.maybe_par(), dst_limit.maybe_par()).into() + format!( + "{dst_base_str}[{}..{}]", + dst_offset.maybe_paren(), + dst_limit.maybe_paren() + ) + .into() }; let method_str = if is_copy(cx, elem_ty) { @@ -196,7 +201,12 @@ fn build_manual_memcpy_suggestion<'tcx>( let src = if is_array_length_equal_to_range(cx, start, end, src.base) { src_base_str } else { - format!("{src_base_str}[{}..{}]", src_offset.maybe_par(), src_limit.maybe_par()).into() + format!( + "{src_base_str}[{}..{}]", + src_offset.maybe_paren(), + src_limit.maybe_paren() + ) + .into() }; format!("{dst}.{method_str}(&{src});") diff --git a/clippy_lints/src/loops/utils.rs b/clippy_lints/src/loops/utils.rs index a5185d38e7c33..468c27b508bff 100644 --- a/clippy_lints/src/loops/utils.rs +++ b/clippy_lints/src/loops/utils.rs @@ -263,7 +263,7 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic if impls_iterator { format!( "{}", - sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_par() + sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_paren() ) } else { // (&x).into_iter() ==> x.iter() @@ -281,12 +281,12 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic }; format!( "{}.{method_name}()", - sugg::Sugg::hir_with_applicability(cx, caller, "_", applic_ref).maybe_par(), + sugg::Sugg::hir_with_applicability(cx, caller, "_", applic_ref).maybe_paren(), ) }, _ => format!( "{}.into_iter()", - sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_par() + sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_paren() ), } } diff --git a/clippy_lints/src/manual_assert.rs b/clippy_lints/src/manual_assert.rs index 83c16d4466d06..8378e15c581c6 100644 --- a/clippy_lints/src/manual_assert.rs +++ b/clippy_lints/src/manual_assert.rs @@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert { ExprKind::Unary(UnOp::Not, e) => (e, ""), _ => (cond, "!"), }; - let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par(); + let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_paren(); let semicolon = if is_parent_stmt(cx, expr.hir_id) { ";" } else { "" }; let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip}){semicolon}"); // we show to the user the suggestion without the comments, but when applying the fix, include the diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index 50c8331eebab4..02afe9f0997de 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -181,7 +181,7 @@ fn maybe_emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggest make_assignment, hir_with_ignore_attr, } = suggestion; - let input = Sugg::hir(cx, input, "..").maybe_par(); + let input = Sugg::hir(cx, input, "..").maybe_paren(); let min = Sugg::hir(cx, min, ".."); let max = Sugg::hir(cx, max, ".."); let semicolon = if make_assignment.is_some() { ";" } else { "" }; diff --git a/clippy_lints/src/manual_div_ceil.rs b/clippy_lints/src/manual_div_ceil.rs index 9944c4f880481..70db403e10396 100644 --- a/clippy_lints/src/manual_div_ceil.rs +++ b/clippy_lints/src/manual_div_ceil.rs @@ -167,7 +167,7 @@ fn build_suggestion( rhs: &Expr<'_>, applicability: &mut Applicability, ) { - let dividend_sugg = Sugg::hir_with_applicability(cx, lhs, "..", applicability).maybe_par(); + let dividend_sugg = Sugg::hir_with_applicability(cx, lhs, "..", applicability).maybe_paren(); let type_suffix = if cx.typeck_results().expr_ty(lhs).is_numeric() && matches!( lhs.kind, diff --git a/clippy_lints/src/manual_is_ascii_check.rs b/clippy_lints/src/manual_is_ascii_check.rs index faf01a276a131..8ab49bd2ea8ea 100644 --- a/clippy_lints/src/manual_is_ascii_check.rs +++ b/clippy_lints/src/manual_is_ascii_check.rs @@ -148,7 +148,7 @@ fn check_is_ascii( }; let default_snip = ".."; let mut app = Applicability::MachineApplicable; - let recv = Sugg::hir_with_context(cx, recv, span.ctxt(), default_snip, &mut app).maybe_par(); + let recv = Sugg::hir_with_context(cx, recv, span.ctxt(), default_snip, &mut app).maybe_paren(); let mut suggestion = vec![(span, format!("{recv}.{sugg}()"))]; if let Some((ty_span, ty)) = ty_sugg { suggestion.push((ty_span, format!("{recv}: {ty}"))); diff --git a/clippy_lints/src/manual_rotate.rs b/clippy_lints/src/manual_rotate.rs index 07537fc65c08c..06ee00c2cef3c 100644 --- a/clippy_lints/src/manual_rotate.rs +++ b/clippy_lints/src/manual_rotate.rs @@ -101,7 +101,7 @@ impl LateLintPass<'_> for ManualRotate { (r_shift_dir, r_amount) }; let mut applicability = Applicability::MachineApplicable; - let expr_sugg = sugg::Sugg::hir_with_applicability(cx, l_expr, "_", &mut applicability).maybe_par(); + let expr_sugg = sugg::Sugg::hir_with_applicability(cx, l_expr, "_", &mut applicability).maybe_paren(); span_lint_and_sugg( cx, MANUAL_ROTATE, diff --git a/clippy_lints/src/manual_unwrap_or_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs index 87d2faa225c52..1aa12e72a6d45 100644 --- a/clippy_lints/src/manual_unwrap_or_default.rs +++ b/clippy_lints/src/manual_unwrap_or_default.rs @@ -150,7 +150,7 @@ fn handle<'tcx>(cx: &LateContext<'tcx>, if_let_or_match: IfLetOrMatch<'tcx>, exp // We now check the `None` arm is calling a method equivalent to `Default::default`. && let body_none = peel_blocks(body_none) && is_default_equivalent(cx, body_none) - && let Some(receiver) = Sugg::hir_opt(cx, condition).map(Sugg::maybe_par) + && let Some(receiver) = Sugg::hir_opt(cx, condition).map(Sugg::maybe_paren) { // Machine applicable only if there are no comments present let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) { diff --git a/clippy_lints/src/matches/manual_ok_err.rs b/clippy_lints/src/matches/manual_ok_err.rs index 576e42a564c2b..02f69b34af1cd 100644 --- a/clippy_lints/src/matches/manual_ok_err.rs +++ b/clippy_lints/src/matches/manual_ok_err.rs @@ -132,7 +132,7 @@ fn apply_lint(cx: &LateContext<'_>, expr: &Expr<'_>, scrutinee: &Expr<'_>, is_ok } else { Applicability::MachineApplicable }; - let scrut = Sugg::hir_with_applicability(cx, scrutinee, "..", &mut app).maybe_par(); + let scrut = Sugg::hir_with_applicability(cx, scrutinee, "..", &mut app).maybe_paren(); let sugg = format!("{scrut}.{method}()"); // If the expression being expanded is the `if …` part of an `else if …`, it must be blockified. let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr) diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs index 2bf7ec8ab7dde..5394b7af8ff8e 100644 --- a/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/clippy_lints/src/matches/manual_unwrap_or.rs @@ -120,7 +120,7 @@ fn lint<'tcx>( let reindented_or_body = reindent_multiline(or_body_snippet, true, Some(indent)); let mut app = Applicability::MachineApplicable; - let suggestion = sugg::Sugg::hir_with_context(cx, scrutinee, expr.span.ctxt(), "..", &mut app).maybe_par(); + let suggestion = sugg::Sugg::hir_with_context(cx, scrutinee, expr.span.ctxt(), "..", &mut app).maybe_paren(); span_lint_and_sugg( cx, MANUAL_UNWRAP_OR, diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs index 722ea7042dd7f..c4d51a5946e37 100644 --- a/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/clippy_lints/src/matches/redundant_pattern_match.rs @@ -255,7 +255,7 @@ fn find_method_sugg_for_if_let<'tcx>( }; let sugg = Sugg::hir_with_context(cx, result_expr, ctxt, "_", &mut app) - .maybe_par() + .maybe_paren() .to_string(); diag.span_suggestion(span, "try", format!("{keyword} {sugg}.{good_method}"), app); @@ -279,7 +279,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op _ => op, }; let mut app = Applicability::MachineApplicable; - let receiver_sugg = Sugg::hir_with_applicability(cx, result_expr, "_", &mut app).maybe_par(); + let receiver_sugg = Sugg::hir_with_applicability(cx, result_expr, "_", &mut app).maybe_paren(); let mut sugg = format!("{receiver_sugg}.{good_method}"); if let Some(guard) = maybe_guard { @@ -303,7 +303,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op } let guard = Sugg::hir(cx, guard, ".."); - let _ = write!(sugg, " && {}", guard.maybe_par()); + let _ = write!(sugg, " && {}", guard.maybe_paren()); } span_lint_and_sugg( diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index a0919947b3fc7..982e0695d7795 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -145,7 +145,7 @@ fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &E "consider `Option::take()` instead", format!( "{}.take()", - Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "", &mut applicability).maybe_par() + Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "", &mut applicability).maybe_paren() ), applicability, ); @@ -178,7 +178,7 @@ fn check_replace_option_with_some( "consider `Option::replace()` instead", format!( "{}.replace({})", - Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "_", &mut applicability).maybe_par(), + Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "_", &mut applicability).maybe_paren(), snippet_with_applicability(cx, src_arg.span, "_", &mut applicability) ), applicability, diff --git a/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/clippy_lints/src/methods/from_iter_instead_of_collect.rs index f4840785584ef..1f26b44767b25 100644 --- a/clippy_lints/src/methods/from_iter_instead_of_collect.rs +++ b/clippy_lints/src/methods/from_iter_instead_of_collect.rs @@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp && implements_trait(cx, arg_ty, iter_id, &[]) { // `expr` implements `FromIterator` trait - let iter_expr = sugg::Sugg::hir(cx, &args[0], "..").maybe_par(); + let iter_expr = sugg::Sugg::hir(cx, &args[0], "..").maybe_paren(); let turbofish = extract_turbofish(cx, expr, ty); let sugg = format!("{iter_expr}.collect::<{turbofish}>()"); span_lint_and_sugg( diff --git a/clippy_lints/src/methods/manual_str_repeat.rs b/clippy_lints/src/methods/manual_str_repeat.rs index 098721dc046f8..8167e4f960534 100644 --- a/clippy_lints/src/methods/manual_str_repeat.rs +++ b/clippy_lints/src/methods/manual_str_repeat.rs @@ -77,7 +77,7 @@ pub(super) fn check( s @ Cow::Borrowed(_) => s, }, RepeatKind::String => Sugg::hir_with_context(cx, repeat_arg, ctxt, "..", &mut app) - .maybe_par() + .maybe_paren() .to_string() .into(), }; diff --git a/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs index 6cf0936c598fa..a2a522a60687d 100644 --- a/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs +++ b/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs @@ -41,7 +41,7 @@ fn extract_count_with_applicability( return Some(format!("{count}")); } let end_snippet = Sugg::hir_with_applicability(cx, end, "...", applicability) - .maybe_par() + .maybe_paren() .into_string(); if lower_bound == 0 { if range.limits == RangeLimits::Closed { diff --git a/clippy_lints/src/methods/unnecessary_map_or.rs b/clippy_lints/src/methods/unnecessary_map_or.rs index d7bd522ddab94..66f9654e99014 100644 --- a/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/clippy_lints/src/methods/unnecessary_map_or.rs @@ -109,8 +109,8 @@ pub(super) fn check<'a>( let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr) { match parent_expr.kind { - ExprKind::Binary(..) | ExprKind::Unary(..) | ExprKind::Cast(..) => binop.maybe_par(), - ExprKind::MethodCall(_, receiver, _, _) if receiver.hir_id == expr.hir_id => binop.maybe_par(), + ExprKind::Binary(..) | ExprKind::Unary(..) | ExprKind::Cast(..) => binop.maybe_paren(), + ExprKind::MethodCall(_, receiver, _, _) if receiver.hir_id == expr.hir_id => binop.maybe_paren(), _ => binop, } } else { diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 2eacd6875d6b4..0e648c5cb2bc5 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool { || is_receiver_of_method_call(cx, e) || is_as_argument(cx, e) { - snip = snip.maybe_par(); + snip = snip.maybe_paren(); } span_lint_and_sugg( diff --git a/clippy_lints/src/operators/float_equality_without_abs.rs b/clippy_lints/src/operators/float_equality_without_abs.rs index 74e0a6333db0f..047a5a0159cb0 100644 --- a/clippy_lints/src/operators/float_equality_without_abs.rs +++ b/clippy_lints/src/operators/float_equality_without_abs.rs @@ -50,7 +50,7 @@ pub(crate) fn check<'tcx>( // format the suggestion let suggestion = format!( "{}.abs()", - sugg::make_assoc(AssocOp::Binary(BinOpKind::Sub), &sug_l, &sug_r).maybe_par() + sugg::make_assoc(AssocOp::Binary(BinOpKind::Sub), &sug_l, &sug_r).maybe_paren() ); // spans the lint span_lint_and_then( diff --git a/clippy_lints/src/operators/verbose_bit_mask.rs b/clippy_lints/src/operators/verbose_bit_mask.rs index a6aba33e431a4..1477378914120 100644 --- a/clippy_lints/src/operators/verbose_bit_mask.rs +++ b/clippy_lints/src/operators/verbose_bit_mask.rs @@ -32,7 +32,7 @@ pub(super) fn check<'tcx>( e.span, "bit mask could be simplified with a call to `trailing_zeros`", |diag| { - let sugg = Sugg::hir(cx, left1, "...").maybe_par(); + let sugg = Sugg::hir(cx, left1, "...").maybe_paren(); diag.span_suggestion( e.span, "try", diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 6f302ea196217..f37f3a12d4e9c 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -106,7 +106,7 @@ struct OptionOccurrence { fn format_option_in_sugg(cond_sugg: Sugg<'_>, as_ref: bool, as_mut: bool) -> String { format!( "{}{}", - cond_sugg.maybe_par(), + cond_sugg.maybe_paren(), if as_mut { ".as_mut()" } else if as_ref { diff --git a/clippy_lints/src/partialeq_to_none.rs b/clippy_lints/src/partialeq_to_none.rs index 6d4216970cc4d..9b9024c810575 100644 --- a/clippy_lints/src/partialeq_to_none.rs +++ b/clippy_lints/src/partialeq_to_none.rs @@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialeqToNone { let sugg = format!( "{}.{}", sugg::Sugg::hir_with_applicability(cx, peel_ref_operators(cx, scrutinee), "..", &mut applicability) - .maybe_par(), + .maybe_paren(), if is_eq { "is_none()" } else { "is_some()" } ); diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 55f1ece05593f..597894fe98721 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -287,8 +287,8 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { is_null_path(cx, l), is_null_path(cx, r), ) { - (false, true, false) if let Some(sugg) = Sugg::hir_opt(cx, r) => sugg.maybe_par(), - (false, false, true) if let Some(sugg) = Sugg::hir_opt(cx, l) => sugg.maybe_par(), + (false, true, false) if let Some(sugg) = Sugg::hir_opt(cx, r) => sugg.maybe_paren(), + (false, false, true) if let Some(sugg) = Sugg::hir_opt(cx, l) => sugg.maybe_paren(), _ => return check_ptr_eq(cx, expr, op.node, l, r), }; diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index cc423eca74fbe..83c36d71a9c7f 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -361,8 +361,8 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) { span, "an inclusive range would be more readable", |diag| { - let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string()); - let end = Sugg::hir(cx, y, "y").maybe_par(); + let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_paren().to_string()); + let end = Sugg::hir(cx, y, "y").maybe_paren(); match span.with_source_text(cx, |src| src.starts_with('(') && src.ends_with(')')) { Some(true) => { diag.span_suggestion(span, "use", format!("({start}..={end})"), Applicability::MaybeIncorrect); @@ -398,8 +398,8 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) { expr.span, "an exclusive range would be more readable", |diag| { - let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string()); - let end = Sugg::hir(cx, y, "y").maybe_par(); + let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_paren().to_string()); + let end = Sugg::hir(cx, y, "y").maybe_paren(); diag.span_suggestion( expr.span, "use", diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index 1498a49a7a4a9..84597269a58fa 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -206,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { // avoid clippy::double_parens if !is_in_fn_call_arg { - hint = hint.maybe_par(); + hint = hint.maybe_paren(); } diag.span_suggestion(full_expr.span, "try doing something like", hint, applicability); diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 7176d533b6164..d1486c2c246e1 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -133,7 +133,7 @@ fn generate_swap_warning<'tcx>( applicability: &mut applicability, } .snippet_index_bindings(&[idx1, idx2, rhs1, rhs2]), - slice.maybe_par(), + slice.maybe_paren(), snippet_with_context(cx, idx1.span, ctxt, "..", &mut applicability).0, snippet_with_context(cx, idx2.span, ctxt, "..", &mut applicability).0, ), diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs index f2c757952af38..df2f681a16291 100644 --- a/clippy_lints/src/transmute/transmute_float_to_int.rs +++ b/clippy_lints/src/transmute/transmute_float_to_int.rs @@ -47,7 +47,7 @@ pub(super) fn check<'tcx>( } } - sugg = sugg::Sugg::NonParen(format!("{}.to_bits()", sugg.maybe_par()).into()); + sugg = sugg::Sugg::NonParen(format!("{}.to_bits()", sugg.maybe_paren()).into()); // cast the result of `to_bits` if `to_ty` is signed sugg = if let ty::Int(int_ty) = to_ty.kind() { diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index fcc763763bd2f..933e25fe98c65 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -33,7 +33,7 @@ pub(super) fn check<'tcx>( diag.span_suggestion_verbose( e.span, "use `pointer::cast` instead", - format!("{}.cast::<{to_pointee_ty}>()", arg.maybe_par()), + format!("{}.cast::<{to_pointee_ty}>()", arg.maybe_paren()), Applicability::MaybeIncorrect, ); } else if from_pointee_ty == to_pointee_ty @@ -48,7 +48,7 @@ pub(super) fn check<'tcx>( diag.span_suggestion_verbose( e.span, format!("use `pointer::{method}` instead"), - format!("{}.{method}()", arg.maybe_par()), + format!("{}.{method}()", arg.maybe_paren()), Applicability::MaybeIncorrect, ); } else { diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index 45ee83c78ab67..e58212fae15cf 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -38,7 +38,7 @@ pub(super) fn check<'tcx>( let sugg = if let Some(ty) = get_explicit_type(path) { let ty_snip = snippet_with_applicability(cx, ty.span, "..", &mut app); if msrv.meets(cx, msrvs::POINTER_CAST) { - format!("{deref}{}.cast::<{ty_snip}>()", arg.maybe_par()) + format!("{deref}{}.cast::<{ty_snip}>()", arg.maybe_paren()) } else if from_ptr_ty.has_erased_regions() { sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {ty_snip}"))).to_string() } else { @@ -47,7 +47,7 @@ pub(super) fn check<'tcx>( } else if *from_ptr_ty == *to_ref_ty { if from_ptr_ty.has_erased_regions() { if msrv.meets(cx, msrvs::POINTER_CAST) { - format!("{deref}{}.cast::<{to_ref_ty}>()", arg.maybe_par()) + format!("{deref}{}.cast::<{to_ref_ty}>()", arg.maybe_paren()) } else { sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {to_ref_ty}"))) .to_string() diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 57bb2fc27f145..972c1adbd40ae 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -356,7 +356,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { if cx.tcx.is_diagnostic_item(sym::from_fn, def_id) && same_type_and_consts(a, b) { let mut app = Applicability::MachineApplicable; - let sugg = Sugg::hir_with_context(cx, arg, e.span.ctxt(), "", &mut app).maybe_par(); + let sugg = Sugg::hir_with_context(cx, arg, e.span.ctxt(), "", &mut app).maybe_paren(); let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); span_lint_and_sugg( cx, diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 68a1de96a3515..1b35d86146d06 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -326,7 +326,7 @@ impl<'a> Sugg<'a> { /// `self` argument of a method call /// (e.g., to build `bar.foo()` or `(1 + 2).foo()`). #[must_use] - pub fn maybe_par(self) -> Self { + pub fn maybe_paren(self) -> Self { match self { Sugg::NonParen(..) => self, // `(x)` and `(x).y()` both don't need additional parens. @@ -494,7 +494,7 @@ impl Display for ParenHelper { /// operators have the same /// precedence. pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> { - Sugg::MaybeParen(format!("{op}{}", expr.maybe_par()).into()) + Sugg::MaybeParen(format!("{op}{}", expr.maybe_paren()).into()) } /// Builds the string for ` ` adding parenthesis when necessary. @@ -1009,12 +1009,12 @@ mod test { } #[test] - fn binop_maybe_par() { + fn binop_maybe_paren() { let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "1".into(), "1".into()); - assert_eq!("(1 + 1)", sugg.maybe_par().to_string()); + assert_eq!("(1 + 1)", sugg.maybe_paren().to_string()); let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "(1 + 1)".into(), "(1 + 1)".into()); - assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_par().to_string()); + assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_paren().to_string()); } #[test] fn not_op() { From de8b6beac8710f6391e1fe99f774ba99bb0f54ac Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 24 Mar 2025 10:40:03 +0200 Subject: [PATCH 0257/2248] 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 0258/2248] 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 78d456a647c73bfdf933b806080e6e1a06b37c06 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 14 Mar 2025 16:21:02 +0100 Subject: [PATCH 0259/2248] Make `borrow_as_ptr` flag implicit casts as well --- clippy_lints/src/casts/borrow_as_ptr.rs | 27 +++++++++++++++++-- clippy_lints/src/casts/mod.rs | 3 +++ clippy_lints/src/non_copy_const.rs | 2 +- tests/ui/borrow_as_ptr.fixed | 18 +++++++++++++ tests/ui/borrow_as_ptr.rs | 18 +++++++++++++ tests/ui/borrow_as_ptr.stderr | 35 ++++++++++++++++++++++++- 6 files changed, 99 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs index 0c9639f3ea617..ad0a4f8cdf35a 100644 --- a/clippy_lints/src/casts/borrow_as_ptr.rs +++ b/clippy_lints/src/casts/borrow_as_ptr.rs @@ -1,11 +1,12 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::msrvs::Msrv; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; -use clippy_utils::{is_expr_temporary_value, is_lint_allowed, msrvs, std_or_core}; +use clippy_utils::{get_parent_expr, is_expr_temporary_value, is_lint_allowed, msrvs, std_or_core}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind}; use rustc_lint::LateContext; +use rustc_middle::ty::adjustment::{Adjust, AutoBorrow}; use rustc_span::BytePos; use super::BORROW_AS_PTR; @@ -55,3 +56,25 @@ pub(super) fn check<'tcx>( } false } + +/// Check for an implicit cast from reference to raw pointer outside an explicit `as`. +pub(super) fn check_implicit_cast(cx: &LateContext<'_>, expr: &Expr<'_>) { + if !expr.span.from_expansion() + && let ExprKind::AddrOf(BorrowKind::Ref, _, pointee) = expr.kind + && !matches!(get_parent_expr(cx, expr).map(|e| e.kind), Some(ExprKind::Cast(..))) + && let [deref, borrow] = cx.typeck_results().expr_adjustments(expr) + && matches!(deref.kind, Adjust::Deref(..)) + && let Adjust::Borrow(AutoBorrow::RawPtr(mutability)) = borrow.kind + // Do not suggest taking a raw pointer to a temporary value + && !is_expr_temporary_value(cx, pointee) + { + span_lint_and_then(cx, BORROW_AS_PTR, expr.span, "implicit borrow as raw pointer", |diag| { + diag.span_suggestion_verbose( + expr.span.until(pointee.span), + "use a raw pointer instead", + format!("&raw {} ", mutability.ptr_str()), + Applicability::MachineApplicable, + ); + }); + } +} diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index dc2a1fa85bf5c..b56a4180e6c3a 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -846,6 +846,9 @@ impl<'tcx> LateLintPass<'tcx> for Casts { } } + if self.msrv.meets(cx, msrvs::RAW_REF_OP) { + borrow_as_ptr::check_implicit_cast(cx, expr); + } cast_ptr_alignment::check(cx, expr); char_lit_as_u8::check(cx, expr); ptr_as_ptr::check(cx, expr, self.msrv); diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index d4da12451f181..12efdaeb81e0e 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -449,7 +449,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { dereferenced_expr = parent_expr; }, - ExprKind::Index(e, _, _) if ptr::eq(&**e, cur_expr) => { + ExprKind::Index(e, _, _) if ptr::eq(&raw const **e, cur_expr) => { // `e[i]` => desugared to `*Index::index(&e, i)`, // meaning `e` must be referenced. // no need to go further up since a method call is involved now. diff --git a/tests/ui/borrow_as_ptr.fixed b/tests/ui/borrow_as_ptr.fixed index 3dca06fce4b8d..3ba2eea59f0b0 100644 --- a/tests/ui/borrow_as_ptr.fixed +++ b/tests/ui/borrow_as_ptr.fixed @@ -29,3 +29,21 @@ fn issue_13882() { let _raw = (&raw mut x[1]).wrapping_offset(-1); //~^ borrow_as_ptr } + +fn implicit_cast() { + let val = 1; + let p: *const i32 = &raw const val; + //~^ borrow_as_ptr + + let mut val = 1; + let p: *mut i32 = &raw mut val; + //~^ borrow_as_ptr + + let mut val = 1; + // Only lint the leftmost argument, the rightmost is ref to a temporary + core::ptr::eq(&raw const val, &1); + //~^ borrow_as_ptr + + // Do not lint references to temporaries + core::ptr::eq(&0i32, &1i32); +} diff --git a/tests/ui/borrow_as_ptr.rs b/tests/ui/borrow_as_ptr.rs index 3559dc23d0185..8cdd0512da5f7 100644 --- a/tests/ui/borrow_as_ptr.rs +++ b/tests/ui/borrow_as_ptr.rs @@ -29,3 +29,21 @@ fn issue_13882() { let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1); //~^ borrow_as_ptr } + +fn implicit_cast() { + let val = 1; + let p: *const i32 = &val; + //~^ borrow_as_ptr + + let mut val = 1; + let p: *mut i32 = &mut val; + //~^ borrow_as_ptr + + let mut val = 1; + // Only lint the leftmost argument, the rightmost is ref to a temporary + core::ptr::eq(&val, &1); + //~^ borrow_as_ptr + + // Do not lint references to temporaries + core::ptr::eq(&0i32, &1i32); +} diff --git a/tests/ui/borrow_as_ptr.stderr b/tests/ui/borrow_as_ptr.stderr index 4a9f2ed4aa003..b1fcce49403c8 100644 --- a/tests/ui/borrow_as_ptr.stderr +++ b/tests/ui/borrow_as_ptr.stderr @@ -25,5 +25,38 @@ error: borrow as raw pointer LL | let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `&raw mut x[1]` -error: aborting due to 4 previous errors +error: implicit borrow as raw pointer + --> tests/ui/borrow_as_ptr.rs:35:25 + | +LL | let p: *const i32 = &val; + | ^^^^ + | +help: use a raw pointer instead + | +LL | let p: *const i32 = &raw const val; + | +++++++++ + +error: implicit borrow as raw pointer + --> tests/ui/borrow_as_ptr.rs:39:23 + | +LL | let p: *mut i32 = &mut val; + | ^^^^^^^^ + | +help: use a raw pointer instead + | +LL | let p: *mut i32 = &raw mut val; + | +++ + +error: implicit borrow as raw pointer + --> tests/ui/borrow_as_ptr.rs:44:19 + | +LL | core::ptr::eq(&val, &1); + | ^^^^ + | +help: use a raw pointer instead + | +LL | core::ptr::eq(&raw const val, &1); + | +++++++++ + +error: aborting due to 7 previous errors From 2ae0973516d2ecab92b8442e48c8544f305848dd Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 24 Mar 2025 13:43:47 +0100 Subject: [PATCH 0260/2248] refactor: Replace custom `ThinVec` with `thin-vec` crate --- src/tools/rust-analyzer/Cargo.lock | 7 + .../rust-analyzer/crates/hir-def/Cargo.toml | 1 + .../crates/hir-def/src/generics.rs | 31 +- .../crates/hir-def/src/hir/type_ref.rs | 36 +- .../crates/hir-def/src/item_tree/lower.rs | 2 +- .../rust-analyzer/crates/hir-def/src/lower.rs | 2 +- .../rust-analyzer/crates/hir-def/src/path.rs | 52 +- .../crates/hir-def/src/path/lower.rs | 10 +- .../crates/hir-def/src/pretty.rs | 8 +- .../crates/hir-def/src/resolver.rs | 4 +- .../crates/hir-ty/src/display.rs | 10 +- .../crates/hir-ty/src/infer/expr.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/lower.rs | 8 +- .../rust-analyzer/crates/stdx/src/lib.rs | 1 - .../rust-analyzer/crates/stdx/src/thin_vec.rs | 468 ------------------ 15 files changed, 99 insertions(+), 543 deletions(-) delete mode 100644 src/tools/rust-analyzer/crates/stdx/src/thin_vec.rs diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 5fb6cff0e26e0..2c421451213d5 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -651,6 +651,7 @@ dependencies = [ "test-fixture", "test-utils", "text-size", + "thin-vec", "tracing", "triomphe", "tt", @@ -2330,6 +2331,12 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" +[[package]] +name = "thin-vec" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d" + [[package]] name = "thiserror" version = "1.0.69" diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml index 98d24d20b0cd2..f97597ffe5a6b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml @@ -43,6 +43,7 @@ mbe.workspace = true cfg.workspace = true tt.workspace = true span.workspace = true +thin-vec = "0.2.14" [dev-dependencies] expect-test.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs index ee026509a2cf4..58ac86e8a6050 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs @@ -12,11 +12,9 @@ use hir_expand::{ }; use intern::sym; use la_arena::{Arena, RawIdx}; -use stdx::{ - impl_from, - thin_vec::{EmptyOptimizedThinVec, ThinVec}, -}; +use stdx::impl_from; use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds}; +use thin_vec::ThinVec; use triomphe::Arc; use crate::{ @@ -753,12 +751,17 @@ fn copy_type_ref( ) -> TypeRefId { let result = match &from[type_ref] { TypeRef::Fn(fn_) => { - let params = fn_.params().iter().map(|(name, param_type)| { + let params = fn_.params.iter().map(|(name, param_type)| { (name.clone(), copy_type_ref(*param_type, from, from_source_map, to, to_source_map)) }); - TypeRef::Fn(FnType::new(fn_.is_varargs(), fn_.is_unsafe(), fn_.abi().clone(), params)) + TypeRef::Fn(Box::new(FnType { + params: params.collect(), + is_varargs: fn_.is_varargs, + is_unsafe: fn_.is_unsafe, + abi: fn_.abi.clone(), + })) } - TypeRef::Tuple(types) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter( + TypeRef::Tuple(types) => TypeRef::Tuple(ThinVec::from_iter( types.iter().map(|&t| copy_type_ref(t, from, from_source_map, to, to_source_map)), )), &TypeRef::RawPtr(type_ref, mutbl) => TypeRef::RawPtr( @@ -817,13 +820,17 @@ fn copy_path( Path::BarePath(mod_path) => Path::BarePath(mod_path.clone()), Path::Normal(path) => { let type_anchor = path - .type_anchor() + .type_anchor .map(|type_ref| copy_type_ref(type_ref, from, from_source_map, to, to_source_map)); - let mod_path = path.mod_path().clone(); - let generic_args = path.generic_args().iter().map(|generic_args| { + let mod_path = path.mod_path.clone(); + let generic_args = path.generic_args.iter().map(|generic_args| { copy_generic_args(generic_args, from, from_source_map, to, to_source_map) }); - Path::Normal(NormalPath::new(type_anchor, mod_path, generic_args)) + Path::Normal(Box::new(NormalPath { + generic_args: generic_args.collect(), + type_anchor, + mod_path, + })) } Path::LangItem(lang_item, name) => Path::LangItem(*lang_item, name.clone()), } @@ -879,7 +886,7 @@ fn copy_type_bounds<'a>( from_source_map: &'a TypesSourceMap, to: &'a mut TypesMap, to_source_map: &'a mut TypesSourceMap, -) -> impl stdx::thin_vec::TrustedLen + 'a { +) -> impl Iterator + 'a { bounds.iter().map(|bound| copy_type_bound(bound, from, from_source_map, to, to_source_map)) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs index 7bb558d34563e..fd50d2f009894 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs @@ -12,11 +12,11 @@ use hir_expand::{ use intern::{Symbol, sym}; use la_arena::{Arena, ArenaMap, Idx}; use span::Edition; -use stdx::thin_vec::{EmptyOptimizedThinVec, ThinVec, thin_vec_with_header_struct}; use syntax::{ AstPtr, ast::{self, HasGenericArgs, HasName, IsString}, }; +use thin_vec::ThinVec; use crate::{ SyntheticSyntax, @@ -120,13 +120,12 @@ impl TraitRef { } } -thin_vec_with_header_struct! { - pub new(pub(crate)) struct FnType, FnTypeHeader { - pub params: [(Option, TypeRefId)], - pub is_varargs: bool, - pub is_unsafe: bool, - pub abi: Option; ref, - } +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct FnType { + pub params: Box<[(Option, TypeRefId)]>, + pub is_varargs: bool, + pub is_unsafe: bool, + pub abi: Option, } #[derive(Clone, PartialEq, Eq, Hash, Debug)] @@ -148,14 +147,14 @@ pub struct RefType { pub enum TypeRef { Never, Placeholder, - Tuple(EmptyOptimizedThinVec), + Tuple(ThinVec), Path(Path), RawPtr(TypeRefId, Mutability), Reference(Box), Array(Box), Slice(TypeRefId), /// A fn pointer. Last element of the vector is the return type. - Fn(FnType), + Fn(Box), ImplTrait(ThinVec), DynTrait(ThinVec), Macro(AstId), @@ -273,9 +272,9 @@ impl TypeRef { pub fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> TypeRefId { let ty = match &node { ast::Type::ParenType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()), - ast::Type::TupleType(inner) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter( - Vec::from_iter(inner.fields().map(|it| TypeRef::from_ast(ctx, it))), - )), + ast::Type::TupleType(inner) => TypeRef::Tuple(ThinVec::from_iter(Vec::from_iter( + inner.fields().map(|it| TypeRef::from_ast(ctx, it)), + ))), ast::Type::NeverType(..) => TypeRef::Never, ast::Type::PathType(inner) => { // FIXME: Use `Path::from_src` @@ -342,7 +341,12 @@ impl TypeRef { let abi = inner.abi().map(lower_abi); params.push((None, ret_ty)); - TypeRef::Fn(FnType::new(is_varargs, inner.unsafe_token().is_some(), abi, params)) + TypeRef::Fn(Box::new(FnType { + params: params.into(), + is_varargs, + is_unsafe: inner.unsafe_token().is_some(), + abi, + })) } // for types are close enough for our purposes to the inner type for now... ast::Type::ForType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()), @@ -375,7 +379,7 @@ impl TypeRef { } pub(crate) fn unit() -> TypeRef { - TypeRef::Tuple(EmptyOptimizedThinVec::empty()) + TypeRef::Tuple(ThinVec::new()) } pub fn walk(this: TypeRefId, map: &TypesMap, f: &mut impl FnMut(&TypeRef)) { @@ -386,7 +390,7 @@ impl TypeRef { f(type_ref); match type_ref { TypeRef::Fn(fn_) => { - fn_.params().iter().for_each(|&(_, param_type)| go(param_type, f, map)) + fn_.params.iter().for_each(|&(_, param_type)| go(param_type, f, map)) } TypeRef::Tuple(types) => types.iter().for_each(|&t| go(t, f, map)), TypeRef::RawPtr(type_ref, _) | TypeRef::Slice(type_ref) => go(*type_ref, f, map), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 776ee98f3bce2..6866821420529 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -12,11 +12,11 @@ use intern::{Symbol, sym}; use la_arena::Arena; use rustc_hash::FxHashMap; use span::{AstIdMap, SyntaxContext}; -use stdx::thin_vec::ThinVec; use syntax::{ AstNode, ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString}, }; +use thin_vec::ThinVec; use triomphe::Arc; use crate::{ diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs index c0f6e1a6867ce..b3acfe4239b88 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs @@ -3,8 +3,8 @@ use std::{cell::OnceCell, mem}; use hir_expand::{AstId, HirFileId, InFile, span_map::SpanMap}; use span::{AstIdMap, AstIdNode, Edition, EditionedFileId, FileId, RealSpanMap}; -use stdx::thin_vec::ThinVec; use syntax::ast; +use thin_vec::ThinVec; use triomphe::Arc; use crate::{ diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/path.rs index 1f7365f9a738c..7ef31d02450a9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path.rs @@ -16,7 +16,6 @@ use crate::{ use hir_expand::name::Name; use intern::Interned; use span::Edition; -use stdx::thin_vec::thin_vec_with_header_struct; use syntax::ast; pub use hir_expand::mod_path::{ModPath, PathKind, path}; @@ -58,7 +57,7 @@ pub enum Path { /// this is not a problem since many more paths have generics than a type anchor). BarePath(Interned), /// `Path::Normal` will always have either generics or type anchor. - Normal(NormalPath), + Normal(Box), /// A link to a lang item. It is used in desugaring of things like `it?`. We can show these /// links via a normal path since they might be private and not accessible in the usage place. LangItem(LangItemTarget, Option), @@ -71,12 +70,11 @@ const _: () = { assert!(size_of::>() == 16); }; -thin_vec_with_header_struct! { - pub new(pub(crate)) struct NormalPath, NormalPathHeader { - pub generic_args: [Option], - pub type_anchor: Option, - pub mod_path: Interned; ref, - } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct NormalPath { + pub generic_args: Box<[Option]>, + pub type_anchor: Option, + pub mod_path: Interned, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -143,7 +141,11 @@ impl Path { /// Converts a known mod path to `Path`. pub fn from_known_path(path: ModPath, generic_args: Vec>) -> Path { - Path::Normal(NormalPath::new(None, Interned::new(path), generic_args)) + Path::Normal(Box::new(NormalPath { + generic_args: generic_args.into_boxed_slice(), + type_anchor: None, + mod_path: Interned::new(path), + })) } /// Converts a known mod path to `Path`. @@ -155,7 +157,7 @@ impl Path { pub fn kind(&self) -> &PathKind { match self { Path::BarePath(mod_path) => &mod_path.kind, - Path::Normal(path) => &path.mod_path().kind, + Path::Normal(path) => &path.mod_path.kind, Path::LangItem(..) => &PathKind::Abs, } } @@ -163,7 +165,7 @@ impl Path { #[inline] pub fn type_anchor(&self) -> Option { match self { - Path::Normal(path) => path.type_anchor(), + Path::Normal(path) => path.type_anchor, Path::LangItem(..) | Path::BarePath(_) => None, } } @@ -171,7 +173,7 @@ impl Path { #[inline] pub fn generic_args(&self) -> Option<&[Option]> { match self { - Path::Normal(path) => Some(path.generic_args()), + Path::Normal(path) => Some(&path.generic_args), Path::LangItem(..) | Path::BarePath(_) => None, } } @@ -182,8 +184,8 @@ impl Path { PathSegments { segments: mod_path.segments(), generic_args: None } } Path::Normal(path) => PathSegments { - segments: path.mod_path().segments(), - generic_args: Some(path.generic_args()), + segments: path.mod_path.segments(), + generic_args: Some(&path.generic_args), }, Path::LangItem(_, seg) => PathSegments { segments: seg.as_slice(), generic_args: None }, } @@ -192,7 +194,7 @@ impl Path { pub fn mod_path(&self) -> Option<&ModPath> { match self { Path::BarePath(mod_path) => Some(mod_path), - Path::Normal(path) => Some(path.mod_path()), + Path::Normal(path) => Some(&path.mod_path), Path::LangItem(..) => None, } } @@ -209,12 +211,12 @@ impl Path { )))) } Path::Normal(path) => { - let mod_path = path.mod_path(); + let mod_path = &path.mod_path; if mod_path.is_ident() { return None; } - let type_anchor = path.type_anchor(); - let generic_args = path.generic_args(); + let type_anchor = path.type_anchor; + let generic_args = &path.generic_args; let qualifier_mod_path = Interned::new(ModPath::from_segments( mod_path.kind, mod_path.segments()[..mod_path.segments().len() - 1].iter().cloned(), @@ -223,11 +225,11 @@ impl Path { if type_anchor.is_none() && qualifier_generic_args.iter().all(|it| it.is_none()) { Some(Path::BarePath(qualifier_mod_path)) } else { - Some(Path::Normal(NormalPath::new( + Some(Path::Normal(Box::new(NormalPath { type_anchor, - qualifier_mod_path, - qualifier_generic_args.iter().cloned(), - ))) + mod_path: qualifier_mod_path, + generic_args: qualifier_generic_args.iter().cloned().collect(), + }))) } } Path::LangItem(..) => None, @@ -238,9 +240,9 @@ impl Path { match self { Path::BarePath(mod_path) => mod_path.is_Self(), Path::Normal(path) => { - path.type_anchor().is_none() - && path.mod_path().is_Self() - && path.generic_args().iter().all(|args| args.is_none()) + path.type_anchor.is_none() + && path.mod_path.is_Self() + && path.generic_args.iter().all(|args| args.is_none()) } Path::LangItem(..) => false, } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs index c8269db581731..78f3ec07aa3c2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs @@ -9,8 +9,8 @@ use hir_expand::{ name::{AsName, Name}, }; use intern::{Interned, sym}; -use stdx::thin_vec::EmptyOptimizedThinVec; use syntax::ast::{self, AstNode, HasGenericArgs, HasTypeBounds}; +use thin_vec::ThinVec; use crate::{ path::{ @@ -213,7 +213,11 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option< if type_anchor.is_none() && generic_args.is_empty() { return Some(Path::BarePath(mod_path)); } else { - return Some(Path::Normal(NormalPath::new(type_anchor, mod_path, generic_args))); + return Some(Path::Normal(Box::new(NormalPath { + generic_args: generic_args.into_boxed_slice(), + type_anchor, + mod_path, + }))); } fn qualifier(path: &ast::Path) -> Option { @@ -344,7 +348,7 @@ fn lower_generic_args_from_fn_path( param_types.push(type_ref); } let args = Box::new([GenericArg::Type( - ctx.alloc_type_ref_desugared(TypeRef::Tuple(EmptyOptimizedThinVec::from_iter(param_types))), + ctx.alloc_type_ref_desugared(TypeRef::Tuple(ThinVec::from_iter(param_types))), )]); let bindings = if let Some(ret_type) = ret_type { let type_ref = TypeRef::from_ast_opt(ctx, ret_type.ty()); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs index c431b45dc79cd..8d5f6b8b453b2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs @@ -220,11 +220,11 @@ pub(crate) fn print_type_ref( } TypeRef::Fn(fn_) => { let ((_, return_type), args) = - fn_.params().split_last().expect("TypeRef::Fn is missing return type"); - if fn_.is_unsafe() { + fn_.params.split_last().expect("TypeRef::Fn is missing return type"); + if fn_.is_unsafe { write!(buf, "unsafe ")?; } - if let Some(abi) = fn_.abi() { + if let Some(abi) = &fn_.abi { buf.write_str("extern ")?; buf.write_str(abi.as_str())?; buf.write_char(' ')?; @@ -236,7 +236,7 @@ pub(crate) fn print_type_ref( } print_type_ref(db, *typeref, map, buf, edition)?; } - if fn_.is_varargs() { + if fn_.is_varargs { if !args.is_empty() { write!(buf, ", ")?; } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 28ebaadf4d79e..4f1be7285c751 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -181,7 +181,7 @@ impl Resolver { { let path = match path { Path::BarePath(mod_path) => mod_path, - Path::Normal(it) => it.mod_path(), + Path::Normal(it) => &it.mod_path, Path::LangItem(l, seg) => { let type_ns = match *l { LangItemTarget::Union(it) => TypeNs::AdtId(it.into()), @@ -304,7 +304,7 @@ impl Resolver { ) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo)> { let path = match path { Path::BarePath(mod_path) => mod_path, - Path::Normal(it) => it.mod_path(), + Path::Normal(it) => &it.mod_path, Path::LangItem(l, None) => { return Some(( ResolveValueResult::ValueNs( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index d72b1955246e1..52ed0525a2cfa 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -2128,16 +2128,16 @@ impl HirDisplayWithTypesMap for TypeRefId { write!(f, "]")?; } TypeRef::Fn(fn_) => { - if fn_.is_unsafe() { + if fn_.is_unsafe { write!(f, "unsafe ")?; } - if let Some(abi) = fn_.abi() { + if let Some(abi) = &fn_.abi { f.write_str("extern \"")?; f.write_str(abi.as_str())?; f.write_str("\" ")?; } write!(f, "fn(")?; - if let Some(((_, return_type), function_parameters)) = fn_.params().split_last() { + if let Some(((_, return_type), function_parameters)) = fn_.params.split_last() { for index in 0..function_parameters.len() { let (param_name, param_type) = &function_parameters[index]; if let Some(name) = param_name { @@ -2150,8 +2150,8 @@ impl HirDisplayWithTypesMap for TypeRefId { write!(f, ", ")?; } } - if fn_.is_varargs() { - write!(f, "{}...", if fn_.params().len() == 1 { "" } else { ", " })?; + if fn_.is_varargs { + write!(f, "{}...", if fn_.params.len() == 1 { "" } else { ", " })?; } write!(f, ")")?; match &types_map[*return_type] { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index c5a6c21d29b29..238cbe2b05ded 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -198,7 +198,7 @@ impl InferenceContext<'_> { match &self.body[expr] { // Lang item paths cannot currently be local variables or statics. Expr::Path(Path::LangItem(_, _)) => false, - Expr::Path(Path::Normal(path)) => path.type_anchor().is_none(), + Expr::Path(Path::Normal(path)) => path.type_anchor.is_none(), Expr::Path(path) => self .resolver .resolve_path_in_value_ns_fully( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index e5f3c4cfc8fc9..9df8d9cebbe89 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -318,15 +318,15 @@ impl<'a> TyLoweringContext<'a> { let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { Substitution::from_iter( Interner, - fn_.params().iter().map(|&(_, tr)| ctx.lower_ty(tr)), + fn_.params.iter().map(|&(_, tr)| ctx.lower_ty(tr)), ) }); TyKind::Function(FnPointer { num_binders: 0, // FIXME lower `for<'a> fn()` correctly sig: FnSig { - abi: fn_.abi().as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol), - safety: if fn_.is_unsafe() { Safety::Unsafe } else { Safety::Safe }, - variadic: fn_.is_varargs(), + abi: fn_.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol), + safety: if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe }, + variadic: fn_.is_varargs, }, substitution: FnSubst(substs), }) diff --git a/src/tools/rust-analyzer/crates/stdx/src/lib.rs b/src/tools/rust-analyzer/crates/stdx/src/lib.rs index ce56a819942fc..982be40dd4256 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/lib.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/lib.rs @@ -12,7 +12,6 @@ pub mod non_empty_vec; pub mod panic_context; pub mod process; pub mod rand; -pub mod thin_vec; pub mod thread; pub use itertools; diff --git a/src/tools/rust-analyzer/crates/stdx/src/thin_vec.rs b/src/tools/rust-analyzer/crates/stdx/src/thin_vec.rs deleted file mode 100644 index 69d8ee7d9068b..0000000000000 --- a/src/tools/rust-analyzer/crates/stdx/src/thin_vec.rs +++ /dev/null @@ -1,468 +0,0 @@ -use std::alloc::{Layout, dealloc, handle_alloc_error}; -use std::fmt; -use std::hash::{Hash, Hasher}; -use std::marker::PhantomData; -use std::ops::{Deref, DerefMut}; -use std::ptr::{NonNull, addr_of_mut, slice_from_raw_parts_mut}; - -/// A type that is functionally equivalent to `(Header, Box<[Item]>)`, -/// but all data is stored in one heap allocation and the pointer is thin, -/// so the whole thing's size is like a pointer. -pub struct ThinVecWithHeader { - /// INVARIANT: Points to a valid heap allocation that contains `ThinVecInner
`, - /// followed by (suitably aligned) `len` `Item`s. - ptr: NonNull>, - _marker: PhantomData<(Header, Box<[Item]>)>, -} - -// SAFETY: We essentially own both the header and the items. -unsafe impl Send for ThinVecWithHeader {} -unsafe impl Sync for ThinVecWithHeader {} - -#[derive(Clone)] -struct ThinVecInner
{ - header: Header, - len: usize, -} - -impl ThinVecWithHeader { - /// # Safety - /// - /// The iterator must produce `len` elements. - #[inline] - unsafe fn from_trusted_len_iter( - header: Header, - len: usize, - items: impl Iterator, - ) -> Self { - let (ptr, layout, items_offset) = Self::allocate(len); - - struct DeallocGuard(*mut u8, Layout); - impl Drop for DeallocGuard { - fn drop(&mut self) { - // SAFETY: We allocated this above. - unsafe { - dealloc(self.0, self.1); - } - } - } - let _dealloc_guard = DeallocGuard(ptr.as_ptr().cast::(), layout); - - // INVARIANT: Between `0..1` there are only initialized items. - struct ItemsGuard(*mut Item, *mut Item); - impl Drop for ItemsGuard { - fn drop(&mut self) { - // SAFETY: Our invariant. - unsafe { - slice_from_raw_parts_mut(self.0, self.1.offset_from(self.0) as usize) - .drop_in_place(); - } - } - } - - // SAFETY: We allocated enough space. - let mut items_ptr = unsafe { ptr.as_ptr().byte_add(items_offset).cast::() }; - // INVARIANT: There are zero elements in this range. - let mut items_guard = ItemsGuard(items_ptr, items_ptr); - items.for_each(|item| { - // SAFETY: Our precondition guarantee we won't get more than `len` items, and we allocated - // enough space for `len` items. - unsafe { - items_ptr.write(item); - items_ptr = items_ptr.add(1); - } - // INVARIANT: We just initialized this item. - items_guard.1 = items_ptr; - }); - - // SAFETY: We allocated enough space. - unsafe { - ptr.write(ThinVecInner { header, len }); - } - - std::mem::forget(items_guard); - - std::mem::forget(_dealloc_guard); - - // INVARIANT: We allocated and initialized all fields correctly. - Self { ptr, _marker: PhantomData } - } - - #[inline] - fn allocate(len: usize) -> (NonNull>, Layout, usize) { - let (layout, items_offset) = Self::layout(len); - // SAFETY: We always have `len`, so our allocation cannot be zero-sized. - let ptr = unsafe { std::alloc::alloc(layout).cast::>() }; - let Some(ptr) = NonNull::>::new(ptr) else { - handle_alloc_error(layout); - }; - (ptr, layout, items_offset) - } - - #[inline] - #[allow(clippy::should_implement_trait)] - pub fn from_iter(header: Header, items: I) -> Self - where - I: IntoIterator, - I::IntoIter: TrustedLen, - { - let items = items.into_iter(); - // SAFETY: `TrustedLen` guarantees the iterator length is exact. - unsafe { Self::from_trusted_len_iter(header, items.len(), items) } - } - - #[inline] - fn items_offset(&self) -> usize { - // SAFETY: We `pad_to_align()` in `layout()`, so at most where accessing past the end of the allocation, - // which is allowed. - unsafe { - Layout::new::>().extend(Layout::new::()).unwrap_unchecked().1 - } - } - - #[inline] - fn header_and_len(&self) -> &ThinVecInner
{ - // SAFETY: By `ptr`'s invariant, it is correctly allocated and initialized. - unsafe { &*self.ptr.as_ptr() } - } - - #[inline] - fn items_ptr(&self) -> *mut [Item] { - let len = self.header_and_len().len; - // SAFETY: `items_offset()` returns the correct offset of the items, where they are allocated. - let ptr = unsafe { self.ptr.as_ptr().byte_add(self.items_offset()).cast::() }; - slice_from_raw_parts_mut(ptr, len) - } - - #[inline] - pub fn header(&self) -> &Header { - &self.header_and_len().header - } - - #[inline] - pub fn header_mut(&mut self) -> &mut Header { - // SAFETY: By `ptr`'s invariant, it is correctly allocated and initialized. - unsafe { &mut *addr_of_mut!((*self.ptr.as_ptr()).header) } - } - - #[inline] - pub fn items(&self) -> &[Item] { - // SAFETY: `items_ptr()` gives a valid pointer. - unsafe { &*self.items_ptr() } - } - - #[inline] - pub fn items_mut(&mut self) -> &mut [Item] { - // SAFETY: `items_ptr()` gives a valid pointer. - unsafe { &mut *self.items_ptr() } - } - - #[inline] - pub fn len(&self) -> usize { - self.header_and_len().len - } - - #[inline] - fn layout(len: usize) -> (Layout, usize) { - let (layout, items_offset) = Layout::new::>() - .extend(Layout::array::(len).expect("too big `ThinVec` requested")) - .expect("too big `ThinVec` requested"); - let layout = layout.pad_to_align(); - (layout, items_offset) - } -} - -/// # Safety -/// -/// The length reported must be exactly the number of items yielded. -pub unsafe trait TrustedLen: ExactSizeIterator {} - -unsafe impl TrustedLen for std::vec::IntoIter {} -unsafe impl TrustedLen for std::slice::Iter<'_, T> {} -unsafe impl<'a, T: Clone + 'a, I: TrustedLen> TrustedLen for std::iter::Cloned {} -unsafe impl T> TrustedLen for std::iter::Map {} -unsafe impl TrustedLen for std::vec::Drain<'_, T> {} -unsafe impl TrustedLen for std::array::IntoIter {} - -impl Clone for ThinVecWithHeader { - #[inline] - fn clone(&self) -> Self { - Self::from_iter(self.header().clone(), self.items().iter().cloned()) - } -} - -impl Drop for ThinVecWithHeader { - #[inline] - fn drop(&mut self) { - // This must come before we drop `header`, because after that we cannot make a reference to it in `len()`. - let len = self.len(); - - // SAFETY: The contents are allocated and initialized. - unsafe { - addr_of_mut!((*self.ptr.as_ptr()).header).drop_in_place(); - self.items_ptr().drop_in_place(); - } - - let (layout, _) = Self::layout(len); - // SAFETY: This was allocated in `new()` with the same layout calculation. - unsafe { - dealloc(self.ptr.as_ptr().cast::(), layout); - } - } -} - -impl fmt::Debug for ThinVecWithHeader { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ThinVecWithHeader") - .field("header", self.header()) - .field("items", &self.items()) - .finish() - } -} - -impl PartialEq for ThinVecWithHeader { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.header() == other.header() && self.items() == other.items() - } -} - -impl Eq for ThinVecWithHeader {} - -impl Hash for ThinVecWithHeader { - #[inline] - fn hash(&self, state: &mut H) { - self.header().hash(state); - self.items().hash(state); - } -} - -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct ThinVec(ThinVecWithHeader<(), T>); - -impl ThinVec { - #[inline] - #[allow(clippy::should_implement_trait)] - pub fn from_iter(values: I) -> Self - where - I: IntoIterator, - I::IntoIter: TrustedLen, - { - Self(ThinVecWithHeader::from_iter((), values)) - } - - #[inline] - pub fn len(&self) -> usize { - self.0.len() - } - - #[inline] - pub fn iter(&self) -> std::slice::Iter<'_, T> { - (**self).iter() - } - - #[inline] - pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> { - (**self).iter_mut() - } -} - -impl Deref for ThinVec { - type Target = [T]; - - #[inline] - fn deref(&self) -> &Self::Target { - self.0.items() - } -} - -impl DerefMut for ThinVec { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - self.0.items_mut() - } -} - -impl<'a, T> IntoIterator for &'a ThinVec { - type IntoIter = std::slice::Iter<'a, T>; - type Item = &'a T; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, T> IntoIterator for &'a mut ThinVec { - type IntoIter = std::slice::IterMut<'a, T>; - type Item = &'a mut T; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.iter_mut() - } -} - -impl fmt::Debug for ThinVec { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(&**self).finish() - } -} - -/// A [`ThinVec`] that requires no allocation for the empty case. -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct EmptyOptimizedThinVec(Option>); - -impl EmptyOptimizedThinVec { - #[inline] - #[allow(clippy::should_implement_trait)] - pub fn from_iter(values: I) -> Self - where - I: IntoIterator, - I::IntoIter: TrustedLen, - { - let values = values.into_iter(); - if values.len() == 0 { Self::empty() } else { Self(Some(ThinVec::from_iter(values))) } - } - - #[inline] - pub fn empty() -> Self { - Self(None) - } - - #[inline] - pub fn len(&self) -> usize { - self.0.as_ref().map_or(0, ThinVec::len) - } - - #[inline] - pub fn iter(&self) -> std::slice::Iter<'_, T> { - (**self).iter() - } - - #[inline] - pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> { - (**self).iter_mut() - } -} - -impl Default for EmptyOptimizedThinVec { - #[inline] - fn default() -> Self { - Self::empty() - } -} - -impl Deref for EmptyOptimizedThinVec { - type Target = [T]; - - #[inline] - fn deref(&self) -> &Self::Target { - self.0.as_deref().unwrap_or_default() - } -} - -impl DerefMut for EmptyOptimizedThinVec { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - self.0.as_deref_mut().unwrap_or_default() - } -} - -impl<'a, T> IntoIterator for &'a EmptyOptimizedThinVec { - type IntoIter = std::slice::Iter<'a, T>; - type Item = &'a T; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, T> IntoIterator for &'a mut EmptyOptimizedThinVec { - type IntoIter = std::slice::IterMut<'a, T>; - type Item = &'a mut T; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.iter_mut() - } -} - -impl fmt::Debug for EmptyOptimizedThinVec { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(&**self).finish() - } -} - -/// Syntax: -/// -/// ```ignore -/// thin_vec_with_header_struct! { -/// pub new(pub(crate)) struct MyCoolStruct, MyCoolStructHeader { -/// pub(crate) variable_length: [Ty], -/// pub field1: CopyTy, -/// pub field2: NonCopyTy; ref, -/// } -/// } -/// ``` -#[doc(hidden)] -#[macro_export] -macro_rules! thin_vec_with_header_struct_ { - (@maybe_ref (ref) $($t:tt)*) => { &$($t)* }; - (@maybe_ref () $($t:tt)*) => { $($t)* }; - ( - $vis:vis new($new_vis:vis) struct $struct:ident, $header:ident { - $items_vis:vis $items:ident : [$items_ty:ty], - $( $header_var_vis:vis $header_var:ident : $header_var_ty:ty $(; $ref:ident)?, )+ - } - ) => { - #[derive(Debug, Clone, Eq, PartialEq, Hash)] - struct $header { - $( $header_var : $header_var_ty, )+ - } - - #[derive(Clone, Eq, PartialEq, Hash)] - $vis struct $struct($crate::thin_vec::ThinVecWithHeader<$header, $items_ty>); - - impl $struct { - #[inline] - #[allow(unused)] - $new_vis fn new( - $( $header_var: $header_var_ty, )+ - $items: I, - ) -> Self - where - I: ::std::iter::IntoIterator, - I::IntoIter: $crate::thin_vec::TrustedLen, - { - Self($crate::thin_vec::ThinVecWithHeader::from_iter( - $header { $( $header_var, )+ }, - $items, - )) - } - - #[inline] - $items_vis fn $items(&self) -> &[$items_ty] { - self.0.items() - } - - $( - #[inline] - $header_var_vis fn $header_var(&self) -> $crate::thin_vec_with_header_struct_!(@maybe_ref ($($ref)?) $header_var_ty) { - $crate::thin_vec_with_header_struct_!(@maybe_ref ($($ref)?) self.0.header().$header_var) - } - )+ - } - - impl ::std::fmt::Debug for $struct { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - f.debug_struct(stringify!($struct)) - $( .field(stringify!($header_var), &self.$header_var()) )* - .field(stringify!($items), &self.$items()) - .finish() - } - } - }; -} -pub use crate::thin_vec_with_header_struct_ as thin_vec_with_header_struct; From 315e9aa79fc37e40d37a3ec0a5b46f6b81377306 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Sat, 8 Mar 2025 12:13:19 -0500 Subject: [PATCH 0261/2248] Don't check deprecated configs in `configs_are_tested` test --- clippy_config/src/conf.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 1b9ea464dc3c6..64b5acd19f277 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -1090,7 +1090,13 @@ mod tests { fn configs_are_tested() { let mut names: HashSet = crate::get_configuration_metadata() .into_iter() - .map(|meta| meta.name.replace('_', "-")) + .filter_map(|meta| { + if meta.deprecation_reason.is_none() { + Some(meta.name.replace('_', "-")) + } else { + None + } + }) .collect(); let toml_files = WalkDir::new("../tests") From e8c06a71cfe5606a9c4cb8854ee8d981ade9ca1f Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Mon, 24 Mar 2025 22:27:44 +0900 Subject: [PATCH 0262/2248] remove obsolete "Known Problems" in `ok_expect` --- clippy_lints/src/methods/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 1d9296016e25f..44753d963deed 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -478,9 +478,6 @@ declare_clippy_lint! { /// Because you usually call `expect()` on the `Result` /// directly to get a better error message. /// - /// ### Known problems - /// The error type needs to implement `Debug` - /// /// ### Example /// ```no_run /// # let x = Ok::<_, ()>(()); From 809c931804e5f6b338f395d13e2f31724ce1cae2 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 9 Feb 2025 22:26:34 +0100 Subject: [PATCH 0263/2248] `wildcard_imports`: lint on `pub use` if asked to `warn_on_all_wildcard_imports` should warn on all wildcard imports, including the reexported ones. --- book/src/lint_configuration.md | 3 ++- clippy_config/src/conf.rs | 3 ++- clippy_lints/src/wildcard_imports.rs | 6 +++++- tests/ui-toml/wildcard_imports/wildcard_imports.fixed | 2 +- tests/ui-toml/wildcard_imports/wildcard_imports.rs | 2 +- tests/ui-toml/wildcard_imports/wildcard_imports.stderr | 6 +++--- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 0e264cdcd4a3a..d7bdc00fe10ec 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -1030,7 +1030,8 @@ The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' ## `warn-on-all-wildcard-imports` -Whether to allow certain wildcard imports (prelude, super in tests). +Whether to emit warnings on all wildcard imports, including those from `prelude`, from `super` in tests, +or for `pub use` reexports. **Default Value:** `false` diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index cac4408fff0e3..90739436c8038 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -737,7 +737,8 @@ define_Conf! { /// The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' #[lints(verbose_bit_mask)] verbose_bit_mask_threshold: u64 = 1, - /// Whether to allow certain wildcard imports (prelude, super in tests). + /// Whether to emit warnings on all wildcard imports, including those from `prelude`, from `super` in tests, + /// or for `pub use` reexports. #[lints(wildcard_imports)] warn_on_all_wildcard_imports: bool = false, /// Whether to also emit warnings for unsafe blocks with metavariable expansions in **private** macros. diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 405310512dff3..5b3f60ad6ab0b 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -68,6 +68,8 @@ declare_clippy_lint! { /// (including the standard library) provide modules named "prelude" specifically designed /// for wildcard import. /// + /// Wildcard imports reexported through `pub use` are also allowed. + /// /// `use super::*` is allowed in test modules. This is defined as any module with "test" in the name. /// /// These exceptions can be disabled using the `warn-on-all-wildcard-imports` configuration flag. @@ -121,7 +123,9 @@ impl LateLintPass<'_> for WildcardImports { } let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id); - if cx.tcx.visibility(item.owner_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) { + if cx.tcx.visibility(item.owner_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) + && !self.warn_on_all + { return; } if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind diff --git a/tests/ui-toml/wildcard_imports/wildcard_imports.fixed b/tests/ui-toml/wildcard_imports/wildcard_imports.fixed index af72d6be0e096..20511cbed165e 100644 --- a/tests/ui-toml/wildcard_imports/wildcard_imports.fixed +++ b/tests/ui-toml/wildcard_imports/wildcard_imports.fixed @@ -15,7 +15,7 @@ mod my_crate { } } -use utils::{BAR, print}; +pub use utils::{BAR, print}; //~^ ERROR: usage of wildcard import use my_crate::utils::my_util_fn; //~^ ERROR: usage of wildcard import diff --git a/tests/ui-toml/wildcard_imports/wildcard_imports.rs b/tests/ui-toml/wildcard_imports/wildcard_imports.rs index 91009dd8835f8..8d05910f471ba 100644 --- a/tests/ui-toml/wildcard_imports/wildcard_imports.rs +++ b/tests/ui-toml/wildcard_imports/wildcard_imports.rs @@ -15,7 +15,7 @@ mod my_crate { } } -use utils::*; +pub use utils::*; //~^ ERROR: usage of wildcard import use my_crate::utils::*; //~^ ERROR: usage of wildcard import diff --git a/tests/ui-toml/wildcard_imports/wildcard_imports.stderr b/tests/ui-toml/wildcard_imports/wildcard_imports.stderr index 3d3be965aa411..5e624dd6c3cdc 100644 --- a/tests/ui-toml/wildcard_imports/wildcard_imports.stderr +++ b/tests/ui-toml/wildcard_imports/wildcard_imports.stderr @@ -1,8 +1,8 @@ error: usage of wildcard import - --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:18:5 + --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:18:9 | -LL | use utils::*; - | ^^^^^^^^ help: try: `utils::{BAR, print}` +LL | pub use utils::*; + | ^^^^^^^^ help: try: `utils::{BAR, print}` | = note: `-D clippy::wildcard-imports` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::wildcard_imports)]` From 621911a67702661b3ce4f2ce482193407d2fc412 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 24 Mar 2025 15:58:40 +0100 Subject: [PATCH 0264/2248] Fix various typos in lint messages, descriptions and comments --- clippy_lints/src/attrs/repr_attributes.rs | 2 +- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/methods/unnecessary_map_or.rs | 4 ++-- clippy_lints/src/non_std_lazy_statics.rs | 4 ++-- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/zombie_processes.rs | 2 +- clippy_utils/src/str_utils.rs | 4 ++-- clippy_utils/src/ty/mod.rs | 2 +- lintcheck/src/recursive.rs | 2 +- .../non_std_lazy_static_fixable.fixed | 14 +++++++------- .../non_std_lazy_static_fixable.rs | 14 +++++++------- .../non_std_lazy_static_fixable.stderr | 14 +++++++------- .../non_std_lazy_static_unfixable.rs | 12 ++++++------ .../non_std_lazy_static_unfixable.stderr | 12 ++++++------ tests/ui/repr_packed_without_abi.stderr | 4 ++-- 15 files changed, 47 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/attrs/repr_attributes.rs b/clippy_lints/src/attrs/repr_attributes.rs index e5cfbaf952a70..df01c7fde1819 100644 --- a/clippy_lints/src/attrs/repr_attributes.rs +++ b/clippy_lints/src/attrs/repr_attributes.rs @@ -30,7 +30,7 @@ pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute], diag.warn( "unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI", ) - .help("qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`") + .help("qualify the desired ABI explicitly via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`") .span_label(packed_span, "`packed` representation set here"); }, ); diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 03ed9c657b30a..d85005d57ede8 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -256,7 +256,7 @@ fn lint_branches_sharing_code<'tcx>( let suggestion = reindent_multiline(&suggestion, true, indent); let span = span.with_hi(last_block.span.hi()); - // Improve formatting if the inner block has indention (i.e. normal Rust formatting) + // Improve formatting if the inner block has indentation (i.e. normal Rust formatting) let span = span .map_range(cx, |src, range| { (range.start > 4 && src.get(range.start - 4..range.start)? == " ") diff --git a/clippy_lints/src/methods/unnecessary_map_or.rs b/clippy_lints/src/methods/unnecessary_map_or.rs index d7bd522ddab94..274bc5d1bf56a 100644 --- a/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/clippy_lints/src/methods/unnecessary_map_or.rs @@ -76,7 +76,7 @@ pub(super) fn check<'a>( && ((BinOpKind::Eq == op.node && !def_bool) || (BinOpKind::Ne == op.node && def_bool)) && let non_binding_location = if path_to_local_id(l, hir_id) { r } else { l } && switch_to_eager_eval(cx, non_binding_location) - // xor, because if its both then thats a strange edge case and + // xor, because if its both then that's a strange edge case and // we can just ignore it, since by default clippy will error on this && (path_to_local_id(l, hir_id) ^ path_to_local_id(r, hir_id)) && !is_local_used(cx, non_binding_location, hir_id) @@ -92,7 +92,7 @@ pub(super) fn check<'a>( // we may need to add parens around the suggestion // in case the parent expression has additional method calls, // since for example `Some(5).map_or(false, |x| x == 5).then(|| 1)` - // being converted to `Some(5) == Some(5).then(|| 1)` isnt + // being converted to `Some(5) == Some(5).then(|| 1)` isn't // the same thing let inner_non_binding = Sugg::NonParen(Cow::Owned(format!( diff --git a/clippy_lints/src/non_std_lazy_statics.rs b/clippy_lints/src/non_std_lazy_statics.rs index 8305bf345ef19..1df40a674bc46 100644 --- a/clippy_lints/src/non_std_lazy_statics.rs +++ b/clippy_lints/src/non_std_lazy_statics.rs @@ -121,7 +121,7 @@ impl<'hir> LateLintPass<'hir> for NonStdLazyStatic { cx, NON_STD_LAZY_STATICS, macro_call.span, - "this macro has been superceded by `std::sync::LazyLock`", + "this macro has been superseded by `std::sync::LazyLock`", ); return; } @@ -240,7 +240,7 @@ impl LazyInfo { cx, NON_STD_LAZY_STATICS, self.ty_span_no_args, - "this type has been superceded by `LazyLock` in the standard library", + "this type has been superseded by `LazyLock` in the standard library", |diag| { diag.multipart_suggestion("use `std::sync::LazyLock` instead", suggs, appl); }, diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index ee282ee1dfb71..3795c7483da4d 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -65,7 +65,7 @@ declare_clippy_lint! { #[clippy::version = "pre 1.29.0"] pub SHADOW_REUSE, restriction, - "rebinding a name to an expression that re-uses the original value, e.g., `let x = x + 1`" + "rebinding a name to an expression that reuses the original value, e.g., `let x = x + 1`" } declare_clippy_lint! { diff --git a/clippy_lints/src/zombie_processes.rs b/clippy_lints/src/zombie_processes.rs index 7667db469689e..39c1aab8967ad 100644 --- a/clippy_lints/src/zombie_processes.rs +++ b/clippy_lints/src/zombie_processes.rs @@ -131,7 +131,7 @@ struct WaitFinder<'a, 'tcx> { local_id: HirId, state: VisitorState, early_return: Option, - // When joining two if branches where one of them doesn't call `wait()`, stores its span for more targetted help + // When joining two if branches where one of them doesn't call `wait()`, stores its span for more targeted help // messages missing_wait_branch: Option, } diff --git a/clippy_utils/src/str_utils.rs b/clippy_utils/src/str_utils.rs index 421b25a77fe8b..f0f82c8dddcf5 100644 --- a/clippy_utils/src/str_utils.rs +++ b/clippy_utils/src/str_utils.rs @@ -1,4 +1,4 @@ -/// Dealing with sting indices can be hard, this struct ensures that both the +/// Dealing with string indices can be hard, this struct ensures that both the /// character and byte index are provided for correct indexing. #[derive(Debug, Default, PartialEq, Eq)] pub struct StrIndex { @@ -165,7 +165,7 @@ pub fn camel_case_split(s: &str) -> Vec<&str> { offsets.windows(2).map(|w| &s[w[0]..w[1]]).collect() } -/// Dealing with sting comparison can be complicated, this struct ensures that both the +/// Dealing with string comparison can be complicated, this struct ensures that both the /// character and byte count are provided for correct indexing. #[derive(Debug, Default, PartialEq, Eq)] pub struct StrCount { diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 6fdf4c244f8d8..99650d0292faf 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -1352,7 +1352,7 @@ pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_n } } -/// Get's the type of a field by name. +/// Gets the type of a field by name. pub fn get_field_by_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> Option> { match *ty.kind() { ty::Adt(def, args) if def.is_union() || def.is_struct() => def diff --git a/lintcheck/src/recursive.rs b/lintcheck/src/recursive.rs index 57073f523648e..6406b2dcb643b 100644 --- a/lintcheck/src/recursive.rs +++ b/lintcheck/src/recursive.rs @@ -64,7 +64,7 @@ fn process_stream( // It's 99% likely that dependencies compiled with recursive mode are on crates.io // and therefore on docs.rs. This links to the sources directly, do avoid invalid - // links due to remaped paths. See rust-lang/docs.rs#2551 for more details. + // links due to remapped paths. See rust-lang/docs.rs#2551 for more details. let base_url = format!( "https://docs.rs/crate/{}/{}/source/src/{{file}}#{{line}}", driver_info.package_name, driver_info.version diff --git a/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.fixed b/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.fixed index f7c56b6fffe81..2b30c8f984ebe 100644 --- a/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.fixed +++ b/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.fixed @@ -9,16 +9,16 @@ use once_cell::sync::Lazy; fn main() {} static LAZY_FOO: std::sync::LazyLock = std::sync::LazyLock::new(|| "foo".to_uppercase()); -//~^ ERROR: this type has been superceded by `LazyLock` in the standard library +//~^ ERROR: this type has been superseded by `LazyLock` in the standard library static LAZY_BAR: std::sync::LazyLock = std::sync::LazyLock::new(|| { - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library let x = "bar"; x.to_uppercase() }); static LAZY_BAZ: std::sync::LazyLock = { std::sync::LazyLock::new(|| "baz".to_uppercase()) }; -//~^ ERROR: this type has been superceded by `LazyLock` in the standard library +//~^ ERROR: this type has been superseded by `LazyLock` in the standard library static LAZY_QUX: std::sync::LazyLock = { - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library if "qux".len() == 3 { std::sync::LazyLock::new(|| "qux".to_uppercase()) } else if "qux".is_ascii() { @@ -39,11 +39,11 @@ mod once_cell_lazy_with_fns { use once_cell::sync::Lazy; static LAZY_FOO: std::sync::LazyLock = std::sync::LazyLock::new(|| "foo".to_uppercase()); - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library static LAZY_BAR: std::sync::LazyLock = std::sync::LazyLock::new(|| "bar".to_uppercase()); - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library static mut LAZY_BAZ: std::sync::LazyLock = std::sync::LazyLock::new(|| "baz".to_uppercase()); - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library fn calling_replaceable_fns() { let _ = std::sync::LazyLock::force(&LAZY_FOO); diff --git a/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs b/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs index 90bc428137cea..c52338eee83cb 100644 --- a/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs +++ b/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs @@ -9,16 +9,16 @@ use once_cell::sync::Lazy; fn main() {} static LAZY_FOO: Lazy = Lazy::new(|| "foo".to_uppercase()); -//~^ ERROR: this type has been superceded by `LazyLock` in the standard library +//~^ ERROR: this type has been superseded by `LazyLock` in the standard library static LAZY_BAR: Lazy = Lazy::new(|| { - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library let x = "bar"; x.to_uppercase() }); static LAZY_BAZ: Lazy = { Lazy::new(|| "baz".to_uppercase()) }; -//~^ ERROR: this type has been superceded by `LazyLock` in the standard library +//~^ ERROR: this type has been superseded by `LazyLock` in the standard library static LAZY_QUX: Lazy = { - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library if "qux".len() == 3 { Lazy::new(|| "qux".to_uppercase()) } else if "qux".is_ascii() { @@ -39,11 +39,11 @@ mod once_cell_lazy_with_fns { use once_cell::sync::Lazy; static LAZY_FOO: Lazy = Lazy::new(|| "foo".to_uppercase()); - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library static LAZY_BAR: Lazy = Lazy::new(|| "bar".to_uppercase()); - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library static mut LAZY_BAZ: Lazy = Lazy::new(|| "baz".to_uppercase()); - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library fn calling_replaceable_fns() { let _ = Lazy::force(&LAZY_FOO); diff --git a/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.stderr b/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.stderr index 333052ae1c110..bb80cd11c7199 100644 --- a/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.stderr +++ b/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.stderr @@ -1,4 +1,4 @@ -error: this type has been superceded by `LazyLock` in the standard library +error: this type has been superseded by `LazyLock` in the standard library --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:11:18 | LL | static LAZY_FOO: Lazy = Lazy::new(|| "foo".to_uppercase()); @@ -12,7 +12,7 @@ LL - static LAZY_FOO: Lazy = Lazy::new(|| "foo".to_uppercase()); LL + static LAZY_FOO: std::sync::LazyLock = std::sync::LazyLock::new(|| "foo".to_uppercase()); | -error: this type has been superceded by `LazyLock` in the standard library +error: this type has been superseded by `LazyLock` in the standard library --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:13:18 | LL | static LAZY_BAR: Lazy = Lazy::new(|| { @@ -24,7 +24,7 @@ LL - static LAZY_BAR: Lazy = Lazy::new(|| { LL + static LAZY_BAR: std::sync::LazyLock = std::sync::LazyLock::new(|| { | -error: this type has been superceded by `LazyLock` in the standard library +error: this type has been superseded by `LazyLock` in the standard library --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:18:18 | LL | static LAZY_BAZ: Lazy = { Lazy::new(|| "baz".to_uppercase()) }; @@ -36,7 +36,7 @@ LL - static LAZY_BAZ: Lazy = { Lazy::new(|| "baz".to_uppercase()) }; LL + static LAZY_BAZ: std::sync::LazyLock = { std::sync::LazyLock::new(|| "baz".to_uppercase()) }; | -error: this type has been superceded by `LazyLock` in the standard library +error: this type has been superseded by `LazyLock` in the standard library --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:20:18 | LL | static LAZY_QUX: Lazy = { @@ -54,7 +54,7 @@ LL | } else { LL ~ std::sync::LazyLock::new(|| "qux".to_string()) | -error: this type has been superceded by `LazyLock` in the standard library +error: this type has been superseded by `LazyLock` in the standard library --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:41:22 | LL | static LAZY_FOO: Lazy = Lazy::new(|| "foo".to_uppercase()); @@ -69,7 +69,7 @@ LL | fn calling_replaceable_fns() { LL ~ let _ = std::sync::LazyLock::force(&LAZY_FOO); | -error: this type has been superceded by `LazyLock` in the standard library +error: this type has been superseded by `LazyLock` in the standard library --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:43:22 | LL | static LAZY_BAR: Lazy = Lazy::new(|| "bar".to_uppercase()); @@ -84,7 +84,7 @@ LL | let _ = Lazy::force(&LAZY_FOO); LL ~ let _ = std::sync::LazyLock::force(&LAZY_BAR); | -error: this type has been superceded by `LazyLock` in the standard library +error: this type has been superseded by `LazyLock` in the standard library --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:45:26 | LL | static mut LAZY_BAZ: Lazy = Lazy::new(|| "baz".to_uppercase()); diff --git a/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs b/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs index 34f8dd1ccb2ea..acc8c04678f50 100644 --- a/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs +++ b/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs @@ -9,11 +9,11 @@ mod once_cell_lazy { use once_cell::sync::Lazy; static LAZY_FOO: Lazy = Lazy::new(|| "foo".to_uppercase()); - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library static mut LAZY_BAR: Lazy = Lazy::new(|| "bar".to_uppercase()); - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library static mut LAZY_BAZ: Lazy = Lazy::new(|| "baz".to_uppercase()); - //~^ ERROR: this type has been superceded by `LazyLock` in the standard library + //~^ ERROR: this type has been superseded by `LazyLock` in the standard library fn calling_irreplaceable_fns() { let _ = Lazy::get(&LAZY_FOO); @@ -31,13 +31,13 @@ mod lazy_static_lazy_static { lazy_static! { static ref LAZY_FOO: String = "foo".to_uppercase(); } - //~^^^ ERROR: this macro has been superceded by `std::sync::LazyLock` + //~^^^ ERROR: this macro has been superseded by `std::sync::LazyLock` lazy_static! { static ref LAZY_BAR: String = "bar".to_uppercase(); static ref LAZY_BAZ: String = "baz".to_uppercase(); } - //~^^^^ ERROR: this macro has been superceded by `std::sync::LazyLock` - //~| ERROR: this macro has been superceded by `std::sync::LazyLock` + //~^^^^ ERROR: this macro has been superseded by `std::sync::LazyLock` + //~| ERROR: this macro has been superseded by `std::sync::LazyLock` } fn main() {} diff --git a/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.stderr b/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.stderr index 216190ae4ca31..2c35cad6237ab 100644 --- a/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.stderr +++ b/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.stderr @@ -1,4 +1,4 @@ -error: this macro has been superceded by `std::sync::LazyLock` +error: this macro has been superseded by `std::sync::LazyLock` --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:31:5 | LL | / lazy_static! { @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::non-std-lazy-statics` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::non_std_lazy_statics)]` -error: this macro has been superceded by `std::sync::LazyLock` +error: this macro has been superseded by `std::sync::LazyLock` --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:35:5 | LL | / lazy_static! { @@ -18,7 +18,7 @@ LL | | static ref LAZY_BAZ: String = "baz".to_uppercase(); LL | | } | |_____^ -error: this macro has been superceded by `std::sync::LazyLock` +error: this macro has been superseded by `std::sync::LazyLock` --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:35:5 | LL | / lazy_static! { @@ -29,7 +29,7 @@ LL | | } | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: this type has been superceded by `LazyLock` in the standard library +error: this type has been superseded by `LazyLock` in the standard library --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:11:22 | LL | static LAZY_FOO: Lazy = Lazy::new(|| "foo".to_uppercase()); @@ -41,7 +41,7 @@ LL - static LAZY_FOO: Lazy = Lazy::new(|| "foo".to_uppercase()); LL + static LAZY_FOO: std::sync::LazyLock = std::sync::LazyLock::new(|| "foo".to_uppercase()); | -error: this type has been superceded by `LazyLock` in the standard library +error: this type has been superseded by `LazyLock` in the standard library --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:13:26 | LL | static mut LAZY_BAR: Lazy = Lazy::new(|| "bar".to_uppercase()); @@ -53,7 +53,7 @@ LL - static mut LAZY_BAR: Lazy = Lazy::new(|| "bar".to_uppercase()); LL + static mut LAZY_BAR: std::sync::LazyLock = std::sync::LazyLock::new(|| "bar".to_uppercase()); | -error: this type has been superceded by `LazyLock` in the standard library +error: this type has been superseded by `LazyLock` in the standard library --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:15:26 | LL | static mut LAZY_BAZ: Lazy = Lazy::new(|| "baz".to_uppercase()); diff --git a/tests/ui/repr_packed_without_abi.stderr b/tests/ui/repr_packed_without_abi.stderr index d1078b3e8e48e..f688e4bc744ae 100644 --- a/tests/ui/repr_packed_without_abi.stderr +++ b/tests/ui/repr_packed_without_abi.stderr @@ -11,7 +11,7 @@ LL | | } | |_^ | = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI - = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]` + = help: qualify the desired ABI explicitly via `#[repr(C, packed)]` or `#[repr(Rust, packed)]` note: the lint level is defined here --> tests/ui/repr_packed_without_abi.rs:1:9 | @@ -31,7 +31,7 @@ LL | | } | |_^ | = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI - = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]` + = help: qualify the desired ABI explicitly via `#[repr(C, packed)]` or `#[repr(Rust, packed)]` error: aborting due to 2 previous errors From 22624ade4891a203971b53a900501a92d612f1fe Mon Sep 17 00:00:00 2001 From: David Barsky Date: Fri, 14 Mar 2025 14:03:50 -0400 Subject: [PATCH 0265/2248] analysis-stats: emit lines of code and item tree counts for workspace; dependencies --- .../rust-analyzer/src/cli/analysis_stats.rs | 87 +++++++++++++------ 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 29331000a1193..74d791318849c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -118,27 +118,67 @@ impl flags::AnalysisStats { } let mut item_tree_sw = self.stop_watch(); - let mut num_item_trees = 0; let source_roots = krates .iter() .cloned() .map(|krate| db.file_source_root(krate.root_file(db)).source_root_id(db)) .unique(); + + let mut dep_loc = 0; + let mut workspace_loc = 0; + let mut deps_item_trees = 0; + let mut workspace_item_trees = 0; + for source_root_id in source_roots { let source_root = db.source_root(source_root_id).source_root(db); - if !source_root.is_library || self.with_deps { - for file_id in source_root.iter() { - if let Some(p) = source_root.path_for_file(&file_id) { - if let Some((_, Some("rs"))) = p.name_and_extension() { + for file_id in source_root.iter() { + if let Some(p) = source_root.path_for_file(&file_id) { + if let Some((_, Some("rs"))) = p.name_and_extension() { + // measure workspace/project code + if !source_root.is_library || self.with_deps { + let length = db.file_text(file_id).text(db).lines().count(); db.file_item_tree(EditionedFileId::current_edition(file_id).into()); - num_item_trees += 1; + + workspace_loc += length; + workspace_item_trees += 1; + } else if self.source_stats { + let length = db.file_text(file_id).text(db).lines().count(); + db.file_item_tree(EditionedFileId::current_edition(file_id).into()); + + dep_loc += length; + deps_item_trees += 1 } } } } } - eprintln!(" item trees: {num_item_trees}"); + eprintln!(" item trees: {workspace_item_trees}"); let item_tree_time = item_tree_sw.elapsed(); + + if self.source_stats { + eprintln!("Source stats:"); + eprintln!(" dependency lines of code: {dep_loc}, item trees: {deps_item_trees}"); + eprintln!( + " workspace lines of code: {workspace_loc}, item trees: {workspace_item_trees}" + ); + + // FIXME(salsa-transition): bring back stats for ParseQuery (file size) + // and ParseMacroExpansionQuery (mcaro expansion "file") size whenever we implement + // Salsa's memory usage tracking works with tracked functions. + + // let mut total_file_size = Bytes::default(); + // for e in ide_db::base_db::ParseQuery.in_db(db).entries::>() { + // total_file_size += syntax_len(db.parse(e.key).syntax_node()) + // } + + // let mut total_macro_file_size = Bytes::default(); + // for e in hir::db::ParseMacroExpansionQuery.in_db(db).entries::>() { + // let val = db.parse_macro_expansion(e.key).value.0; + // total_macro_file_size += syntax_len(val.syntax_node()) + // } + // eprintln!("source files: {total_file_size}, macro files: {total_macro_file_size}"); + } + eprintln!("{:<20} {}", "Item Tree Collection:", item_tree_time); report_metric("item tree time", item_tree_time.time.as_millis() as u64, "ms"); @@ -168,6 +208,11 @@ impl flags::AnalysisStats { let mut bodies = Vec::new(); let mut adts = Vec::new(); let mut file_ids = Vec::new(); + + let mut num_traits = 0; + let mut num_macro_rules_macros = 0; + let mut num_proc_macros = 0; + while let Some(module) = visit_queue.pop() { if visited_modules.insert(module) { file_ids.extend(module.as_source_file_id(db)); @@ -189,6 +234,14 @@ impl flags::AnalysisStats { bodies.push(DefWithBody::from(c)); } ModuleDef::Static(s) => bodies.push(DefWithBody::from(s)), + ModuleDef::Trait(_) => num_traits += 1, + ModuleDef::Macro(m) => match m.kind(db) { + hir::MacroKind::Declarative => num_macro_rules_macros += 1, + hir::MacroKind::Derive + | hir::MacroKind::Attr + | hir::MacroKind::ProcMacro => num_proc_macros += 1, + _ => (), + }, _ => (), }; } @@ -217,6 +270,8 @@ impl flags::AnalysisStats { .filter(|it| matches!(it, DefWithBody::Const(_) | DefWithBody::Static(_))) .count(), ); + eprintln!(" traits: {num_traits}, macro_rules macros: {num_macro_rules_macros}, proc_macros: {num_proc_macros}"); + let crate_def_map_time = crate_def_map_sw.elapsed(); eprintln!("{:<20} {}", "Item Collection:", crate_def_map_time); report_metric("crate def map time", crate_def_map_time.time.as_millis() as u64, "ms"); @@ -264,24 +319,6 @@ impl flags::AnalysisStats { } report_metric("total memory", total_span.memory.allocated.megabytes() as u64, "MB"); - if self.source_stats { - // FIXME(salsa-transition): bring back stats for ParseQuery (file size) - // and ParseMacroExpansionQuery (mcaro expansion "file") size whenever we implement - // Salsa's memory usage tracking works with tracked functions. - - // let mut total_file_size = Bytes::default(); - // for e in ide_db::base_db::ParseQuery.in_db(db).entries::>() { - // total_file_size += syntax_len(db.parse(e.key).syntax_node()) - // } - - // let mut total_macro_file_size = Bytes::default(); - // for e in hir::db::ParseMacroExpansionQuery.in_db(db).entries::>() { - // let val = db.parse_macro_expansion(e.key).value.0; - // total_macro_file_size += syntax_len(val.syntax_node()) - // } - // eprintln!("source files: {total_file_size}, macro files: {total_macro_file_size}"); - } - if verbosity.is_verbose() { print_memory_usage(host, vfs); } From efe3fe76ea699b51c4da6e6c98c0b03b1eddb59f Mon Sep 17 00:00:00 2001 From: David Barsky Date: Fri, 14 Mar 2025 15:27:56 -0400 Subject: [PATCH 0266/2248] analysis-stats: always print source stats --- .../rust-analyzer/src/cli/analysis_stats.rs | 44 +++++++++---------- .../crates/rust-analyzer/src/cli/flags.rs | 3 -- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 74d791318849c..97a319f031257 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -141,7 +141,7 @@ impl flags::AnalysisStats { workspace_loc += length; workspace_item_trees += 1; - } else if self.source_stats { + } else { let length = db.file_text(file_id).text(db).lines().count(); db.file_item_tree(EditionedFileId::current_edition(file_id).into()); @@ -155,29 +155,25 @@ impl flags::AnalysisStats { eprintln!(" item trees: {workspace_item_trees}"); let item_tree_time = item_tree_sw.elapsed(); - if self.source_stats { - eprintln!("Source stats:"); - eprintln!(" dependency lines of code: {dep_loc}, item trees: {deps_item_trees}"); - eprintln!( - " workspace lines of code: {workspace_loc}, item trees: {workspace_item_trees}" - ); + eprintln!("Source stats:"); + eprintln!(" dependency lines of code: {dep_loc}, item trees: {deps_item_trees}"); + eprintln!(" workspace lines of code: {workspace_loc}, item trees: {workspace_item_trees}"); - // FIXME(salsa-transition): bring back stats for ParseQuery (file size) - // and ParseMacroExpansionQuery (mcaro expansion "file") size whenever we implement - // Salsa's memory usage tracking works with tracked functions. - - // let mut total_file_size = Bytes::default(); - // for e in ide_db::base_db::ParseQuery.in_db(db).entries::>() { - // total_file_size += syntax_len(db.parse(e.key).syntax_node()) - // } - - // let mut total_macro_file_size = Bytes::default(); - // for e in hir::db::ParseMacroExpansionQuery.in_db(db).entries::>() { - // let val = db.parse_macro_expansion(e.key).value.0; - // total_macro_file_size += syntax_len(val.syntax_node()) - // } - // eprintln!("source files: {total_file_size}, macro files: {total_macro_file_size}"); - } + // FIXME(salsa-transition): bring back stats for ParseQuery (file size) + // and ParseMacroExpansionQuery (mcaro expansion "file") size whenever we implement + // Salsa's memory usage tracking works with tracked functions. + + // let mut total_file_size = Bytes::default(); + // for e in ide_db::base_db::ParseQuery.in_db(db).entries::>() { + // total_file_size += syntax_len(db.parse(e.key).syntax_node()) + // } + + // let mut total_macro_file_size = Bytes::default(); + // for e in hir::db::ParseMacroExpansionQuery.in_db(db).entries::>() { + // let val = db.parse_macro_expansion(e.key).value.0; + // total_macro_file_size += syntax_len(val.syntax_node()) + // } + // eprintln!("source files: {total_file_size}, macro files: {total_macro_file_size}"); eprintln!("{:<20} {}", "Item Tree Collection:", item_tree_time); report_metric("item tree time", item_tree_time.time.as_millis() as u64, "ms"); @@ -261,7 +257,7 @@ impl flags::AnalysisStats { } } eprintln!( - ", mods: {}, decls: {num_decls}, bodies: {}, adts: {}, consts: {}", + ", mods: {}, decls: {num_decls}, bodies: {}, adts: {}, consts: {},", visited_modules.len(), bodies.len(), adts.len(), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs index ff24602144a9d..13075d4994228 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs @@ -62,8 +62,6 @@ xflags::xflags! { optional --randomize /// Run type inference in parallel. optional --parallel - /// Print the total length of all source and macro files (whitespace is not counted). - optional --source-stats /// Only analyze items matching this path. optional -o, --only path: String @@ -231,7 +229,6 @@ pub struct AnalysisStats { pub output: Option, pub randomize: bool, pub parallel: bool, - pub source_stats: bool, pub only: Option, pub with_deps: bool, pub no_sysroot: bool, From 44a5b14ca253728381368a6afce68017058c25d5 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Fri, 14 Mar 2025 15:57:47 -0400 Subject: [PATCH 0267/2248] analysis-stats: add `UsizeWithUnderscore` for readability of large numbers --- .../rust-analyzer/src/cli/analysis_stats.rs | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 97a319f031257..c5186d85d5566 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -2,7 +2,7 @@ //! errors. use std::{ - env, + env, fmt, time::{SystemTime, UNIX_EPOCH}, }; @@ -156,6 +156,11 @@ impl flags::AnalysisStats { let item_tree_time = item_tree_sw.elapsed(); eprintln!("Source stats:"); + let dep_loc = UsizeWithUnderscore(dep_loc); + let deps_item_trees = UsizeWithUnderscore(deps_item_trees); + let workspace_loc = UsizeWithUnderscore(workspace_loc); + let workspace_item_trees = UsizeWithUnderscore(workspace_item_trees); + eprintln!(" dependency lines of code: {dep_loc}, item trees: {deps_item_trees}"); eprintln!(" workspace lines of code: {workspace_loc}, item trees: {workspace_item_trees}"); @@ -1250,6 +1255,30 @@ fn percentage(n: u64, total: u64) -> u64 { (n * 100).checked_div(total).unwrap_or(100) } +struct UsizeWithUnderscore(usize); + +impl fmt::Display for UsizeWithUnderscore { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let num_str = self.0.to_string(); + + if num_str.len() <= 3 { + return write!(f, "{}", num_str); + } + + let mut result = String::new(); + + for (count, ch) in num_str.chars().rev().enumerate() { + if count > 0 && count % 3 == 0 { + result.push('_'); + } + result.push(ch); + } + + let result = result.chars().rev().collect::(); + write!(f, "{}", result) + } +} + // FIXME(salsa-transition): bring this back whenever we implement // Salsa's memory usage tracking to work with tracked functions. // fn syntax_len(node: SyntaxNode) -> usize { From 12dc311eb83d20e3241bdf7817eb4d11b03f4aee Mon Sep 17 00:00:00 2001 From: David Barsky Date: Fri, 14 Mar 2025 17:53:17 -0400 Subject: [PATCH 0268/2248] analysis-stats: cleanup printing of some workspace stats --- .../rust-analyzer/src/cli/analysis_stats.rs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index c5186d85d5566..bca44f9588682 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -126,7 +126,7 @@ impl flags::AnalysisStats { let mut dep_loc = 0; let mut workspace_loc = 0; - let mut deps_item_trees = 0; + let mut dep_item_trees = 0; let mut workspace_item_trees = 0; for source_root_id in source_roots { @@ -146,7 +146,7 @@ impl flags::AnalysisStats { db.file_item_tree(EditionedFileId::current_edition(file_id).into()); dep_loc += length; - deps_item_trees += 1 + dep_item_trees += 1 } } } @@ -156,16 +156,19 @@ impl flags::AnalysisStats { let item_tree_time = item_tree_sw.elapsed(); eprintln!("Source stats:"); - let dep_loc = UsizeWithUnderscore(dep_loc); - let deps_item_trees = UsizeWithUnderscore(deps_item_trees); - let workspace_loc = UsizeWithUnderscore(workspace_loc); - let workspace_item_trees = UsizeWithUnderscore(workspace_item_trees); - - eprintln!(" dependency lines of code: {dep_loc}, item trees: {deps_item_trees}"); - eprintln!(" workspace lines of code: {workspace_loc}, item trees: {workspace_item_trees}"); + eprintln!( + " dependency lines of code: {}, item trees: {}", + UsizeWithUnderscore(dep_loc), + UsizeWithUnderscore(dep_item_trees), + ); + eprintln!( + " workspace lines of code: {}, item trees: {}", + UsizeWithUnderscore(workspace_loc), + UsizeWithUnderscore(workspace_item_trees), + ); // FIXME(salsa-transition): bring back stats for ParseQuery (file size) - // and ParseMacroExpansionQuery (mcaro expansion "file") size whenever we implement + // and ParseMacroExpansionQuery (macro expansion "file") size whenever we implement // Salsa's memory usage tracking works with tracked functions. // let mut total_file_size = Bytes::default(); @@ -180,7 +183,7 @@ impl flags::AnalysisStats { // } // eprintln!("source files: {total_file_size}, macro files: {total_macro_file_size}"); - eprintln!("{:<20} {}", "Item Tree Collection:", item_tree_time); + eprintln!("{:<20} {}", "Item Tree Collection (workspace):", item_tree_time); report_metric("item tree time", item_tree_time.time.as_millis() as u64, "ms"); let mut crate_def_map_sw = self.stop_watch(); From fe192932a9bdc77dd56e5b3d989e223b565eca51 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Sat, 15 Mar 2025 11:19:25 -0400 Subject: [PATCH 0269/2248] analysis-stats: expose and print some limited statistics from `hir-def` --- .../crates/hir-def/src/item_tree.rs | 25 +++++++ .../rust-analyzer/src/cli/analysis_stats.rs | 68 ++++++++++++++++++- 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index ea87b0f70006c..2debbb1ee4e35 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -218,6 +218,22 @@ impl ItemTree { Attrs::filter(db, krate, self.raw_attrs(of).clone()) } + /// Returns a count of a few, expensive items. + /// + /// For more detail, see [`ItemTreeDataStats`]. + pub fn item_tree_stats(&self) -> ItemTreeDataStats { + match self.data { + Some(ref data) => ItemTreeDataStats { + traits: data.traits.len(), + impls: data.impls.len(), + mods: data.mods.len(), + macro_calls: data.macro_calls.len(), + macro_rules: data.macro_rules.len(), + }, + None => ItemTreeDataStats::default(), + } + } + pub fn pretty_print(&self, db: &dyn DefDatabase, edition: Edition) -> String { pretty::print_item_tree(db, self, edition) } @@ -328,6 +344,15 @@ struct ItemTreeData { vis: ItemVisibilities, } +#[derive(Default, Debug, Eq, PartialEq)] +pub struct ItemTreeDataStats { + pub traits: usize, + pub impls: usize, + pub mods: usize, + pub macro_calls: usize, + pub macro_rules: usize, +} + #[derive(Default, Debug, Eq, PartialEq)] pub struct ItemTreeSourceMaps { all_concatenated: Box<[TypesSourceMap]>, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index bca44f9588682..ec232d8e85c36 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -3,6 +3,7 @@ use std::{ env, fmt, + ops::AddAssign, time::{SystemTime, UNIX_EPOCH}, }; @@ -129,6 +130,9 @@ impl flags::AnalysisStats { let mut dep_item_trees = 0; let mut workspace_item_trees = 0; + let mut workspace_item_stats = PrettyItemStats::default(); + let mut dep_item_stats = PrettyItemStats::default(); + for source_root_id in source_roots { let source_root = db.source_root(source_root_id).source_root(db); for file_id in source_root.iter() { @@ -137,16 +141,24 @@ impl flags::AnalysisStats { // measure workspace/project code if !source_root.is_library || self.with_deps { let length = db.file_text(file_id).text(db).lines().count(); - db.file_item_tree(EditionedFileId::current_edition(file_id).into()); + let item_stats = db + .file_item_tree(EditionedFileId::current_edition(file_id).into()) + .item_tree_stats() + .into(); workspace_loc += length; workspace_item_trees += 1; + workspace_item_stats += item_stats; } else { let length = db.file_text(file_id).text(db).lines().count(); - db.file_item_tree(EditionedFileId::current_edition(file_id).into()); + let item_stats = db + .file_item_tree(EditionedFileId::current_edition(file_id).into()) + .item_tree_stats() + .into(); dep_loc += length; - dep_item_trees += 1 + dep_item_trees += 1; + dep_item_stats += item_stats; } } } @@ -161,11 +173,13 @@ impl flags::AnalysisStats { UsizeWithUnderscore(dep_loc), UsizeWithUnderscore(dep_item_trees), ); + eprintln!(" dependency item stats: {}", dep_item_stats); eprintln!( " workspace lines of code: {}, item trees: {}", UsizeWithUnderscore(workspace_loc), UsizeWithUnderscore(workspace_item_trees), ); + eprintln!(" workspace stats: {}", workspace_item_stats); // FIXME(salsa-transition): bring back stats for ParseQuery (file size) // and ParseMacroExpansionQuery (macro expansion "file") size whenever we implement @@ -1258,6 +1272,7 @@ fn percentage(n: u64, total: u64) -> u64 { (n * 100).checked_div(total).unwrap_or(100) } +#[derive(Default, Debug, Eq, PartialEq)] struct UsizeWithUnderscore(usize); impl fmt::Display for UsizeWithUnderscore { @@ -1282,6 +1297,53 @@ impl fmt::Display for UsizeWithUnderscore { } } +impl std::ops::AddAssign for UsizeWithUnderscore { + fn add_assign(&mut self, other: UsizeWithUnderscore) { + self.0 += other.0; + } +} + +#[derive(Default, Debug, Eq, PartialEq)] +struct PrettyItemStats { + traits: UsizeWithUnderscore, + impls: UsizeWithUnderscore, + mods: UsizeWithUnderscore, + macro_calls: UsizeWithUnderscore, + macro_rules: UsizeWithUnderscore, +} + +impl From for PrettyItemStats { + fn from(value: hir_def::item_tree::ItemTreeDataStats) -> Self { + Self { + traits: UsizeWithUnderscore(value.traits), + impls: UsizeWithUnderscore(value.impls), + mods: UsizeWithUnderscore(value.mods), + macro_calls: UsizeWithUnderscore(value.macro_calls), + macro_rules: UsizeWithUnderscore(value.macro_rules), + } + } +} + +impl AddAssign for PrettyItemStats { + fn add_assign(&mut self, rhs: Self) { + self.traits += rhs.traits; + self.impls += rhs.impls; + self.mods += rhs.mods; + self.macro_calls += rhs.macro_calls; + self.macro_rules += rhs.macro_rules; + } +} + +impl fmt::Display for PrettyItemStats { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "traits: {}, impl: {}, mods: {}, macro calls: {}, macro rules: {}", + self.traits, self.impls, self.mods, self.macro_calls, self.macro_rules + ) + } +} + // FIXME(salsa-transition): bring this back whenever we implement // Salsa's memory usage tracking to work with tracked functions. // fn syntax_len(node: SyntaxNode) -> usize { From a6e4d0308632f09c1041454a82d16527222e4b32 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 23 Mar 2025 22:37:48 +0000 Subject: [PATCH 0270/2248] Test Command::current_dir with verbatim path --- .../process/win-command-curdir-no-verbatim.rs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/ui/process/win-command-curdir-no-verbatim.rs diff --git a/tests/ui/process/win-command-curdir-no-verbatim.rs b/tests/ui/process/win-command-curdir-no-verbatim.rs new file mode 100644 index 0000000000000..99943e1c8abc2 --- /dev/null +++ b/tests/ui/process/win-command-curdir-no-verbatim.rs @@ -0,0 +1,36 @@ +// Test that windows verbatim paths in `Command::current_dir` are converted to +// non-verbatim paths before passing to the subprocess. + +//@ run-pass +//@ only-windows +//@ needs-subprocess + +use std::env; +use std::process::Command; + +fn main() { + if env::args().skip(1).any(|s| s == "--child") { + child(); + } else { + parent(); + } +} + +fn parent() { + let exe = env::current_exe().unwrap(); + let dir = env::current_dir().unwrap(); + let status = Command::new(&exe) + .arg("--child") + .current_dir(dir.canonicalize().unwrap()) + .spawn() + .unwrap() + .wait() + .unwrap(); + assert_eq!(status.code(), Some(0)); +} + +fn child() { + let current_dir = env::current_dir().unwrap(); + let current_dir = current_dir.as_os_str().as_encoded_bytes(); + assert!(!current_dir.starts_with(br"\\?\")); +} 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 0271/2248] 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 da97004e7217f88f40c39998e8406ceb383a9243 Mon Sep 17 00:00:00 2001 From: cerdelen Date: Mon, 24 Mar 2025 16:58:04 +0100 Subject: [PATCH 0272/2248] Multiple return statements doesnt decrease cognitive complexity level multiple times --- clippy_lints/src/cognitive_complexity.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index a1ff20dee721f..1d44c7e9c88b0 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -62,6 +62,7 @@ impl CognitiveComplexity { let mut cc = 1u64; let mut returns = 0u64; + let mut prev_expr: Option<&ExprKind<'tcx>> = None; let _: Option = for_each_expr_without_closures(expr, |e| { match e.kind { ExprKind::If(_, _, _) => { @@ -73,9 +74,14 @@ impl CognitiveComplexity { } cc += arms.iter().filter(|arm| arm.guard.is_some()).count() as u64; }, - ExprKind::Ret(_) => returns += 1, + ExprKind::Ret(_) => { + if !matches!(prev_expr, Some(ExprKind::Ret(_))) { + returns += 1; + } + }, _ => {}, } + prev_expr = Some(&e.kind); ControlFlow::Continue(()) }); From c123adf860b008f703b325d013e7c7c0cc707d56 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 15:57:07 -0500 Subject: [PATCH 0273/2248] 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 0add1a492f12bae00e1bae7afc5b32f5c670e13b Mon Sep 17 00:00:00 2001 From: David Barsky Date: Mon, 24 Mar 2025 12:30:41 -0700 Subject: [PATCH 0274/2248] analysis-stats: redesign printing of item tree stats --- .../rust-analyzer/src/cli/analysis_stats.rs | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index ec232d8e85c36..66334e7738149 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -167,19 +167,12 @@ impl flags::AnalysisStats { eprintln!(" item trees: {workspace_item_trees}"); let item_tree_time = item_tree_sw.elapsed(); - eprintln!("Source stats:"); eprintln!( " dependency lines of code: {}, item trees: {}", UsizeWithUnderscore(dep_loc), UsizeWithUnderscore(dep_item_trees), ); eprintln!(" dependency item stats: {}", dep_item_stats); - eprintln!( - " workspace lines of code: {}, item trees: {}", - UsizeWithUnderscore(workspace_loc), - UsizeWithUnderscore(workspace_item_trees), - ); - eprintln!(" workspace stats: {}", workspace_item_stats); // FIXME(salsa-transition): bring back stats for ParseQuery (file size) // and ParseMacroExpansionQuery (macro expansion "file") size whenever we implement @@ -197,8 +190,9 @@ impl flags::AnalysisStats { // } // eprintln!("source files: {total_file_size}, macro files: {total_macro_file_size}"); - eprintln!("{:<20} {}", "Item Tree Collection (workspace):", item_tree_time); + eprintln!("{:<20} {}", "Item Tree Collection:", item_tree_time); report_metric("item tree time", item_tree_time.time.as_millis() as u64, "ms"); + eprintln!(" Total Statistics:"); let mut crate_def_map_sw = self.stop_watch(); let mut num_crates = 0; @@ -221,7 +215,7 @@ impl flags::AnalysisStats { shuffle(&mut rng, &mut visit_queue); } - eprint!(" crates: {num_crates}"); + eprint!(" crates: {num_crates}"); let mut num_decls = 0; let mut bodies = Vec::new(); let mut adts = Vec::new(); @@ -279,7 +273,7 @@ impl flags::AnalysisStats { } } eprintln!( - ", mods: {}, decls: {num_decls}, bodies: {}, adts: {}, consts: {},", + ", mods: {}, decls: {num_decls}, bodies: {}, adts: {}, consts: {}", visited_modules.len(), bodies.len(), adts.len(), @@ -288,7 +282,25 @@ impl flags::AnalysisStats { .filter(|it| matches!(it, DefWithBody::Const(_) | DefWithBody::Static(_))) .count(), ); - eprintln!(" traits: {num_traits}, macro_rules macros: {num_macro_rules_macros}, proc_macros: {num_proc_macros}"); + + eprintln!(" Workspace:"); + eprintln!( + " traits: {num_traits}, macro_rules macros: {num_macro_rules_macros}, proc_macros: {num_proc_macros}" + ); + eprintln!( + " lines of code: {}, item trees: {}", + UsizeWithUnderscore(workspace_loc), + UsizeWithUnderscore(workspace_item_trees), + ); + eprintln!(" usages: {}", workspace_item_stats); + + eprintln!(" Dependencies:"); + eprintln!( + " lines of code: {}, item trees: {}", + UsizeWithUnderscore(dep_loc), + UsizeWithUnderscore(dep_item_trees), + ); + eprintln!(" declarations: {}", dep_item_stats); let crate_def_map_time = crate_def_map_sw.elapsed(); eprintln!("{:<20} {}", "Item Collection:", crate_def_map_time); From ccd95ac7fde43d6a0380895086efca3a75e1ac35 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 16:19:05 -0500 Subject: [PATCH 0275/2248] 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 59e5920e298d7690d455b13adf31b11485b25dcd Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Wed, 5 Mar 2025 15:28:38 -0800 Subject: [PATCH 0276/2248] Reject test executables when not supported by target Currently, compiling tests for SOLID produces an ICE, because SOLID does not support executables. --- compiler/rustc_session/src/output.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index b37a80274c0cb..2b7420cb1b27e 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -177,6 +177,13 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Date: Mon, 24 Mar 2025 16:56:55 -0500 Subject: [PATCH 0277/2248] 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 0278/2248] 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 f9770e742ad3853d2a472e422b00cdbe8578faae Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 24 Mar 2025 21:55:14 +0100 Subject: [PATCH 0279/2248] Test linking and running no_std binaries --- tests/ui/no_std/simple-runs.rs | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/ui/no_std/simple-runs.rs diff --git a/tests/ui/no_std/simple-runs.rs b/tests/ui/no_std/simple-runs.rs new file mode 100644 index 0000000000000..8931ac7ed11be --- /dev/null +++ b/tests/ui/no_std/simple-runs.rs @@ -0,0 +1,41 @@ +//! Check that `no_std` binaries can link and run without depending on `libstd`. + +//@ run-pass +//@ compile-flags: -Cpanic=abort +//@ ignore-wasm different `main` convention + +#![no_std] +#![no_main] + +use core::ffi::{c_char, c_int}; +use core::panic::PanicInfo; + +// # Linux +// +// Linking `libc` is required by crt1.o, otherwise the linker fails with: +// > /usr/bin/ld: in function `_start': undefined reference to `__libc_start_main' +// +// # Apple +// +// Linking `libSystem` is required, otherwise the linker fails with: +// > ld: dynamic executables or dylibs must link with libSystem.dylib +// +// With the new linker introduced in Xcode 15, the error is instead: +// > Undefined symbols: "dyld_stub_binder", referenced from: +// +// This _can_ be worked around by raising the deployment target with +// MACOSX_DEPLOYMENT_TARGET=13.0, though it's a bit hard to test that while +// still allowing the test suite to support running with older Xcode versions. +#[cfg_attr(all(not(target_vendor = "apple"), unix), link(name = "c"))] +#[cfg_attr(target_vendor = "apple", link(name = "System"))] +extern "C" {} + +#[panic_handler] +fn panic_handler(_info: &PanicInfo<'_>) -> ! { + loop {} +} + +#[no_mangle] +extern "C" fn main(_argc: c_int, _argv: *const *const c_char) -> c_int { + 0 +} From 1af16cd135dd4e62f8e68abfb0587b57eb16ce6e Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 17:31:39 -0500 Subject: [PATCH 0280/2248] 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 0281/2248] 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 0282/2248] 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 0283/2248] 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 0284/2248] 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 0285/2248] 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 0286/2248] 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 0287/2248] 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 0288/2248] 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 f9307c137041e275dcdc002a8e0ba58673942adc Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 25 Mar 2025 07:06:12 +0100 Subject: [PATCH 0289/2248] ci: run `intern` tests via `cargo miri` --- .../rust-analyzer/.github/workflows/ci.yaml | 22 ++++++++++++++++++- .../rust-analyzer/crates/intern/Cargo.toml | 1 - 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index 645b596f97f73..07ff5aacec139 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -143,13 +143,33 @@ jobs: run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats --with-deps --no-sysroot --no-test $(rustc --print sysroot)/lib/rustlib/src/rust/library/ - name: clippy - if: matrix.os == 'windows-latest' + if: matrix.os == 'macos-latest' run: cargo clippy --all-targets -- -D clippy::disallowed_macros -D clippy::dbg_macro -D clippy::todo -D clippy::print_stdout -D clippy::print_stderr - name: rustfmt if: matrix.os == 'ubuntu-latest' run: cargo fmt -- --check + # Weird targets to catch non-portable code + miri: + if: github.repository == 'rust-lang/rust-analyzer' + name: miri + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Rust toolchain + run: | + rustup update --no-self-update nightly + rustup component add miri --toolchain nightly + + - name: Cache Dependencies + uses: Swatinem/rust-cache@9bdad043e88c75890e36ad3bbc8d27f0090dd609 + + - run: cargo +nightly miri test --locked + # Weird targets to catch non-portable code rust-cross: if: github.repository == 'rust-lang/rust-analyzer' diff --git a/src/tools/rust-analyzer/crates/intern/Cargo.toml b/src/tools/rust-analyzer/crates/intern/Cargo.toml index 397eba0929673..9ff656cb744e4 100644 --- a/src/tools/rust-analyzer/crates/intern/Cargo.toml +++ b/src/tools/rust-analyzer/crates/intern/Cargo.toml @@ -13,7 +13,6 @@ rust-version.workspace = true [dependencies] -# We need to freeze the version of the crate, as the raw-api feature is considered unstable dashmap.workspace = true hashbrown.workspace = true rustc-hash.workspace = true From a4cead3a343990e85b1a00c0a68073a7e492e688 Mon Sep 17 00:00:00 2001 From: Hegui Dai Date: Tue, 25 Mar 2025 14:31:28 +0800 Subject: [PATCH 0290/2248] add more completion about "impl" --- .../src/completions/item_list.rs | 4 ++ .../ide-completion/src/completions/keyword.rs | 2 + .../ide-completion/src/tests/expression.rs | 68 +++++++++++++------ .../crates/ide-completion/src/tests/item.rs | 2 + .../ide-completion/src/tests/item_list.rs | 10 +++ .../ide-completion/src/tests/special.rs | 12 +++- 6 files changed, 76 insertions(+), 22 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs index 4ae00ccd81bc6..30ffeff2614a7 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs @@ -114,6 +114,8 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option add_keyword("trait", "trait $1 {\n $0\n}"); if no_vis_qualifiers { add_keyword("impl", "impl $1 {\n $0\n}"); + add_keyword("impl for", "impl $1 for $2 {\n $0\n}"); + add_keyword("impl<> for <>", "impl<$4> $1 for $2<$3> {\n $0\n}"); } } @@ -144,6 +146,8 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option add_keyword("use", "use $0"); if no_vis_qualifiers { add_keyword("impl", "impl $1 {\n $0\n}"); + add_keyword("impl for", "impl $1 for $2 {\n $0\n}"); + add_keyword("impl<> for <>", "impl<$4> $1 for $2<$3> {\n $0\n}"); } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs index 14b0d543ca355..d0ba910d93540 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs @@ -56,6 +56,8 @@ mod tests { kw extern kw fn kw impl + kw impl for + kw impl<> for <> kw trait "#]], ); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index 22d42ba750ed1..5314be3c7fc38 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -171,6 +171,8 @@ impl Unit { kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -236,8 +238,8 @@ fn complete_in_block() { } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -249,6 +251,8 @@ fn complete_in_block() { kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -285,8 +289,8 @@ fn complete_after_if_expr() { } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -300,6 +304,8 @@ fn complete_after_if_expr() { kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -360,8 +366,8 @@ fn completes_in_loop_ctx() { check( r"fn my() { loop { $0 } }", expect![[r#" - fn my() fn() - bt u32 u32 + fn my() fn() + bt u32 u32 kw async kw break kw const @@ -375,6 +381,8 @@ fn completes_in_loop_ctx() { kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -946,8 +954,8 @@ fn else_completion_after_if() { fn foo() { if foo {} $0 } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -961,6 +969,8 @@ fn foo() { if foo {} $0 } kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -988,8 +998,8 @@ fn foo() { if foo {} $0 } fn foo() { if foo {} el$0 } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -1003,6 +1013,8 @@ fn foo() { if foo {} el$0 } kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -1080,8 +1092,8 @@ fn foo() { bar(if foo {} el$0) } fn foo() { if foo {} $0 let x = 92; } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -1095,6 +1107,8 @@ fn foo() { if foo {} $0 let x = 92; } kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -1122,8 +1136,8 @@ fn foo() { if foo {} $0 let x = 92; } fn foo() { if foo {} el$0 let x = 92; } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -1137,6 +1151,8 @@ fn foo() { if foo {} el$0 let x = 92; } kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -1164,8 +1180,8 @@ fn foo() { if foo {} el$0 let x = 92; } fn foo() { if foo {} el$0 { let x = 92; } } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -1179,6 +1195,8 @@ fn foo() { if foo {} el$0 { let x = 92; } } kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -1217,9 +1235,9 @@ fn main() { pub struct UnstableThisShouldNotBeListed; "#, expect![[r#" - fn main() fn() + fn main() fn() md std - bt u32 u32 + bt u32 u32 kw async kw const kw crate:: @@ -1231,6 +1249,8 @@ pub struct UnstableThisShouldNotBeListed; kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -1285,6 +1305,8 @@ pub struct UnstableButWeAreOnNightlyAnyway; kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -1529,6 +1551,8 @@ fn main() { kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -1986,6 +2010,8 @@ fn bar() { kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -2044,9 +2070,9 @@ fn foo() { } "#, expect![[r#" - fn foo() fn() + fn foo() fn() md proc_macros - bt u32 u32 + bt u32 u32 kw async kw const kw crate:: @@ -2058,6 +2084,8 @@ fn foo() { kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs index be2c37d10162e..a2d2cf39c2df7 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs @@ -284,6 +284,8 @@ fn bar() { kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs index 841c42123a017..ee77845588320 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs @@ -16,6 +16,8 @@ fn in_mod_item_list() { kw extern kw fn kw impl + kw impl for + kw impl<> for <> kw mod kw pub kw pub(crate) @@ -50,6 +52,8 @@ fn in_source_file_item_list() { kw extern kw fn kw impl + kw impl for + kw impl<> for <> kw mod kw pub kw pub(crate) @@ -83,6 +87,8 @@ fn in_item_list_after_attr() { kw extern kw fn kw impl + kw impl for + kw impl<> for <> kw mod kw pub kw pub(crate) @@ -122,6 +128,8 @@ fn after_unsafe_token() { kw extern kw fn kw impl + kw impl for + kw impl<> for <> kw trait "#]], ); @@ -385,6 +393,8 @@ fn after_unit_struct() { kw extern kw fn kw impl + kw impl for + kw impl<> for <> kw mod kw pub kw pub(crate) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs index 70caeac95b6bc..ca579b8fc1e69 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -1008,6 +1008,8 @@ fn here_we_go() { kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -1059,6 +1061,8 @@ fn here_we_go() { kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -1184,6 +1188,8 @@ fn bar() { qu$0 } kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop @@ -1428,8 +1434,8 @@ fn foo() { "#, Some('_'), expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -1441,6 +1447,8 @@ fn foo() { kw if kw if let kw impl + kw impl for + kw impl<> for <> kw let kw letm kw loop From 8d076eca0174b64ba156def68b783b2f67291944 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 25 Mar 2025 07:06:12 +0100 Subject: [PATCH 0291/2248] ci: Require miri step --- src/tools/rust-analyzer/.github/workflows/ci.yaml | 10 +++++++--- .../rust-analyzer/crates/hir-ty/src/infer/closure.rs | 2 +- .../crates/project-model/src/build_dependencies.rs | 6 +----- src/tools/rust-analyzer/xtask/src/tidy.rs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index 07ff5aacec139..8479d006319fa 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -15,7 +15,6 @@ env: CARGO_NET_RETRY: 10 CI: 1 RUST_BACKTRACE: short - RUSTFLAGS: "-D warnings" RUSTUP_MAX_RETRIES: 10 jobs: @@ -45,6 +44,9 @@ jobs: if: github.repository == 'rust-lang/rust-analyzer' && needs.changes.outputs.proc_macros == 'true' name: proc-macro-srv runs-on: ubuntu-latest + env: + RUSTFLAGS: "-D warnings" + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -73,6 +75,7 @@ jobs: name: Rust runs-on: ${{ matrix.os }} env: + RUSTFLAGS: "-D warnings" CC: deny_c strategy: @@ -168,7 +171,7 @@ jobs: - name: Cache Dependencies uses: Swatinem/rust-cache@9bdad043e88c75890e36ad3bbc8d27f0090dd609 - - run: cargo +nightly miri test --locked + - run: cargo +nightly miri test -p intern --locked # Weird targets to catch non-portable code rust-cross: @@ -181,6 +184,7 @@ jobs: # The rust-analyzer binary is not expected to compile on WASM, but the IDE # crate should targets_ide: "wasm32-unknown-unknown" + RUSTFLAGS: "-D warnings" steps: - name: Checkout repository @@ -283,7 +287,7 @@ jobs: run: typos conclusion: - needs: [rust, rust-cross, typescript, typo-check, proc-macro-srv] + needs: [rust, rust-cross, typescript, typo-check, proc-macro-srv, miri] # We need to ensure this job does *not* get skipped if its dependencies fail, # because a skipped job is considered a success by GitHub. So we have to # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index 69de555214d2b..731b7f5e0286f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -223,7 +223,7 @@ impl HirPlace { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow, }) = current_capture { - if self.projections[len..].iter().any(|it| *it == ProjectionElem::Deref) { + if self.projections[len..].contains(&ProjectionElem::Deref) { current_capture = CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }); } diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs index 631787bf8e6fa..b26d19e326892 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs @@ -343,11 +343,7 @@ impl WorkspaceBuildScripts { Message::CompilerArtifact(message) => { with_output_for(&message.package_id.repr, &mut |name, data| { progress(format!("building proc-macros: {name}")); - if message - .target - .kind - .iter() - .any(|k| *k == cargo_metadata::TargetKind::ProcMacro) + if message.target.kind.contains(&cargo_metadata::TargetKind::ProcMacro) { // Skip rmeta file if let Some(filename) = diff --git a/src/tools/rust-analyzer/xtask/src/tidy.rs b/src/tools/rust-analyzer/xtask/src/tidy.rs index bf51760de17ab..343f76f6475e1 100644 --- a/src/tools/rust-analyzer/xtask/src/tidy.rs +++ b/src/tools/rust-analyzer/xtask/src/tidy.rs @@ -254,7 +254,7 @@ impl TidyDocs { d.file_name() .unwrap_or_default() .to_str() - .map(|f_n| file_names.iter().any(|name| *name == f_n)) + .map(|f_n| file_names.contains(&f_n)) .unwrap_or(false) } } From d85bffdba4f8cb1211c825e3ecc818e9348007e0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 18 Mar 2025 07:11:34 +0100 Subject: [PATCH 0292/2248] feat: parse `unsafe` record fields --- .../rust-analyzer/crates/hir-def/src/data/adt.rs | 6 ++++-- .../rust-analyzer/crates/hir-def/src/item_tree.rs | 1 + .../crates/hir-def/src/item_tree/lower.rs | 4 ++-- .../crates/hir-def/src/item_tree/pretty.rs | 14 ++++++++++++-- .../crates/parser/src/grammar/items/adt.rs | 3 ++- .../parser/inline/ok/record_field_list.rast | 14 ++++++++++++++ .../parser/inline/ok/record_field_list.rs | 2 +- src/tools/rust-analyzer/crates/syntax/rust.ungram | 2 +- .../crates/syntax/src/ast/generated/nodes.rs | 2 ++ 9 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index 8ea79406531de..e470fe689b914 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -171,6 +171,7 @@ pub struct FieldData { pub name: Name, pub type_ref: TypeRefId, pub visibility: RawVisibility, + pub is_unsafe: bool, } fn repr_from_value( @@ -329,14 +330,14 @@ impl EnumVariantData { impl VariantData { pub fn fields(&self) -> &Arena { const EMPTY: &Arena = &Arena::new(); - match &self { + match self { VariantData::Record { fields, .. } | VariantData::Tuple { fields, .. } => fields, _ => EMPTY, } } pub fn types_map(&self) -> &TypesMap { - match &self { + match self { VariantData::Record { types_map, .. } | VariantData::Tuple { types_map, .. } => { types_map } @@ -405,5 +406,6 @@ fn lower_field( name: field.name.clone(), type_ref: field.type_ref, visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), + is_unsafe: field.is_unsafe, } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 2debbb1ee4e35..80d666a0aba10 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -1032,6 +1032,7 @@ pub struct Field { pub name: Name, pub type_ref: TypeRefId, pub visibility: RawVisibilityId, + pub is_unsafe: bool, } #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 6866821420529..5389ba49c577f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -320,7 +320,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(field); let type_ref = TypeRef::from_ast_opt(body_ctx, field.ty()); - Field { name, type_ref, visibility } + Field { name, type_ref, visibility, is_unsafe: field.unsafe_token().is_some() } } fn lower_tuple_field( @@ -332,7 +332,7 @@ impl<'a> Ctx<'a> { let name = Name::new_tuple_field(idx); let visibility = self.lower_visibility(field); let type_ref = TypeRef::from_ast_opt(body_ctx, field.ty()); - Field { name, type_ref, visibility } + Field { name, type_ref, visibility, is_unsafe: false } } fn lower_union(&mut self, union: &ast::Union) -> Option> { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index e666b1ea6bc29..f44a000ac1baf 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -135,12 +135,17 @@ impl Printer<'_> { self.whitespace(); w!(self, "{{"); self.indented(|this| { - for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() { + for (idx, Field { name, type_ref, visibility, is_unsafe }) in + fields.iter().enumerate() + { this.print_attrs_of( AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))), "\n", ); this.print_visibility(*visibility); + if *is_unsafe { + w!(this, "unsafe "); + } w!(this, "{}: ", name.display(self.db.upcast(), edition)); this.print_type_ref(*type_ref, map); wln!(this, ","); @@ -151,12 +156,17 @@ impl Printer<'_> { FieldsShape::Tuple => { w!(self, "("); self.indented(|this| { - for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() { + for (idx, Field { name, type_ref, visibility, is_unsafe }) in + fields.iter().enumerate() + { this.print_attrs_of( AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))), "\n", ); this.print_visibility(*visibility); + if *is_unsafe { + w!(this, "unsafe "); + } w!(this, "{}: ", name.display(self.db.upcast(), edition)); this.print_type_ref(*type_ref, map); wln!(this, ","); diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items/adt.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items/adt.rs index 9a16c9db6daf1..a37569614028a 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/items/adt.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items/adt.rs @@ -107,7 +107,7 @@ pub(crate) fn variant_list(p: &mut Parser<'_>) { } // test record_field_list -// struct S { a: i32, b: f32 } +// struct S { a: i32, b: f32, unsafe c: u8 } pub(crate) fn record_field_list(p: &mut Parser<'_>) { assert!(p.at(T!['{'])); let m = p.start(); @@ -131,6 +131,7 @@ pub(crate) fn record_field_list(p: &mut Parser<'_>) { // struct S { #[attr] f: f32 } attributes::outer_attrs(p); opt_visibility(p, false); + p.eat(T![unsafe]); if p.at(IDENT) { name(p); p.expect(T![:]); diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rast index 065d7e7e81f24..07686f509c1bc 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rast @@ -30,6 +30,20 @@ SOURCE_FILE PATH_SEGMENT NAME_REF IDENT "f32" + COMMA "," + WHITESPACE " " + RECORD_FIELD + UNSAFE_KW "unsafe" + WHITESPACE " " + NAME + IDENT "c" + COLON ":" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "u8" WHITESPACE " " R_CURLY "}" WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rs index a3bd7787db77c..1f4612f53913b 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rs +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rs @@ -1 +1 @@ -struct S { a: i32, b: f32 } +struct S { a: i32, b: f32, unsafe c: u8 } diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram index 70a91af6c4790..673334bd22512 100644 --- a/src/tools/rust-analyzer/crates/syntax/rust.ungram +++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram @@ -240,7 +240,7 @@ RecordFieldList = '{' fields:(RecordField (',' RecordField)* ','?)? '}' RecordField = - Attr* Visibility? + Attr* Visibility? 'unsafe'? Name ':' Type ('=' Expr)? TupleFieldList = diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs index 638b9615ea335..fd23cdccd572e 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs @@ -1337,6 +1337,8 @@ impl RecordField { pub fn colon_token(&self) -> Option { support::token(&self.syntax, T![:]) } #[inline] pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } + #[inline] + pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } } pub struct RecordFieldList { pub(crate) syntax: SyntaxNode, From de8c404ed49e16588d6932b3367b6dd0ef1556a1 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 25 Mar 2025 09:42:06 +0100 Subject: [PATCH 0293/2248] Fix type error in lint description --- clippy_lints/src/casts/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index dc2a1fa85bf5c..4e7641c7d3b11 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -71,7 +71,7 @@ declare_clippy_lint! { /// ### Example /// ```no_run /// let y: i8 = -1; - /// y as u128; // will return 18446744073709551615 + /// y as u64; // will return 18446744073709551615 /// ``` #[clippy::version = "pre 1.29.0"] pub CAST_SIGN_LOSS, From a0f47f070efe585642e2f72eae03aba7e7e004ac Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 25 Mar 2025 09:58:17 +0100 Subject: [PATCH 0294/2248] minor: Simplify impl-ty parse validation --- .../crates/syntax/src/validation.rs | 123 ++++++++++-------- .../parser/validation/dangling_impl.rast | 2 +- .../validation/dangling_impl_reference.rast | 2 +- .../validation/impl_trait_lifetime_only.rast | 2 +- 4 files changed, 74 insertions(+), 55 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index 12894a2bda8f7..6397b04481fd1 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -4,6 +4,7 @@ mod block; +use itertools::Itertools; use rowan::Direction; use rustc_lexer::unescape::{self, Mode, unescape_mixed, unescape_unicode}; @@ -37,7 +38,8 @@ pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec) { ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, errors), ast::MacroRules(it) => validate_macro_rules(it, errors), ast::LetExpr(it) => validate_let_expr(it, errors), - ast::ImplTraitType(it) => validate_impl_object_ty(it, errors), + ast::DynTraitType(it) => errors.extend(validate_trait_object_ty(it)), + ast::ImplTraitType(it) => errors.extend(validate_impl_object_ty(it)), _ => (), } } @@ -316,87 +318,104 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec) { - if let Some(ast::Type::DynTraitType(ty)) = ty.ty() { - if let Some(err) = validate_trait_object_ty(ty) { - errors.push(err); + match ty.ty() { + Some(ast::Type::DynTraitType(ty)) => { + if let Some(err) = validate_trait_object_ty_plus(ty) { + errors.push(err); + } + } + Some(ast::Type::ImplTraitType(ty)) => { + if let Some(err) = validate_impl_object_ty_plus(ty) { + errors.push(err); + } } + _ => (), } } fn validate_trait_object_ptr_ty(ty: ast::PtrType, errors: &mut Vec) { - if let Some(ast::Type::DynTraitType(ty)) = ty.ty() { - if let Some(err) = validate_trait_object_ty(ty) { - errors.push(err); + match ty.ty() { + Some(ast::Type::DynTraitType(ty)) => { + if let Some(err) = validate_trait_object_ty_plus(ty) { + errors.push(err); + } } + Some(ast::Type::ImplTraitType(ty)) => { + if let Some(err) = validate_impl_object_ty_plus(ty) { + errors.push(err); + } + } + _ => (), } } fn validate_trait_object_fn_ptr_ret_ty(ty: ast::FnPtrType, errors: &mut Vec) { - if let Some(ast::Type::DynTraitType(ty)) = ty.ret_type().and_then(|ty| ty.ty()) { - if let Some(err) = validate_trait_object_ty(ty) { - errors.push(err); + match ty.ret_type().and_then(|ty| ty.ty()) { + Some(ast::Type::DynTraitType(ty)) => { + if let Some(err) = validate_trait_object_ty_plus(ty) { + errors.push(err); + } + } + Some(ast::Type::ImplTraitType(ty)) => { + if let Some(err) = validate_impl_object_ty_plus(ty) { + errors.push(err); + } } + _ => (), } } fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option { let tbl = ty.type_bound_list()?; - let bounds_count = tbl.bounds().count(); + let no_bounds = tbl.bounds().filter_map(|it| it.ty()).next().is_none(); - match bounds_count { - 0 => Some(SyntaxError::new( + match no_bounds { + true => Some(SyntaxError::new( "At least one trait is required for an object type", ty.syntax().text_range(), )), - _ if bounds_count > 1 => { - let dyn_token = ty.dyn_token()?; - let preceding_token = - algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?; - - if !matches!(preceding_token.kind(), T!['('] | T![<] | T![=]) { - return Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())); - } - None - } - _ => None, + false => None, } } -fn validate_impl_object_ty(ty: ast::ImplTraitType, errors: &mut Vec) { - let Some(bound_list) = ty.type_bound_list() else { - errors.push(SyntaxError::new( - "At least one trait must be specified", - ty.syntax().text_range(), - )); - return; - }; - - let bounds: Vec<_> = bound_list.bounds().collect(); +fn validate_impl_object_ty(ty: ast::ImplTraitType) -> Option { + let tbl = ty.type_bound_list()?; + let no_bounds = tbl.bounds().filter_map(|it| it.ty()).next().is_none(); - if !bounds.iter().any(|b| !matches!(b.kind(), ast::TypeBoundKind::Lifetime(_))) { - errors.push(SyntaxError::new( - "At least one trait must be specified", + match no_bounds { + true => Some(SyntaxError::new( + "At least one trait is required for an object type", ty.syntax().text_range(), - )); - return; + )), + false => None, } +} - if bounds.len() == 1 { - return; +// FIXME: This is not a validation error, this is a context dependent parse error +fn validate_trait_object_ty_plus(ty: ast::DynTraitType) -> Option { + let dyn_token = ty.dyn_token()?; + let preceding_token = algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?; + let tbl = ty.type_bound_list()?; + let more_than_one_bound = tbl.bounds().next_tuple::<(_, _)>().is_some(); + + if more_than_one_bound && !matches!(preceding_token.kind(), T!['('] | T![<] | T![=]) { + Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())) + } else { + None } +} - let Some(preceding_token) = ty - .impl_token() - .and_then(|token| token.prev_token()) - .and_then(|prev| algo::skip_trivia_token(prev, Direction::Prev)) - else { - return; - }; +// FIXME: This is not a validation error, this is a context dependent parse error +fn validate_impl_object_ty_plus(ty: ast::ImplTraitType) -> Option { + let dyn_token = ty.impl_token()?; + let preceding_token = algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?; + let tbl = ty.type_bound_list()?; + let more_than_one_bound = tbl.bounds().next_tuple::<(_, _)>().is_some(); - if !matches!(preceding_token.kind(), T!['('] | T![<] | T![=]) - && matches!(preceding_token.kind(), T![&]) - { - errors.push(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())); + if more_than_one_bound && !matches!(preceding_token.kind(), T!['('] | T![<] | T![=]) { + Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())) + } else { + None } } diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast index 2db07ae12a98e..c337ee8bbf4cf 100644 --- a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast @@ -20,4 +20,4 @@ SOURCE_FILE@0..16 STMT_LIST@14..16 L_CURLY@14..15 "{" R_CURLY@15..16 "}" -error 8..12: At least one trait must be specified +error 8..12: At least one trait is required for an object type diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast index dbe6535ac665b..cb73cb4e058b8 100644 --- a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast @@ -22,4 +22,4 @@ SOURCE_FILE@0..17 STMT_LIST@15..17 L_CURLY@15..16 "{" R_CURLY@16..17 "}" -error 9..13: At least one trait must be specified +error 9..13: At least one trait is required for an object type diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast index 98aa862bc889c..ed938d63db449 100644 --- a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast @@ -26,4 +26,4 @@ SOURCE_FILE@0..20 STMT_LIST@18..20 L_CURLY@18..19 "{" R_CURLY@19..20 "}" -error 9..16: At least one trait must be specified +error 9..16: At least one trait is required for an object type From b7cbb4ec8c3ca8434632bd9ff7025649fca1c21e Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 25 Mar 2025 11:16:31 +0100 Subject: [PATCH 0295/2248] Add myself to reviewer rotation --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 33d3b0728f3d1..4b0ad0fb6bbc0 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -34,4 +34,5 @@ users_on_vacation = [ "@Jarcho", "@blyxyas", "@y21", + "@samueltardieu", ] From 8524a7c4b7faab823f7e03d012b365bb05b82654 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 25 Mar 2025 10:31:05 +0000 Subject: [PATCH 0296/2248] 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 e78216c4a14c4590a0efa3deba7f9ed08e1d0b31 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Thu, 6 Mar 2025 13:44:23 +0900 Subject: [PATCH 0297/2248] suggest `is_some_and` instead of `map_or` in `case_sensitive_file_extension_comparions` --- ...se_sensitive_file_extension_comparisons.rs | 14 +++++-- clippy_lints/src/methods/mod.rs | 2 +- ...sensitive_file_extension_comparisons.fixed | 21 ++++++---- ...se_sensitive_file_extension_comparisons.rs | 7 +++- ...ensitive_file_extension_comparisons.stderr | 40 +++++++++++++------ 5 files changed, 58 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index 18568e3661fe5..1c745b7376ea4 100644 --- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{SpanRangeExt, indent_of, reindent_multiline}; use clippy_utils::ty::is_type_lang_item; use rustc_ast::ast::LitKind; @@ -16,6 +17,7 @@ pub(super) fn check<'tcx>( call_span: Span, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>, + msrv: Msrv, ) { if let ExprKind::MethodCall(path_segment, ..) = recv.kind { if matches!( @@ -58,11 +60,15 @@ pub(super) fn check<'tcx>( let suggestion_source = reindent_multiline( &format!( - "std::path::Path::new({}) + "std::path::Path::new({recv_source}) .extension() - .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))", - recv_source, - ext_str.strip_prefix('.').unwrap() + .{}|ext| ext.eq_ignore_ascii_case(\"{}\"))", + if msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND) { + "is_some_and(" + } else { + "map_or(false, " + }, + ext_str.strip_prefix('.').unwrap(), ), true, Some(indent_of(cx, call_span).unwrap_or(0) + 4), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 94d3657d9f123..f17bf6d636622 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4992,7 +4992,7 @@ impl Methods { }, ("ends_with", [arg]) => { if let ExprKind::MethodCall(.., span) = expr.kind { - case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg); + case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg, self.msrv); } path_ends_with_ext::check(cx, recv, arg, expr, self.msrv, &self.allowed_dotfiles); }, diff --git a/tests/ui/case_sensitive_file_extension_comparisons.fixed b/tests/ui/case_sensitive_file_extension_comparisons.fixed index bf7635fdf09bf..0c9d21243546d 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.fixed +++ b/tests/ui/case_sensitive_file_extension_comparisons.fixed @@ -1,5 +1,4 @@ #![warn(clippy::case_sensitive_file_extension_comparisons)] -#![allow(clippy::unnecessary_map_or)] use std::string::String; @@ -13,7 +12,7 @@ impl TestStruct { fn is_rust_file(filename: &str) -> bool { std::path::Path::new(filename) .extension() - .map_or(false, |ext| ext.eq_ignore_ascii_case("rs")) + .is_some_and(|ext| ext.eq_ignore_ascii_case("rs")) //~^ case_sensitive_file_extension_comparisons } @@ -21,18 +20,18 @@ fn main() { // std::string::String and &str should trigger the lint failure with .ext12 let _ = std::path::Path::new(&String::new()) .extension() - .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12")); //~^ case_sensitive_file_extension_comparisons let _ = std::path::Path::new("str") .extension() - .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12")); //~^ case_sensitive_file_extension_comparisons // The fixup should preserve the indentation level { let _ = std::path::Path::new("str") .extension() - .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12")); //~^ case_sensitive_file_extension_comparisons } @@ -42,11 +41,11 @@ fn main() { // std::string::String and &str should trigger the lint failure with .EXT12 let _ = std::path::Path::new(&String::new()) .extension() - .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + .is_some_and(|ext| ext.eq_ignore_ascii_case("EXT12")); //~^ case_sensitive_file_extension_comparisons let _ = std::path::Path::new("str") .extension() - .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + .is_some_and(|ext| ext.eq_ignore_ascii_case("EXT12")); //~^ case_sensitive_file_extension_comparisons // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase @@ -76,3 +75,11 @@ fn main() { let _ = "str".ends_with(".123"); TestStruct {}.ends_with(".123"); } + +#[clippy::msrv = "1.69"] +fn msrv_check() { + let _ = std::path::Path::new(&String::new()) + .extension() + .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + //~^ case_sensitive_file_extension_comparisons +} diff --git a/tests/ui/case_sensitive_file_extension_comparisons.rs b/tests/ui/case_sensitive_file_extension_comparisons.rs index 0c4070a42d4b0..f8a947aa827b9 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.rs +++ b/tests/ui/case_sensitive_file_extension_comparisons.rs @@ -1,5 +1,4 @@ #![warn(clippy::case_sensitive_file_extension_comparisons)] -#![allow(clippy::unnecessary_map_or)] use std::string::String; @@ -64,3 +63,9 @@ fn main() { let _ = "str".ends_with(".123"); TestStruct {}.ends_with(".123"); } + +#[clippy::msrv = "1.69"] +fn msrv_check() { + let _ = String::new().ends_with(".ext12"); + //~^ case_sensitive_file_extension_comparisons +} diff --git a/tests/ui/case_sensitive_file_extension_comparisons.stderr b/tests/ui/case_sensitive_file_extension_comparisons.stderr index e035534d26996..93bee8e766719 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.stderr +++ b/tests/ui/case_sensitive_file_extension_comparisons.stderr @@ -1,5 +1,5 @@ error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:14:5 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:13:5 | LL | filename.ends_with(".rs") | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -11,11 +11,11 @@ help: use std::path::Path | LL ~ std::path::Path::new(filename) LL + .extension() -LL + .map_or(false, |ext| ext.eq_ignore_ascii_case("rs")) +LL + .is_some_and(|ext| ext.eq_ignore_ascii_case("rs")) | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:20:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:19:13 | LL | let _ = String::new().ends_with(".ext12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,11 +25,11 @@ help: use std::path::Path | LL ~ let _ = std::path::Path::new(&String::new()) LL + .extension() -LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); +LL ~ .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:22:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:21:13 | LL | let _ = "str".ends_with(".ext12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,11 +39,11 @@ help: use std::path::Path | LL ~ let _ = std::path::Path::new("str") LL + .extension() -LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); +LL ~ .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:27:17 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:26:17 | LL | let _ = "str".ends_with(".ext12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -53,11 +53,11 @@ help: use std::path::Path | LL ~ let _ = std::path::Path::new("str") LL + .extension() -LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); +LL ~ .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:35:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:34:13 | LL | let _ = String::new().ends_with(".EXT12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,11 +67,11 @@ help: use std::path::Path | LL ~ let _ = std::path::Path::new(&String::new()) LL + .extension() -LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); +LL ~ .is_some_and(|ext| ext.eq_ignore_ascii_case("EXT12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:37:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:36:13 | LL | let _ = "str".ends_with(".EXT12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -81,8 +81,22 @@ help: use std::path::Path | LL ~ let _ = std::path::Path::new("str") LL + .extension() -LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); +LL ~ .is_some_and(|ext| ext.eq_ignore_ascii_case("EXT12")); + | + +error: case-sensitive file extension comparison + --> tests/ui/case_sensitive_file_extension_comparisons.rs:69:13 + | +LL | let _ = String::new().ends_with(".ext12"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using a case-insensitive comparison instead +help: use std::path::Path + | +LL ~ let _ = std::path::Path::new(&String::new()) +LL + .extension() +LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); | -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors From 1d890389ffe885ac2b148113c852a115f35fdb01 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 6 Feb 2025 02:41:20 -0500 Subject: [PATCH 0298/2248] Move `uninlined_format_args` to `style` This lint was downgraded to `pedantic` in part because rust-analyzer was not fully supporting it at the time per #10087. The support has been added over [a year ago](https://github.com/rust-lang/rust-analyzer/issues/11260), so seems like this should be back to style. Another source of the initial frustration was fixed since then as well - this lint does not trigger by default in case only some arguments can be inlined. --- clippy_lints/src/format_args.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 3862ff7921db8..75f0d626f0c4f 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -141,7 +141,7 @@ declare_clippy_lint! { /// format!("{var:.prec$}"); /// ``` /// - /// If allow-mixed-uninlined-format-args is set to false in clippy.toml, + /// If `allow-mixed-uninlined-format-args` is set to `false` in clippy.toml, /// the following code will also trigger the lint: /// ```no_run /// # let var = 42; @@ -159,7 +159,7 @@ declare_clippy_lint! { /// nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`. #[clippy::version = "1.66.0"] pub UNINLINED_FORMAT_ARGS, - pedantic, + style, "using non-inlined variables in `format!` calls" } From d063e09d102591e9b60d7f4cf0e606c41c11b992 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 15 Feb 2025 17:25:56 -0500 Subject: [PATCH 0299/2248] Move `uninlined_format_args` to `style` This lint was downgraded to `pedantic` in part because rust-analyzer was not fully supporting it at the time per #10087. The support has been added over [a year ago](https://github.com/rust-lang/rust-analyzer/issues/11260), so seems like this should be back to style. Another source of the initial frustration was fixed since then as well - this lint does not trigger by default in case only some arguments can be inlined. --- .../index_refutable_slice.fixed | 2 +- .../index_refutable_slice.rs | 2 +- tests/ui/author/macro_in_closure.rs | 1 + tests/ui/author/macro_in_loop.rs | 1 + tests/ui/dbg_macro/dbg_macro.fixed | 2 +- tests/ui/dbg_macro/dbg_macro.rs | 2 +- tests/ui/large_futures.fixed | 2 +- tests/ui/large_futures.rs | 2 +- tests/ui/manual_inspect.fixed | 2 +- tests/ui/manual_inspect.rs | 2 +- tests/ui/needless_pass_by_ref_mut.rs | 4 ++-- tests/ui/to_string_in_format_args_incremental.fixed | 2 +- tests/ui/to_string_in_format_args_incremental.rs | 2 +- tests/ui/unnecessary_iter_cloned.fixed | 2 +- tests/ui/unnecessary_iter_cloned.rs | 2 +- tests/ui/unnecessary_operation.fixed | 2 +- tests/ui/unnecessary_operation.rs | 2 +- tests/ui/unnecessary_to_owned.fixed | 2 +- tests/ui/unnecessary_to_owned.rs | 2 +- 19 files changed, 20 insertions(+), 18 deletions(-) diff --git a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed index 36540bf1dcf73..2d5900094ee73 100644 --- a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed +++ b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed @@ -1,5 +1,5 @@ #![deny(clippy::index_refutable_slice)] - +#![allow(clippy::uninlined_format_args)] fn below_limit() { let slice: Option<&[u32]> = Some(&[1, 2, 3]); if let Some([_, _, _, _, _, _, _, slice_7, ..]) = slice { diff --git a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs index da76bb20fd961..94bd99a452fe2 100644 --- a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs +++ b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs @@ -1,5 +1,5 @@ #![deny(clippy::index_refutable_slice)] - +#![allow(clippy::uninlined_format_args)] fn below_limit() { let slice: Option<&[u32]> = Some(&[1, 2, 3]); if let Some(slice) = slice { diff --git a/tests/ui/author/macro_in_closure.rs b/tests/ui/author/macro_in_closure.rs index 8a02f38fad87b..b6d8e7ecbdd19 100644 --- a/tests/ui/author/macro_in_closure.rs +++ b/tests/ui/author/macro_in_closure.rs @@ -1,4 +1,5 @@ //@ check-pass +#![allow(clippy::uninlined_format_args)] fn main() { #[clippy::author] diff --git a/tests/ui/author/macro_in_loop.rs b/tests/ui/author/macro_in_loop.rs index 84ffe416e839b..f68275fefaaa3 100644 --- a/tests/ui/author/macro_in_loop.rs +++ b/tests/ui/author/macro_in_loop.rs @@ -1,6 +1,7 @@ //@ check-pass #![feature(stmt_expr_attributes)] +#![allow(clippy::uninlined_format_args)] fn main() { #[clippy::author] diff --git a/tests/ui/dbg_macro/dbg_macro.fixed b/tests/ui/dbg_macro/dbg_macro.fixed index fd1a0d8934b3c..8765035e39887 100644 --- a/tests/ui/dbg_macro/dbg_macro.fixed +++ b/tests/ui/dbg_macro/dbg_macro.fixed @@ -1,6 +1,6 @@ #![warn(clippy::dbg_macro)] #![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)] - +#![allow(clippy::uninlined_format_args)] fn foo(n: u32) -> u32 { if let Some(n) = n.checked_sub(4) { n } else { n } //~^ dbg_macro diff --git a/tests/ui/dbg_macro/dbg_macro.rs b/tests/ui/dbg_macro/dbg_macro.rs index c96e2c7251c29..301f17db3169f 100644 --- a/tests/ui/dbg_macro/dbg_macro.rs +++ b/tests/ui/dbg_macro/dbg_macro.rs @@ -1,6 +1,6 @@ #![warn(clippy::dbg_macro)] #![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)] - +#![allow(clippy::uninlined_format_args)] fn foo(n: u32) -> u32 { if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } //~^ dbg_macro diff --git a/tests/ui/large_futures.fixed b/tests/ui/large_futures.fixed index c2159c58de1ec..6b2acaa9ff103 100644 --- a/tests/ui/large_futures.fixed +++ b/tests/ui/large_futures.fixed @@ -1,7 +1,7 @@ #![warn(clippy::large_futures)] #![allow(clippy::never_loop)] #![allow(clippy::future_not_send)] -#![allow(clippy::manual_async_fn)] +#![allow(clippy::manual_async_fn, clippy::uninlined_format_args)] async fn big_fut(_arg: [u8; 1024 * 16]) {} diff --git a/tests/ui/large_futures.rs b/tests/ui/large_futures.rs index 567f6344afeac..6bf1fb87727ad 100644 --- a/tests/ui/large_futures.rs +++ b/tests/ui/large_futures.rs @@ -1,7 +1,7 @@ #![warn(clippy::large_futures)] #![allow(clippy::never_loop)] #![allow(clippy::future_not_send)] -#![allow(clippy::manual_async_fn)] +#![allow(clippy::manual_async_fn, clippy::uninlined_format_args)] async fn big_fut(_arg: [u8; 1024 * 16]) {} diff --git a/tests/ui/manual_inspect.fixed b/tests/ui/manual_inspect.fixed index 44f15d61f8563..1a722cef43401 100644 --- a/tests/ui/manual_inspect.fixed +++ b/tests/ui/manual_inspect.fixed @@ -1,5 +1,5 @@ #![warn(clippy::manual_inspect)] -#![allow(clippy::no_effect, clippy::op_ref)] +#![allow(clippy::no_effect, clippy::op_ref, clippy::uninlined_format_args)] fn main() { let _ = Some(0).inspect(|&x| { diff --git a/tests/ui/manual_inspect.rs b/tests/ui/manual_inspect.rs index d34f2abce6ae1..eaf6b9fa0edf6 100644 --- a/tests/ui/manual_inspect.rs +++ b/tests/ui/manual_inspect.rs @@ -1,5 +1,5 @@ #![warn(clippy::manual_inspect)] -#![allow(clippy::no_effect, clippy::op_ref)] +#![allow(clippy::no_effect, clippy::op_ref, clippy::uninlined_format_args)] fn main() { let _ = Some(0).map(|x| { diff --git a/tests/ui/needless_pass_by_ref_mut.rs b/tests/ui/needless_pass_by_ref_mut.rs index f0c5a716ac991..18cca14701f31 100644 --- a/tests/ui/needless_pass_by_ref_mut.rs +++ b/tests/ui/needless_pass_by_ref_mut.rs @@ -1,13 +1,13 @@ #![allow( clippy::if_same_then_else, clippy::no_effect, + clippy::ptr_arg, clippy::redundant_closure_call, - clippy::ptr_arg + clippy::uninlined_format_args )] #![warn(clippy::needless_pass_by_ref_mut)] //@no-rustfix use std::ptr::NonNull; - fn foo(s: &mut Vec, b: &u32, x: &mut u32) { //~^ needless_pass_by_ref_mut diff --git a/tests/ui/to_string_in_format_args_incremental.fixed b/tests/ui/to_string_in_format_args_incremental.fixed index 2a29580e390ce..32efc2b5eba14 100644 --- a/tests/ui/to_string_in_format_args_incremental.fixed +++ b/tests/ui/to_string_in_format_args_incremental.fixed @@ -1,5 +1,5 @@ //@compile-flags: -C incremental=target/debug/test/incr - +#![allow(clippy::uninlined_format_args)] // see https://github.com/rust-lang/rust-clippy/issues/10969 fn main() { diff --git a/tests/ui/to_string_in_format_args_incremental.rs b/tests/ui/to_string_in_format_args_incremental.rs index 18ca82976a40e..197685fb0d7c4 100644 --- a/tests/ui/to_string_in_format_args_incremental.rs +++ b/tests/ui/to_string_in_format_args_incremental.rs @@ -1,5 +1,5 @@ //@compile-flags: -C incremental=target/debug/test/incr - +#![allow(clippy::uninlined_format_args)] // see https://github.com/rust-lang/rust-clippy/issues/10969 fn main() { diff --git a/tests/ui/unnecessary_iter_cloned.fixed b/tests/ui/unnecessary_iter_cloned.fixed index aed2dbe1f1ce4..61f2e3745ad05 100644 --- a/tests/ui/unnecessary_iter_cloned.fixed +++ b/tests/ui/unnecessary_iter_cloned.fixed @@ -1,4 +1,4 @@ -#![allow(unused_assignments)] +#![allow(unused_assignments, clippy::uninlined_format_args)] #![warn(clippy::unnecessary_to_owned)] #[allow(dead_code)] diff --git a/tests/ui/unnecessary_iter_cloned.rs b/tests/ui/unnecessary_iter_cloned.rs index 12fdd150e4233..b90ca00a5fece 100644 --- a/tests/ui/unnecessary_iter_cloned.rs +++ b/tests/ui/unnecessary_iter_cloned.rs @@ -1,4 +1,4 @@ -#![allow(unused_assignments)] +#![allow(unused_assignments, clippy::uninlined_format_args)] #![warn(clippy::unnecessary_to_owned)] #[allow(dead_code)] diff --git a/tests/ui/unnecessary_operation.fixed b/tests/ui/unnecessary_operation.fixed index 05dfb72f48d2d..b632c200b2abc 100644 --- a/tests/ui/unnecessary_operation.fixed +++ b/tests/ui/unnecessary_operation.fixed @@ -6,7 +6,7 @@ clippy::unnecessary_struct_initialization )] #![warn(clippy::unnecessary_operation)] - +#![allow(clippy::uninlined_format_args)] use std::fmt::Display; use std::ops::Shl; diff --git a/tests/ui/unnecessary_operation.rs b/tests/ui/unnecessary_operation.rs index 6ef74c3eb1c1e..3e34b46185e34 100644 --- a/tests/ui/unnecessary_operation.rs +++ b/tests/ui/unnecessary_operation.rs @@ -6,7 +6,7 @@ clippy::unnecessary_struct_initialization )] #![warn(clippy::unnecessary_operation)] - +#![allow(clippy::uninlined_format_args)] use std::fmt::Display; use std::ops::Shl; diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed index 5410033dbd8f4..498dab3eb5070 100644 --- a/tests/ui/unnecessary_to_owned.fixed +++ b/tests/ui/unnecessary_to_owned.fixed @@ -7,7 +7,7 @@ clippy::owned_cow )] #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] - +#![allow(clippy::uninlined_format_args)] use std::borrow::Cow; use std::ffi::{CStr, CString, OsStr, OsString}; use std::ops::Deref; diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs index 0619dd4ddec09..b9d613c3a0529 100644 --- a/tests/ui/unnecessary_to_owned.rs +++ b/tests/ui/unnecessary_to_owned.rs @@ -7,7 +7,7 @@ clippy::owned_cow )] #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] - +#![allow(clippy::uninlined_format_args)] use std::borrow::Cow; use std::ffi::{CStr, CString, OsStr, OsString}; use std::ops::Deref; From 8e50cfacdf49ff42432ae2fc6e943f07d316fc21 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 15 Feb 2025 19:54:54 -0500 Subject: [PATCH 0300/2248] make tests consistent --- .../index_refutable_slice.fixed | 3 +- .../index_refutable_slice.rs | 3 +- .../index_refutable_slice.stderr | 4 +- tests/ui/author/macro_in_closure.rs | 1 + tests/ui/dbg_macro/dbg_macro.fixed | 9 ++- tests/ui/dbg_macro/dbg_macro.rs | 9 ++- tests/ui/dbg_macro/dbg_macro.stderr | 38 +++++------ tests/ui/large_futures.fixed | 9 ++- tests/ui/large_futures.rs | 9 ++- tests/ui/large_futures.stderr | 16 ++--- tests/ui/manual_inspect.fixed | 2 +- tests/ui/manual_inspect.rs | 2 +- tests/ui/needless_pass_by_ref_mut.rs | 5 +- tests/ui/needless_pass_by_ref_mut.stderr | 68 +++++++++---------- ...to_string_in_format_args_incremental.fixed | 2 + .../to_string_in_format_args_incremental.rs | 2 + ...o_string_in_format_args_incremental.stderr | 2 +- tests/ui/unnecessary_operation.fixed | 9 +-- tests/ui/unnecessary_operation.rs | 9 +-- tests/ui/unnecessary_operation.stderr | 40 +++++------ tests/ui/unnecessary_to_owned.rs | 8 +-- 21 files changed, 139 insertions(+), 111 deletions(-) diff --git a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed index 2d5900094ee73..2877871d0bf4c 100644 --- a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed +++ b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed @@ -1,5 +1,6 @@ -#![deny(clippy::index_refutable_slice)] #![allow(clippy::uninlined_format_args)] +#![deny(clippy::index_refutable_slice)] + fn below_limit() { let slice: Option<&[u32]> = Some(&[1, 2, 3]); if let Some([_, _, _, _, _, _, _, slice_7, ..]) = slice { diff --git a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs index 94bd99a452fe2..f958b92a102a3 100644 --- a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs +++ b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs @@ -1,5 +1,6 @@ -#![deny(clippy::index_refutable_slice)] #![allow(clippy::uninlined_format_args)] +#![deny(clippy::index_refutable_slice)] + fn below_limit() { let slice: Option<&[u32]> = Some(&[1, 2, 3]); if let Some(slice) = slice { diff --git a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr index 022deb330e6e3..e1a8941e102f5 100644 --- a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr +++ b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr @@ -1,11 +1,11 @@ error: this binding can be a slice pattern to avoid indexing - --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:5:17 + --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:6:17 | LL | if let Some(slice) = slice { | ^^^^^ | note: the lint level is defined here - --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:1:9 + --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:2:9 | LL | #![deny(clippy::index_refutable_slice)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/author/macro_in_closure.rs b/tests/ui/author/macro_in_closure.rs index b6d8e7ecbdd19..373f0148d475a 100644 --- a/tests/ui/author/macro_in_closure.rs +++ b/tests/ui/author/macro_in_closure.rs @@ -1,4 +1,5 @@ //@ check-pass + #![allow(clippy::uninlined_format_args)] fn main() { diff --git a/tests/ui/dbg_macro/dbg_macro.fixed b/tests/ui/dbg_macro/dbg_macro.fixed index 8765035e39887..3b9dee81898ab 100644 --- a/tests/ui/dbg_macro/dbg_macro.fixed +++ b/tests/ui/dbg_macro/dbg_macro.fixed @@ -1,6 +1,11 @@ +#![allow( + clippy::no_effect, + clippy::uninlined_format_args, + clippy::unit_arg, + clippy::unnecessary_operation +)] #![warn(clippy::dbg_macro)] -#![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)] -#![allow(clippy::uninlined_format_args)] + fn foo(n: u32) -> u32 { if let Some(n) = n.checked_sub(4) { n } else { n } //~^ dbg_macro diff --git a/tests/ui/dbg_macro/dbg_macro.rs b/tests/ui/dbg_macro/dbg_macro.rs index 301f17db3169f..1dbbc6fe98456 100644 --- a/tests/ui/dbg_macro/dbg_macro.rs +++ b/tests/ui/dbg_macro/dbg_macro.rs @@ -1,6 +1,11 @@ +#![allow( + clippy::no_effect, + clippy::uninlined_format_args, + clippy::unit_arg, + clippy::unnecessary_operation +)] #![warn(clippy::dbg_macro)] -#![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)] -#![allow(clippy::uninlined_format_args)] + fn foo(n: u32) -> u32 { if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } //~^ dbg_macro diff --git a/tests/ui/dbg_macro/dbg_macro.stderr b/tests/ui/dbg_macro/dbg_macro.stderr index cd6dce584a2fa..f1412023cc897 100644 --- a/tests/ui/dbg_macro/dbg_macro.stderr +++ b/tests/ui/dbg_macro/dbg_macro.stderr @@ -1,5 +1,5 @@ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:5:22 + --> tests/ui/dbg_macro/dbg_macro.rs:10:22 | LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } | ^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + if let Some(n) = n.checked_sub(4) { n } else { n } | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:11:8 + --> tests/ui/dbg_macro/dbg_macro.rs:16:8 | LL | if dbg!(n <= 1) { | ^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + if n <= 1 { | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:14:9 + --> tests/ui/dbg_macro/dbg_macro.rs:19:9 | LL | dbg!(1) | ^^^^^^^ @@ -37,7 +37,7 @@ LL + 1 | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:17:9 + --> tests/ui/dbg_macro/dbg_macro.rs:22:9 | LL | dbg!(n * factorial(n - 1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + n * factorial(n - 1) | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:23:5 + --> tests/ui/dbg_macro/dbg_macro.rs:28:5 | LL | dbg!(42); | ^^^^^^^^ @@ -61,7 +61,7 @@ LL + 42; | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:26:14 + --> tests/ui/dbg_macro/dbg_macro.rs:31:14 | LL | foo(3) + dbg!(factorial(4)); | ^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + foo(3) + factorial(4); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:29:5 + --> tests/ui/dbg_macro/dbg_macro.rs:34:5 | LL | dbg!(1, 2, 3, 4, 5); | ^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + (1, 2, 3, 4, 5); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:51:5 + --> tests/ui/dbg_macro/dbg_macro.rs:56:5 | LL | dbg!(); | ^^^^^^ @@ -96,7 +96,7 @@ LL - dbg!(); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:55:13 + --> tests/ui/dbg_macro/dbg_macro.rs:60:13 | LL | let _ = dbg!(); | ^^^^^^ @@ -108,7 +108,7 @@ LL + let _ = (); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:58:9 + --> tests/ui/dbg_macro/dbg_macro.rs:63:9 | LL | bar(dbg!()); | ^^^^^^ @@ -120,7 +120,7 @@ LL + bar(()); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:61:10 + --> tests/ui/dbg_macro/dbg_macro.rs:66:10 | LL | foo!(dbg!()); | ^^^^^^ @@ -132,7 +132,7 @@ LL + foo!(()); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:64:16 + --> tests/ui/dbg_macro/dbg_macro.rs:69:16 | LL | foo2!(foo!(dbg!())); | ^^^^^^ @@ -144,7 +144,7 @@ LL + foo2!(foo!(())); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:46:13 + --> tests/ui/dbg_macro/dbg_macro.rs:51:13 | LL | dbg!(); | ^^^^^^ @@ -159,7 +159,7 @@ LL - dbg!(); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:87:9 + --> tests/ui/dbg_macro/dbg_macro.rs:92:9 | LL | dbg!(2); | ^^^^^^^ @@ -171,7 +171,7 @@ LL + 2; | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:94:5 + --> tests/ui/dbg_macro/dbg_macro.rs:99:5 | LL | dbg!(1); | ^^^^^^^ @@ -183,7 +183,7 @@ LL + 1; | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:100:5 + --> tests/ui/dbg_macro/dbg_macro.rs:105:5 | LL | dbg!(1); | ^^^^^^^ @@ -195,7 +195,7 @@ LL + 1; | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:107:9 + --> tests/ui/dbg_macro/dbg_macro.rs:112:9 | LL | dbg!(1); | ^^^^^^^ @@ -207,7 +207,7 @@ LL + 1; | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:114:31 + --> tests/ui/dbg_macro/dbg_macro.rs:119:31 | LL | println!("dbg: {:?}", dbg!(s)); | ^^^^^^^ @@ -219,7 +219,7 @@ LL + println!("dbg: {:?}", s); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:117:22 + --> tests/ui/dbg_macro/dbg_macro.rs:122:22 | LL | print!("{}", dbg!(s)); | ^^^^^^^ diff --git a/tests/ui/large_futures.fixed b/tests/ui/large_futures.fixed index 6b2acaa9ff103..4c7215f0abeb0 100644 --- a/tests/ui/large_futures.fixed +++ b/tests/ui/large_futures.fixed @@ -1,7 +1,10 @@ +#![allow( + clippy::future_not_send, + clippy::manual_async_fn, + clippy::never_loop, + clippy::uninlined_format_args +)] #![warn(clippy::large_futures)] -#![allow(clippy::never_loop)] -#![allow(clippy::future_not_send)] -#![allow(clippy::manual_async_fn, clippy::uninlined_format_args)] async fn big_fut(_arg: [u8; 1024 * 16]) {} diff --git a/tests/ui/large_futures.rs b/tests/ui/large_futures.rs index 6bf1fb87727ad..2b5860583f5ec 100644 --- a/tests/ui/large_futures.rs +++ b/tests/ui/large_futures.rs @@ -1,7 +1,10 @@ +#![allow( + clippy::future_not_send, + clippy::manual_async_fn, + clippy::never_loop, + clippy::uninlined_format_args +)] #![warn(clippy::large_futures)] -#![allow(clippy::never_loop)] -#![allow(clippy::future_not_send)] -#![allow(clippy::manual_async_fn, clippy::uninlined_format_args)] async fn big_fut(_arg: [u8; 1024 * 16]) {} diff --git a/tests/ui/large_futures.stderr b/tests/ui/large_futures.stderr index fd6ba4e3563de..4280c9e2af284 100644 --- a/tests/ui/large_futures.stderr +++ b/tests/ui/large_futures.stderr @@ -1,5 +1,5 @@ error: large future with a size of 16385 bytes - --> tests/ui/large_futures.rs:10:9 + --> tests/ui/large_futures.rs:13:9 | LL | big_fut([0u8; 1024 * 16]).await; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))` @@ -8,37 +8,37 @@ LL | big_fut([0u8; 1024 * 16]).await; = help: to override `-D warnings` add `#[allow(clippy::large_futures)]` error: large future with a size of 16386 bytes - --> tests/ui/large_futures.rs:13:5 + --> tests/ui/large_futures.rs:16:5 | LL | f.await | ^ help: consider `Box::pin` on it: `Box::pin(f)` error: large future with a size of 16387 bytes - --> tests/ui/large_futures.rs:18:9 + --> tests/ui/large_futures.rs:21:9 | LL | wait().await; | ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())` error: large future with a size of 16387 bytes - --> tests/ui/large_futures.rs:24:13 + --> tests/ui/large_futures.rs:27:13 | LL | wait().await; | ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())` error: large future with a size of 65540 bytes - --> tests/ui/large_futures.rs:32:5 + --> tests/ui/large_futures.rs:35:5 | LL | foo().await; | ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())` error: large future with a size of 49159 bytes - --> tests/ui/large_futures.rs:35:5 + --> tests/ui/large_futures.rs:38:5 | LL | calls_fut(fut).await; | ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))` error: large future with a size of 65540 bytes - --> tests/ui/large_futures.rs:48:5 + --> tests/ui/large_futures.rs:51:5 | LL | / async { LL | | @@ -61,7 +61,7 @@ LL + }) | error: large future with a size of 65540 bytes - --> tests/ui/large_futures.rs:61:13 + --> tests/ui/large_futures.rs:64:13 | LL | / async { LL | | diff --git a/tests/ui/manual_inspect.fixed b/tests/ui/manual_inspect.fixed index 1a722cef43401..8d045c48ceb04 100644 --- a/tests/ui/manual_inspect.fixed +++ b/tests/ui/manual_inspect.fixed @@ -1,5 +1,5 @@ -#![warn(clippy::manual_inspect)] #![allow(clippy::no_effect, clippy::op_ref, clippy::uninlined_format_args)] +#![warn(clippy::manual_inspect)] fn main() { let _ = Some(0).inspect(|&x| { diff --git a/tests/ui/manual_inspect.rs b/tests/ui/manual_inspect.rs index eaf6b9fa0edf6..a89d28dab689c 100644 --- a/tests/ui/manual_inspect.rs +++ b/tests/ui/manual_inspect.rs @@ -1,5 +1,5 @@ -#![warn(clippy::manual_inspect)] #![allow(clippy::no_effect, clippy::op_ref, clippy::uninlined_format_args)] +#![warn(clippy::manual_inspect)] fn main() { let _ = Some(0).map(|x| { diff --git a/tests/ui/needless_pass_by_ref_mut.rs b/tests/ui/needless_pass_by_ref_mut.rs index 18cca14701f31..e9c50ea5dd51c 100644 --- a/tests/ui/needless_pass_by_ref_mut.rs +++ b/tests/ui/needless_pass_by_ref_mut.rs @@ -1,3 +1,5 @@ +//@no-rustfix + #![allow( clippy::if_same_then_else, clippy::no_effect, @@ -6,8 +8,9 @@ clippy::uninlined_format_args )] #![warn(clippy::needless_pass_by_ref_mut)] -//@no-rustfix + use std::ptr::NonNull; + fn foo(s: &mut Vec, b: &u32, x: &mut u32) { //~^ needless_pass_by_ref_mut diff --git a/tests/ui/needless_pass_by_ref_mut.stderr b/tests/ui/needless_pass_by_ref_mut.stderr index 6637a255b5f51..a718188f4af37 100644 --- a/tests/ui/needless_pass_by_ref_mut.stderr +++ b/tests/ui/needless_pass_by_ref_mut.stderr @@ -1,5 +1,5 @@ error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:11:11 + --> tests/ui/needless_pass_by_ref_mut.rs:14:11 | LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` @@ -8,79 +8,79 @@ LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:37:12 + --> tests/ui/needless_pass_by_ref_mut.rs:40:12 | LL | fn foo6(s: &mut Vec) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:48:12 + --> tests/ui/needless_pass_by_ref_mut.rs:51:12 | LL | fn bar(&mut self) {} | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:51:29 + --> tests/ui/needless_pass_by_ref_mut.rs:54:29 | LL | fn mushroom(&self, vec: &mut Vec) -> usize { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:129:16 + --> tests/ui/needless_pass_by_ref_mut.rs:132:16 | LL | async fn a1(x: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:134:16 + --> tests/ui/needless_pass_by_ref_mut.rs:137:16 | LL | async fn a2(x: &mut i32, y: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:139:16 + --> tests/ui/needless_pass_by_ref_mut.rs:142:16 | LL | async fn a3(x: &mut i32, y: String, z: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:144:16 + --> tests/ui/needless_pass_by_ref_mut.rs:147:16 | LL | async fn a4(x: &mut i32, y: i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:149:24 + --> tests/ui/needless_pass_by_ref_mut.rs:152:24 | LL | async fn a5(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:154:24 + --> tests/ui/needless_pass_by_ref_mut.rs:157:24 | LL | async fn a6(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:159:32 + --> tests/ui/needless_pass_by_ref_mut.rs:162:32 | LL | async fn a7(x: i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:164:24 + --> tests/ui/needless_pass_by_ref_mut.rs:167:24 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:164:45 + --> tests/ui/needless_pass_by_ref_mut.rs:167:45 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:200:16 + --> tests/ui/needless_pass_by_ref_mut.rs:203:16 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -88,7 +88,7 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:205:20 + --> tests/ui/needless_pass_by_ref_mut.rs:208:20 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -96,115 +96,115 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:218:39 + --> tests/ui/needless_pass_by_ref_mut.rs:221:39 | LL | async fn inner_async2(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:227:26 + --> tests/ui/needless_pass_by_ref_mut.rs:230:26 | LL | async fn inner_async3(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:247:30 + --> tests/ui/needless_pass_by_ref_mut.rs:250:30 | LL | async fn call_in_closure1(n: &mut str) { | ^^^^^^^^ help: consider changing to: `&str` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:267:16 + --> tests/ui/needless_pass_by_ref_mut.rs:270:16 | LL | fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { | ^^^^^^^^^^ help: consider changing to: `&usize` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:279:22 + --> tests/ui/needless_pass_by_ref_mut.rs:282:22 | LL | async fn closure4(n: &mut usize) { | ^^^^^^^^^^ help: consider changing to: `&usize` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:334:12 + --> tests/ui/needless_pass_by_ref_mut.rs:337:12 | LL | fn bar(&mut self) {} | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:337:18 + --> tests/ui/needless_pass_by_ref_mut.rs:340:18 | LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:337:45 + --> tests/ui/needless_pass_by_ref_mut.rs:340:45 | LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:346:46 + --> tests/ui/needless_pass_by_ref_mut.rs:349:46 | LL | async fn foo2(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:363:18 + --> tests/ui/needless_pass_by_ref_mut.rs:366:18 | LL | fn _empty_tup(x: &mut (())) {} | ^^^^^^^^^ help: consider changing to: `&()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:365:19 + --> tests/ui/needless_pass_by_ref_mut.rs:368:19 | LL | fn _single_tup(x: &mut ((i32,))) {} | ^^^^^^^^^^^^^ help: consider changing to: `&(i32,)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:367:18 + --> tests/ui/needless_pass_by_ref_mut.rs:370:18 | LL | fn _multi_tup(x: &mut ((i32, u32))) {} | ^^^^^^^^^^^^^^^^^ help: consider changing to: `&(i32, u32)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:369:11 + --> tests/ui/needless_pass_by_ref_mut.rs:372:11 | LL | fn _fn(x: &mut (fn())) {} | ^^^^^^^^^^^ help: consider changing to: `&fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:372:23 + --> tests/ui/needless_pass_by_ref_mut.rs:375:23 | LL | fn _extern_rust_fn(x: &mut extern "Rust" fn()) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "Rust" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:374:20 + --> tests/ui/needless_pass_by_ref_mut.rs:377:20 | LL | fn _extern_c_fn(x: &mut extern "C" fn()) {} | ^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "C" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:376:18 + --> tests/ui/needless_pass_by_ref_mut.rs:379:18 | LL | fn _unsafe_fn(x: &mut unsafe fn()) {} | ^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:378:25 + --> tests/ui/needless_pass_by_ref_mut.rs:381:25 | LL | fn _unsafe_extern_fn(x: &mut unsafe extern "C" fn()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:380:20 + --> tests/ui/needless_pass_by_ref_mut.rs:383:20 | LL | fn _fn_with_arg(x: &mut unsafe extern "C" fn(i32)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn(i32)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:382:20 + --> tests/ui/needless_pass_by_ref_mut.rs:385:20 | LL | fn _fn_with_ret(x: &mut unsafe extern "C" fn() -> (i32)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn() -> (i32)` diff --git a/tests/ui/to_string_in_format_args_incremental.fixed b/tests/ui/to_string_in_format_args_incremental.fixed index 32efc2b5eba14..98b028c15fd0a 100644 --- a/tests/ui/to_string_in_format_args_incremental.fixed +++ b/tests/ui/to_string_in_format_args_incremental.fixed @@ -1,5 +1,7 @@ //@compile-flags: -C incremental=target/debug/test/incr + #![allow(clippy::uninlined_format_args)] + // see https://github.com/rust-lang/rust-clippy/issues/10969 fn main() { diff --git a/tests/ui/to_string_in_format_args_incremental.rs b/tests/ui/to_string_in_format_args_incremental.rs index 197685fb0d7c4..a5ebe4b032750 100644 --- a/tests/ui/to_string_in_format_args_incremental.rs +++ b/tests/ui/to_string_in_format_args_incremental.rs @@ -1,5 +1,7 @@ //@compile-flags: -C incremental=target/debug/test/incr + #![allow(clippy::uninlined_format_args)] + // see https://github.com/rust-lang/rust-clippy/issues/10969 fn main() { diff --git a/tests/ui/to_string_in_format_args_incremental.stderr b/tests/ui/to_string_in_format_args_incremental.stderr index 535dd21ea5888..62178cc0cfbff 100644 --- a/tests/ui/to_string_in_format_args_incremental.stderr +++ b/tests/ui/to_string_in_format_args_incremental.stderr @@ -1,5 +1,5 @@ error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/to_string_in_format_args_incremental.rs:7:21 + --> tests/ui/to_string_in_format_args_incremental.rs:9:21 | LL | println!("{}", s.to_string()); | ^^^^^^^^^^^^ help: remove this diff --git a/tests/ui/unnecessary_operation.fixed b/tests/ui/unnecessary_operation.fixed index b632c200b2abc..645b56fe95e74 100644 --- a/tests/ui/unnecessary_operation.fixed +++ b/tests/ui/unnecessary_operation.fixed @@ -1,12 +1,13 @@ #![allow( clippy::deref_addrof, - dead_code, - unused, clippy::no_effect, - clippy::unnecessary_struct_initialization + clippy::uninlined_format_args, + clippy::unnecessary_struct_initialization, + dead_code, + unused )] #![warn(clippy::unnecessary_operation)] -#![allow(clippy::uninlined_format_args)] + use std::fmt::Display; use std::ops::Shl; diff --git a/tests/ui/unnecessary_operation.rs b/tests/ui/unnecessary_operation.rs index 3e34b46185e34..97e90269c5c0c 100644 --- a/tests/ui/unnecessary_operation.rs +++ b/tests/ui/unnecessary_operation.rs @@ -1,12 +1,13 @@ #![allow( clippy::deref_addrof, - dead_code, - unused, clippy::no_effect, - clippy::unnecessary_struct_initialization + clippy::uninlined_format_args, + clippy::unnecessary_struct_initialization, + dead_code, + unused )] #![warn(clippy::unnecessary_operation)] -#![allow(clippy::uninlined_format_args)] + use std::fmt::Display; use std::ops::Shl; diff --git a/tests/ui/unnecessary_operation.stderr b/tests/ui/unnecessary_operation.stderr index eb98af09e7a3d..0fda1dfde1903 100644 --- a/tests/ui/unnecessary_operation.stderr +++ b/tests/ui/unnecessary_operation.stderr @@ -1,5 +1,5 @@ error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:70:5 + --> tests/ui/unnecessary_operation.rs:71:5 | LL | Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` @@ -8,103 +8,103 @@ LL | Tuple(get_number()); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_operation)]` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:72:5 + --> tests/ui/unnecessary_operation.rs:73:5 | LL | Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:74:5 + --> tests/ui/unnecessary_operation.rs:75:5 | LL | Struct { ..get_struct() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_struct();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:76:5 + --> tests/ui/unnecessary_operation.rs:77:5 | LL | Enum::Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:78:5 + --> tests/ui/unnecessary_operation.rs:79:5 | LL | Enum::Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:80:5 + --> tests/ui/unnecessary_operation.rs:81:5 | LL | 5 + get_number(); | ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:82:5 + --> tests/ui/unnecessary_operation.rs:83:5 | LL | *&get_number(); | ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:84:5 + --> tests/ui/unnecessary_operation.rs:85:5 | LL | &get_number(); | ^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:86:5 + --> tests/ui/unnecessary_operation.rs:87:5 | LL | (5, 6, get_number()); | ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;6;get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:88:5 + --> tests/ui/unnecessary_operation.rs:89:5 | LL | get_number()..; | ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:90:5 + --> tests/ui/unnecessary_operation.rs:91:5 | LL | ..get_number(); | ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:92:5 + --> tests/ui/unnecessary_operation.rs:93:5 | LL | 5..get_number(); | ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:94:5 + --> tests/ui/unnecessary_operation.rs:95:5 | LL | [42, get_number()]; | ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:96:5 + --> tests/ui/unnecessary_operation.rs:97:5 | LL | [42, 55][get_usize()]; | ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:98:5 + --> tests/ui/unnecessary_operation.rs:99:5 | LL | (42, get_number()).1; | ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:100:5 + --> tests/ui/unnecessary_operation.rs:101:5 | LL | [get_number(); 55]; | ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:102:5 + --> tests/ui/unnecessary_operation.rs:103:5 | LL | [42; 55][get_usize()]; | ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42; 55].len() > get_usize());` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:104:5 + --> tests/ui/unnecessary_operation.rs:105:5 | LL | / { LL | | @@ -113,7 +113,7 @@ LL | | }; | |______^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:108:5 + --> tests/ui/unnecessary_operation.rs:109:5 | LL | / FooString { LL | | @@ -122,7 +122,7 @@ LL | | }; | |______^ help: statement can be reduced to: `String::from("blah");` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:149:5 + --> tests/ui/unnecessary_operation.rs:150:5 | LL | [42, 55][get_usize()]; | ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());` diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs index b9d613c3a0529..84ac575ddf521 100644 --- a/tests/ui/unnecessary_to_owned.rs +++ b/tests/ui/unnecessary_to_owned.rs @@ -1,13 +1,13 @@ #![allow( + clippy::manual_async_fn, clippy::needless_borrow, clippy::needless_borrows_for_generic_args, - clippy::ptr_arg, - clippy::manual_async_fn, clippy::needless_lifetimes, - clippy::owned_cow + clippy::owned_cow, + clippy::ptr_arg )] #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] -#![allow(clippy::uninlined_format_args)] + use std::borrow::Cow; use std::ffi::{CStr, CString, OsStr, OsString}; use std::ops::Deref; From 1ca79a8797e8c81854a1afc8b1cde40d503c92d6 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 25 Mar 2025 10:49:14 -0400 Subject: [PATCH 0301/2248] test fixes --- tests/ui/manual_strip_fixable.fixed | 1 + tests/ui/manual_strip_fixable.rs | 1 + tests/ui/manual_strip_fixable.stderr | 8 +- tests/ui/needless_pass_by_ref_mut.rs | 4 +- tests/ui/needless_pass_by_ref_mut.stderr | 68 +++---- .../ui/unnecessary_os_str_debug_formatting.rs | 1 + ...unnecessary_os_str_debug_formatting.stderr | 12 +- tests/ui/unnecessary_path_debug_formatting.rs | 1 + .../unnecessary_path_debug_formatting.stderr | 18 +- tests/ui/unnecessary_to_owned.fixed | 9 +- tests/ui/unnecessary_to_owned.rs | 3 +- tests/ui/unnecessary_to_owned.stderr | 174 +++++++++--------- 12 files changed, 152 insertions(+), 148 deletions(-) diff --git a/tests/ui/manual_strip_fixable.fixed b/tests/ui/manual_strip_fixable.fixed index 75a3f1645de33..b59e3719d951d 100644 --- a/tests/ui/manual_strip_fixable.fixed +++ b/tests/ui/manual_strip_fixable.fixed @@ -1,4 +1,5 @@ #![warn(clippy::manual_strip)] +#![allow(clippy::uninlined_format_args)] fn main() { let s = "abc"; diff --git a/tests/ui/manual_strip_fixable.rs b/tests/ui/manual_strip_fixable.rs index 5080068449e20..4fb3a9bf007f6 100644 --- a/tests/ui/manual_strip_fixable.rs +++ b/tests/ui/manual_strip_fixable.rs @@ -1,4 +1,5 @@ #![warn(clippy::manual_strip)] +#![allow(clippy::uninlined_format_args)] fn main() { let s = "abc"; diff --git a/tests/ui/manual_strip_fixable.stderr b/tests/ui/manual_strip_fixable.stderr index 1c276e5d8fdfe..da8b0cd08f893 100644 --- a/tests/ui/manual_strip_fixable.stderr +++ b/tests/ui/manual_strip_fixable.stderr @@ -1,11 +1,11 @@ error: stripping a prefix manually - --> tests/ui/manual_strip_fixable.rs:7:24 + --> tests/ui/manual_strip_fixable.rs:8:24 | LL | let stripped = &s["ab".len()..]; | ^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> tests/ui/manual_strip_fixable.rs:6:5 + --> tests/ui/manual_strip_fixable.rs:7:5 | LL | if s.starts_with("ab") { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,13 +19,13 @@ LL ~ println!("{stripped}{}", stripped); | error: stripping a suffix manually - --> tests/ui/manual_strip_fixable.rs:13:24 + --> tests/ui/manual_strip_fixable.rs:14:24 | LL | let stripped = &s[..s.len() - "bc".len()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the suffix was tested here - --> tests/ui/manual_strip_fixable.rs:12:5 + --> tests/ui/manual_strip_fixable.rs:13:5 | LL | if s.ends_with("bc") { | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/needless_pass_by_ref_mut.rs b/tests/ui/needless_pass_by_ref_mut.rs index e9c50ea5dd51c..5d9936fdac4d9 100644 --- a/tests/ui/needless_pass_by_ref_mut.rs +++ b/tests/ui/needless_pass_by_ref_mut.rs @@ -1,5 +1,3 @@ -//@no-rustfix - #![allow( clippy::if_same_then_else, clippy::no_effect, @@ -8,7 +6,7 @@ clippy::uninlined_format_args )] #![warn(clippy::needless_pass_by_ref_mut)] - +//@no-rustfix use std::ptr::NonNull; fn foo(s: &mut Vec, b: &u32, x: &mut u32) { diff --git a/tests/ui/needless_pass_by_ref_mut.stderr b/tests/ui/needless_pass_by_ref_mut.stderr index a718188f4af37..94d98f0e9b12d 100644 --- a/tests/ui/needless_pass_by_ref_mut.stderr +++ b/tests/ui/needless_pass_by_ref_mut.stderr @@ -1,5 +1,5 @@ error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:14:11 + --> tests/ui/needless_pass_by_ref_mut.rs:12:11 | LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` @@ -8,79 +8,79 @@ LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:40:12 + --> tests/ui/needless_pass_by_ref_mut.rs:38:12 | LL | fn foo6(s: &mut Vec) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:51:12 + --> tests/ui/needless_pass_by_ref_mut.rs:49:12 | LL | fn bar(&mut self) {} | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:54:29 + --> tests/ui/needless_pass_by_ref_mut.rs:52:29 | LL | fn mushroom(&self, vec: &mut Vec) -> usize { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:132:16 + --> tests/ui/needless_pass_by_ref_mut.rs:130:16 | LL | async fn a1(x: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:137:16 + --> tests/ui/needless_pass_by_ref_mut.rs:135:16 | LL | async fn a2(x: &mut i32, y: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:142:16 + --> tests/ui/needless_pass_by_ref_mut.rs:140:16 | LL | async fn a3(x: &mut i32, y: String, z: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:147:16 + --> tests/ui/needless_pass_by_ref_mut.rs:145:16 | LL | async fn a4(x: &mut i32, y: i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:152:24 + --> tests/ui/needless_pass_by_ref_mut.rs:150:24 | LL | async fn a5(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:157:24 + --> tests/ui/needless_pass_by_ref_mut.rs:155:24 | LL | async fn a6(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:162:32 + --> tests/ui/needless_pass_by_ref_mut.rs:160:32 | LL | async fn a7(x: i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:167:24 + --> tests/ui/needless_pass_by_ref_mut.rs:165:24 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:167:45 + --> tests/ui/needless_pass_by_ref_mut.rs:165:45 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:203:16 + --> tests/ui/needless_pass_by_ref_mut.rs:201:16 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -88,7 +88,7 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:208:20 + --> tests/ui/needless_pass_by_ref_mut.rs:206:20 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -96,115 +96,115 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:221:39 + --> tests/ui/needless_pass_by_ref_mut.rs:219:39 | LL | async fn inner_async2(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:230:26 + --> tests/ui/needless_pass_by_ref_mut.rs:228:26 | LL | async fn inner_async3(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:250:30 + --> tests/ui/needless_pass_by_ref_mut.rs:248:30 | LL | async fn call_in_closure1(n: &mut str) { | ^^^^^^^^ help: consider changing to: `&str` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:270:16 + --> tests/ui/needless_pass_by_ref_mut.rs:268:16 | LL | fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { | ^^^^^^^^^^ help: consider changing to: `&usize` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:282:22 + --> tests/ui/needless_pass_by_ref_mut.rs:280:22 | LL | async fn closure4(n: &mut usize) { | ^^^^^^^^^^ help: consider changing to: `&usize` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:337:12 + --> tests/ui/needless_pass_by_ref_mut.rs:335:12 | LL | fn bar(&mut self) {} | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:340:18 + --> tests/ui/needless_pass_by_ref_mut.rs:338:18 | LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:340:45 + --> tests/ui/needless_pass_by_ref_mut.rs:338:45 | LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:349:46 + --> tests/ui/needless_pass_by_ref_mut.rs:347:46 | LL | async fn foo2(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:366:18 + --> tests/ui/needless_pass_by_ref_mut.rs:364:18 | LL | fn _empty_tup(x: &mut (())) {} | ^^^^^^^^^ help: consider changing to: `&()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:368:19 + --> tests/ui/needless_pass_by_ref_mut.rs:366:19 | LL | fn _single_tup(x: &mut ((i32,))) {} | ^^^^^^^^^^^^^ help: consider changing to: `&(i32,)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:370:18 + --> tests/ui/needless_pass_by_ref_mut.rs:368:18 | LL | fn _multi_tup(x: &mut ((i32, u32))) {} | ^^^^^^^^^^^^^^^^^ help: consider changing to: `&(i32, u32)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:372:11 + --> tests/ui/needless_pass_by_ref_mut.rs:370:11 | LL | fn _fn(x: &mut (fn())) {} | ^^^^^^^^^^^ help: consider changing to: `&fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:375:23 + --> tests/ui/needless_pass_by_ref_mut.rs:373:23 | LL | fn _extern_rust_fn(x: &mut extern "Rust" fn()) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "Rust" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:377:20 + --> tests/ui/needless_pass_by_ref_mut.rs:375:20 | LL | fn _extern_c_fn(x: &mut extern "C" fn()) {} | ^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "C" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:379:18 + --> tests/ui/needless_pass_by_ref_mut.rs:377:18 | LL | fn _unsafe_fn(x: &mut unsafe fn()) {} | ^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:381:25 + --> tests/ui/needless_pass_by_ref_mut.rs:379:25 | LL | fn _unsafe_extern_fn(x: &mut unsafe extern "C" fn()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:383:20 + --> tests/ui/needless_pass_by_ref_mut.rs:381:20 | LL | fn _fn_with_arg(x: &mut unsafe extern "C" fn(i32)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn(i32)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:385:20 + --> tests/ui/needless_pass_by_ref_mut.rs:383:20 | LL | fn _fn_with_ret(x: &mut unsafe extern "C" fn() -> (i32)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn() -> (i32)` diff --git a/tests/ui/unnecessary_os_str_debug_formatting.rs b/tests/ui/unnecessary_os_str_debug_formatting.rs index 12663ec9a528f..6652efd9ae1d8 100644 --- a/tests/ui/unnecessary_os_str_debug_formatting.rs +++ b/tests/ui/unnecessary_os_str_debug_formatting.rs @@ -1,4 +1,5 @@ #![warn(clippy::unnecessary_debug_formatting)] +#![allow(clippy::uninlined_format_args)] use std::ffi::{OsStr, OsString}; diff --git a/tests/ui/unnecessary_os_str_debug_formatting.stderr b/tests/ui/unnecessary_os_str_debug_formatting.stderr index 001309ab817a1..382e59b046193 100644 --- a/tests/ui/unnecessary_os_str_debug_formatting.stderr +++ b/tests/ui/unnecessary_os_str_debug_formatting.stderr @@ -1,5 +1,5 @@ error: unnecessary `Debug` formatting in `println!` args - --> tests/ui/unnecessary_os_str_debug_formatting.rs:14:22 + --> tests/ui/unnecessary_os_str_debug_formatting.rs:15:22 | LL | println!("{:?}", os_str); | ^^^^^^ @@ -10,7 +10,7 @@ LL | println!("{:?}", os_str); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_debug_formatting)]` error: unnecessary `Debug` formatting in `println!` args - --> tests/ui/unnecessary_os_str_debug_formatting.rs:15:22 + --> tests/ui/unnecessary_os_str_debug_formatting.rs:16:22 | LL | println!("{:?}", os_string); | ^^^^^^^^^ @@ -19,7 +19,7 @@ LL | println!("{:?}", os_string); = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed error: unnecessary `Debug` formatting in `println!` args - --> tests/ui/unnecessary_os_str_debug_formatting.rs:17:16 + --> tests/ui/unnecessary_os_str_debug_formatting.rs:18:16 | LL | println!("{os_str:?}"); | ^^^^^^ @@ -28,7 +28,7 @@ LL | println!("{os_str:?}"); = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed error: unnecessary `Debug` formatting in `println!` args - --> tests/ui/unnecessary_os_str_debug_formatting.rs:18:16 + --> tests/ui/unnecessary_os_str_debug_formatting.rs:19:16 | LL | println!("{os_string:?}"); | ^^^^^^^^^ @@ -37,7 +37,7 @@ LL | println!("{os_string:?}"); = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed error: unnecessary `Debug` formatting in `format!` args - --> tests/ui/unnecessary_os_str_debug_formatting.rs:20:37 + --> tests/ui/unnecessary_os_str_debug_formatting.rs:21:37 | LL | let _: String = format!("{:?}", os_str); | ^^^^^^ @@ -46,7 +46,7 @@ LL | let _: String = format!("{:?}", os_str); = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed error: unnecessary `Debug` formatting in `format!` args - --> tests/ui/unnecessary_os_str_debug_formatting.rs:21:37 + --> tests/ui/unnecessary_os_str_debug_formatting.rs:22:37 | LL | let _: String = format!("{:?}", os_string); | ^^^^^^^^^ diff --git a/tests/ui/unnecessary_path_debug_formatting.rs b/tests/ui/unnecessary_path_debug_formatting.rs index f14f6085c9a14..215e0d5d7802e 100644 --- a/tests/ui/unnecessary_path_debug_formatting.rs +++ b/tests/ui/unnecessary_path_debug_formatting.rs @@ -1,4 +1,5 @@ #![warn(clippy::unnecessary_debug_formatting)] +#![allow(clippy::uninlined_format_args)] use std::ffi::{OsStr, OsString}; use std::ops::Deref; diff --git a/tests/ui/unnecessary_path_debug_formatting.stderr b/tests/ui/unnecessary_path_debug_formatting.stderr index f12fa72c84b35..d244b9ad6716a 100644 --- a/tests/ui/unnecessary_path_debug_formatting.stderr +++ b/tests/ui/unnecessary_path_debug_formatting.stderr @@ -1,5 +1,5 @@ error: unnecessary `Debug` formatting in `println!` args - --> tests/ui/unnecessary_path_debug_formatting.rs:29:22 + --> tests/ui/unnecessary_path_debug_formatting.rs:30:22 | LL | println!("{:?}", os_str); | ^^^^^^ @@ -10,7 +10,7 @@ LL | println!("{:?}", os_str); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_debug_formatting)]` error: unnecessary `Debug` formatting in `println!` args - --> tests/ui/unnecessary_path_debug_formatting.rs:30:22 + --> tests/ui/unnecessary_path_debug_formatting.rs:31:22 | LL | println!("{:?}", os_string); | ^^^^^^^^^ @@ -19,7 +19,7 @@ LL | println!("{:?}", os_string); = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed error: unnecessary `Debug` formatting in `println!` args - --> tests/ui/unnecessary_path_debug_formatting.rs:32:22 + --> tests/ui/unnecessary_path_debug_formatting.rs:33:22 | LL | println!("{:?}", path); | ^^^^ @@ -28,7 +28,7 @@ LL | println!("{:?}", path); = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed error: unnecessary `Debug` formatting in `println!` args - --> tests/ui/unnecessary_path_debug_formatting.rs:33:22 + --> tests/ui/unnecessary_path_debug_formatting.rs:34:22 | LL | println!("{:?}", path_buf); | ^^^^^^^^ @@ -37,7 +37,7 @@ LL | println!("{:?}", path_buf); = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed error: unnecessary `Debug` formatting in `println!` args - --> tests/ui/unnecessary_path_debug_formatting.rs:35:16 + --> tests/ui/unnecessary_path_debug_formatting.rs:36:16 | LL | println!("{path:?}"); | ^^^^ @@ -46,7 +46,7 @@ LL | println!("{path:?}"); = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed error: unnecessary `Debug` formatting in `println!` args - --> tests/ui/unnecessary_path_debug_formatting.rs:36:16 + --> tests/ui/unnecessary_path_debug_formatting.rs:37:16 | LL | println!("{path_buf:?}"); | ^^^^^^^^ @@ -55,7 +55,7 @@ LL | println!("{path_buf:?}"); = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed error: unnecessary `Debug` formatting in `format!` args - --> tests/ui/unnecessary_path_debug_formatting.rs:38:37 + --> tests/ui/unnecessary_path_debug_formatting.rs:39:37 | LL | let _: String = format!("{:?}", path); | ^^^^ @@ -64,7 +64,7 @@ LL | let _: String = format!("{:?}", path); = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed error: unnecessary `Debug` formatting in `format!` args - --> tests/ui/unnecessary_path_debug_formatting.rs:39:37 + --> tests/ui/unnecessary_path_debug_formatting.rs:40:37 | LL | let _: String = format!("{:?}", path_buf); | ^^^^^^^^ @@ -73,7 +73,7 @@ LL | let _: String = format!("{:?}", path_buf); = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed error: unnecessary `Debug` formatting in `println!` args - --> tests/ui/unnecessary_path_debug_formatting.rs:42:22 + --> tests/ui/unnecessary_path_debug_formatting.rs:43:22 | LL | println!("{:?}", &*deref_path); | ^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed index 498dab3eb5070..b064a8b8f46fb 100644 --- a/tests/ui/unnecessary_to_owned.fixed +++ b/tests/ui/unnecessary_to_owned.fixed @@ -1,13 +1,14 @@ #![allow( + clippy::manual_async_fn, clippy::needless_borrow, clippy::needless_borrows_for_generic_args, - clippy::ptr_arg, - clippy::manual_async_fn, clippy::needless_lifetimes, - clippy::owned_cow + clippy::owned_cow, + clippy::ptr_arg, + clippy::uninlined_format_args )] #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] -#![allow(clippy::uninlined_format_args)] + use std::borrow::Cow; use std::ffi::{CStr, CString, OsStr, OsString}; use std::ops::Deref; diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs index 84ac575ddf521..7954a4ad4ce77 100644 --- a/tests/ui/unnecessary_to_owned.rs +++ b/tests/ui/unnecessary_to_owned.rs @@ -4,7 +4,8 @@ clippy::needless_borrows_for_generic_args, clippy::needless_lifetimes, clippy::owned_cow, - clippy::ptr_arg + clippy::ptr_arg, + clippy::uninlined_format_args )] #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] diff --git a/tests/ui/unnecessary_to_owned.stderr b/tests/ui/unnecessary_to_owned.stderr index 8926db34da8c8..6c52be8393010 100644 --- a/tests/ui/unnecessary_to_owned.stderr +++ b/tests/ui/unnecessary_to_owned.stderr @@ -1,11 +1,11 @@ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:217:64 + --> tests/ui/unnecessary_to_owned.rs:218:64 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:217:20 + --> tests/ui/unnecessary_to_owned.rs:218:20 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,55 +13,55 @@ LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()) = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]` error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:219:40 + --> tests/ui/unnecessary_to_owned.rs:220:40 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:219:21 + --> tests/ui/unnecessary_to_owned.rs:220:21 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:221:48 + --> tests/ui/unnecessary_to_owned.rs:222:48 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:221:19 + --> tests/ui/unnecessary_to_owned.rs:222:19 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:223:35 + --> tests/ui/unnecessary_to_owned.rs:224:35 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:223:18 + --> tests/ui/unnecessary_to_owned.rs:224:18 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:225:39 + --> tests/ui/unnecessary_to_owned.rs:226:39 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:225:20 + --> tests/ui/unnecessary_to_owned.rs:226:20 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^^^^^^^^^ error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:65:36 + --> tests/ui/unnecessary_to_owned.rs:66:36 | LL | require_c_str(&Cow::from(c_str).into_owned()); | ^^^^^^^^^^^^^ help: remove this @@ -70,391 +70,391 @@ LL | require_c_str(&Cow::from(c_str).into_owned()); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:67:19 + --> tests/ui/unnecessary_to_owned.rs:68:19 | LL | require_c_str(&c_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_os_string` - --> tests/ui/unnecessary_to_owned.rs:70:20 + --> tests/ui/unnecessary_to_owned.rs:71:20 | LL | require_os_str(&os_str.to_os_string()); | ^^^^^^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:72:38 + --> tests/ui/unnecessary_to_owned.rs:73:38 | LL | require_os_str(&Cow::from(os_str).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:74:20 + --> tests/ui/unnecessary_to_owned.rs:75:20 | LL | require_os_str(&os_str.to_owned()); | ^^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_path_buf` - --> tests/ui/unnecessary_to_owned.rs:77:18 + --> tests/ui/unnecessary_to_owned.rs:78:18 | LL | require_path(&path.to_path_buf()); | ^^^^^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:79:34 + --> tests/ui/unnecessary_to_owned.rs:80:34 | LL | require_path(&Cow::from(path).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:81:18 + --> tests/ui/unnecessary_to_owned.rs:82:18 | LL | require_path(&path.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:84:17 + --> tests/ui/unnecessary_to_owned.rs:85:17 | LL | require_str(&s.to_string()); | ^^^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:86:30 + --> tests/ui/unnecessary_to_owned.rs:87:30 | LL | require_str(&Cow::from(s).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:88:17 + --> tests/ui/unnecessary_to_owned.rs:89:17 | LL | require_str(&s.to_owned()); | ^^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:90:17 + --> tests/ui/unnecessary_to_owned.rs:91:17 | LL | require_str(&x_ref.to_string()); | ^^^^^^^^^^^^^^^^^^ help: use: `x_ref.as_ref()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:93:19 + --> tests/ui/unnecessary_to_owned.rs:94:19 | LL | require_slice(&slice.to_vec()); | ^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:95:36 + --> tests/ui/unnecessary_to_owned.rs:96:36 | LL | require_slice(&Cow::from(slice).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:97:19 + --> tests/ui/unnecessary_to_owned.rs:98:19 | LL | require_slice(&array.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `array.as_ref()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:99:19 + --> tests/ui/unnecessary_to_owned.rs:100:19 | LL | require_slice(&array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref.as_ref()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:101:19 + --> tests/ui/unnecessary_to_owned.rs:102:19 | LL | require_slice(&slice.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:105:42 + --> tests/ui/unnecessary_to_owned.rs:106:42 | LL | require_x(&Cow::::Owned(x.clone()).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:109:25 + --> tests/ui/unnecessary_to_owned.rs:110:25 | LL | require_deref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:111:26 + --> tests/ui/unnecessary_to_owned.rs:112:26 | LL | require_deref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:113:24 + --> tests/ui/unnecessary_to_owned.rs:114:24 | LL | require_deref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:115:23 + --> tests/ui/unnecessary_to_owned.rs:116:23 | LL | require_deref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:117:25 + --> tests/ui/unnecessary_to_owned.rs:118:25 | LL | require_deref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:120:30 + --> tests/ui/unnecessary_to_owned.rs:121:30 | LL | require_impl_deref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:122:31 + --> tests/ui/unnecessary_to_owned.rs:123:31 | LL | require_impl_deref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:124:29 + --> tests/ui/unnecessary_to_owned.rs:125:29 | LL | require_impl_deref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:126:28 + --> tests/ui/unnecessary_to_owned.rs:127:28 | LL | require_impl_deref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:128:30 + --> tests/ui/unnecessary_to_owned.rs:129:30 | LL | require_impl_deref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:131:29 + --> tests/ui/unnecessary_to_owned.rs:132:29 | LL | require_deref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:131:43 + --> tests/ui/unnecessary_to_owned.rs:132:43 | LL | require_deref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:134:29 + --> tests/ui/unnecessary_to_owned.rs:135:29 | LL | require_deref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:134:47 + --> tests/ui/unnecessary_to_owned.rs:135:47 | LL | require_deref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:138:26 + --> tests/ui/unnecessary_to_owned.rs:139:26 | LL | require_as_ref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:140:27 + --> tests/ui/unnecessary_to_owned.rs:141:27 | LL | require_as_ref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:142:25 + --> tests/ui/unnecessary_to_owned.rs:143:25 | LL | require_as_ref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:144:24 + --> tests/ui/unnecessary_to_owned.rs:145:24 | LL | require_as_ref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:146:24 + --> tests/ui/unnecessary_to_owned.rs:147:24 | LL | require_as_ref_str(x.to_owned()); | ^^^^^^^^^^^^ help: use: `&x` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:148:26 + --> tests/ui/unnecessary_to_owned.rs:149:26 | LL | require_as_ref_slice(array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:150:26 + --> tests/ui/unnecessary_to_owned.rs:151:26 | LL | require_as_ref_slice(array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:152:26 + --> tests/ui/unnecessary_to_owned.rs:153:26 | LL | require_as_ref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:155:31 + --> tests/ui/unnecessary_to_owned.rs:156:31 | LL | require_impl_as_ref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:157:32 + --> tests/ui/unnecessary_to_owned.rs:158:32 | LL | require_impl_as_ref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:159:30 + --> tests/ui/unnecessary_to_owned.rs:160:30 | LL | require_impl_as_ref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:161:29 + --> tests/ui/unnecessary_to_owned.rs:162:29 | LL | require_impl_as_ref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:163:29 + --> tests/ui/unnecessary_to_owned.rs:164:29 | LL | require_impl_as_ref_str(x.to_owned()); | ^^^^^^^^^^^^ help: use: `&x` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:165:31 + --> tests/ui/unnecessary_to_owned.rs:166:31 | LL | require_impl_as_ref_slice(array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:167:31 + --> tests/ui/unnecessary_to_owned.rs:168:31 | LL | require_impl_as_ref_slice(array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:169:31 + --> tests/ui/unnecessary_to_owned.rs:170:31 | LL | require_impl_as_ref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:172:30 + --> tests/ui/unnecessary_to_owned.rs:173:30 | LL | require_as_ref_str_slice(s.to_owned(), array.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:172:44 + --> tests/ui/unnecessary_to_owned.rs:173:44 | LL | require_as_ref_str_slice(s.to_owned(), array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:175:30 + --> tests/ui/unnecessary_to_owned.rs:176:30 | LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:175:44 + --> tests/ui/unnecessary_to_owned.rs:176:44 | LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:178:30 + --> tests/ui/unnecessary_to_owned.rs:179:30 | LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:178:44 + --> tests/ui/unnecessary_to_owned.rs:179:44 | LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:181:30 + --> tests/ui/unnecessary_to_owned.rs:182:30 | LL | require_as_ref_slice_str(array.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:181:48 + --> tests/ui/unnecessary_to_owned.rs:182:48 | LL | require_as_ref_slice_str(array.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:184:30 + --> tests/ui/unnecessary_to_owned.rs:185:30 | LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:184:52 + --> tests/ui/unnecessary_to_owned.rs:185:52 | LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:187:30 + --> tests/ui/unnecessary_to_owned.rs:188:30 | LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:187:48 + --> tests/ui/unnecessary_to_owned.rs:188:48 | LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:191:20 + --> tests/ui/unnecessary_to_owned.rs:192:20 | LL | let _ = x.join(&x_ref.to_string()); | ^^^^^^^^^^^^^^^^^^ help: use: `x_ref` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:194:13 + --> tests/ui/unnecessary_to_owned.rs:195:13 | LL | let _ = slice.to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:196:13 + --> tests/ui/unnecessary_to_owned.rs:197:13 | LL | let _ = slice.to_owned().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:199:13 + --> tests/ui/unnecessary_to_owned.rs:200:13 | LL | let _ = IntoIterator::into_iter(slice.to_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:201:13 + --> tests/ui/unnecessary_to_owned.rs:202:13 | LL | let _ = IntoIterator::into_iter(slice.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:229:26 + --> tests/ui/unnecessary_to_owned.rs:230:26 | LL | let _ref_str: &str = &String::from_utf8(slice.to_vec()).expect("not UTF-8"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -466,7 +466,7 @@ LL + let _ref_str: &str = core::str::from_utf8(&slice).expect("not UTF-8"); | error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:231:26 + --> tests/ui/unnecessary_to_owned.rs:232:26 | LL | let _ref_str: &str = &String::from_utf8(b"foo".to_vec()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -478,7 +478,7 @@ LL + let _ref_str: &str = core::str::from_utf8(b"foo").unwrap(); | error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:233:26 + --> tests/ui/unnecessary_to_owned.rs:234:26 | LL | let _ref_str: &str = &String::from_utf8(b"foo".as_slice().to_owned()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -490,7 +490,7 @@ LL + let _ref_str: &str = core::str::from_utf8(b"foo".as_slice()).unwrap(); | error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:291:14 + --> tests/ui/unnecessary_to_owned.rs:292:14 | LL | for t in file_types.to_vec() { | ^^^^^^^^^^^^^^^^^^^ @@ -503,49 +503,49 @@ LL ~ let path = match get_file_path(t) { | error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:357:24 + --> tests/ui/unnecessary_to_owned.rs:358:24 | LL | Box::new(build(y.to_string())) | ^^^^^^^^^^^^^ help: use: `y` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:467:12 + --> tests/ui/unnecessary_to_owned.rs:468:12 | LL | id("abc".to_string()) | ^^^^^^^^^^^^^^^^^ help: use: `"abc"` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:611:37 + --> tests/ui/unnecessary_to_owned.rs:612:37 | LL | IntoFuture::into_future(foo([].to_vec(), &0)); | ^^^^^^^^^^^ help: use: `[]` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:622:18 + --> tests/ui/unnecessary_to_owned.rs:623:18 | LL | s.remove(&a.to_vec()); | ^^^^^^^^^^^ help: replace it with: `a` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:627:14 + --> tests/ui/unnecessary_to_owned.rs:628:14 | LL | s.remove(&"b".to_owned()); | ^^^^^^^^^^^^^^^ help: replace it with: `"b"` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:629:14 + --> tests/ui/unnecessary_to_owned.rs:630:14 | LL | s.remove(&"b".to_string()); | ^^^^^^^^^^^^^^^^ help: replace it with: `"b"` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:635:14 + --> tests/ui/unnecessary_to_owned.rs:636:14 | LL | s.remove(&["b"].to_vec()); | ^^^^^^^^^^^^^^^ help: replace it with: `["b"].as_slice()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:637:14 + --> tests/ui/unnecessary_to_owned.rs:638:14 | LL | s.remove(&(&["b"]).to_vec()); | ^^^^^^^^^^^^^^^^^^ help: replace it with: `(&["b"]).as_slice()` From aba76d0e78aeb031f941c7a3466eb4d9d13d7a85 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 24 Mar 2025 23:19:18 +0000 Subject: [PATCH 0302/2248] Allow defining opaques in statics and consts --- clippy_utils/src/ast_utils/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index 54261079fcad8..6023ae9cc7b16 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -336,12 +336,14 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { mutability: lm, expr: le, safety: ls, + define_opaque: _, }), Static(box StaticItem { 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()), ( @@ -350,12 +352,14 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { generics: lg, ty: lt, expr: le, + define_opaque: _, }), Const(box ConstItem { defaultness: rd, 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()), ( @@ -490,12 +494,14 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { mutability: lm, expr: le, safety: ls, + define_opaque: _, }), Static(box StaticItem { 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, ( @@ -557,12 +563,14 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { generics: lg, ty: lt, expr: le, + define_opaque: _, }), Const(box ConstItem { defaultness: rd, 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()), ( From 94233fb0ee1a683d076d933aa2c8f77c8cd9f66c Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 1 Mar 2025 17:53:49 +0100 Subject: [PATCH 0303/2248] Unify `manual_unwrap_or` and `manual_unwrap_or_default` code Both lints share a lot of characteristics but were implemented in unrelated ways. This unifies them, saving around 100 SLOC in the process, and making one more test trigger the lint. Also, this removes useless blocks in suggestions. --- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/lib.rs | 2 - clippy_lints/src/manual_unwrap_or_default.rs | 212 ------------- clippy_lints/src/matches/manual_unwrap_or.rs | 294 ++++++++++++------- clippy_lints/src/matches/mod.rs | 38 +++ clippy_utils/src/higher.rs | 6 + clippy_utils/src/lib.rs | 1 + tests/ui/manual_unwrap_or.fixed | 30 +- tests/ui/manual_unwrap_or.rs | 15 +- tests/ui/manual_unwrap_or.stderr | 39 ++- tests/ui/manual_unwrap_or_default.fixed | 7 +- tests/ui/manual_unwrap_or_default.rs | 12 +- tests/ui/manual_unwrap_or_default.stderr | 13 +- 13 files changed, 322 insertions(+), 349 deletions(-) delete mode 100644 clippy_lints/src/manual_unwrap_or_default.rs diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index a9b6b369c4c39..c2274f0a619cf 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -335,7 +335,6 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::manual_slice_size_calculation::MANUAL_SLICE_SIZE_CALCULATION_INFO, crate::manual_string_new::MANUAL_STRING_NEW_INFO, crate::manual_strip::MANUAL_STRIP_INFO, - crate::manual_unwrap_or_default::MANUAL_UNWRAP_OR_DEFAULT_INFO, crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO, crate::map_unit_fn::RESULT_MAP_UNIT_FN_INFO, crate::match_result_ok::MATCH_RESULT_OK_INFO, @@ -345,6 +344,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::matches::MANUAL_MAP_INFO, crate::matches::MANUAL_OK_ERR_INFO, crate::matches::MANUAL_UNWRAP_OR_INFO, + crate::matches::MANUAL_UNWRAP_OR_DEFAULT_INFO, crate::matches::MATCH_AS_REF_INFO, crate::matches::MATCH_BOOL_INFO, crate::matches::MATCH_LIKE_MATCHES_MACRO_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2d390be5248c6..6f2a4a4c529da 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -226,7 +226,6 @@ mod manual_rotate; mod manual_slice_size_calculation; mod manual_string_new; mod manual_strip; -mod manual_unwrap_or_default; mod map_unit_fn; mod match_result_ok; mod matches; @@ -960,7 +959,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations)); store.register_late_pass(move |_| Box::new(assigning_clones::AssigningClones::new(conf))); store.register_late_pass(|_| Box::new(zero_repeat_side_effects::ZeroRepeatSideEffects)); - store.register_late_pass(|_| Box::new(manual_unwrap_or_default::ManualUnwrapOrDefault)); store.register_late_pass(|_| Box::new(integer_division_remainder_used::IntegerDivisionRemainderUsed)); store.register_late_pass(move |_| Box::new(macro_metavars_in_unsafe::ExprMetavarsInUnsafe::new(conf))); store.register_late_pass(move |_| Box::new(string_patterns::StringPatterns::new(conf))); diff --git a/clippy_lints/src/manual_unwrap_or_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs deleted file mode 100644 index 1aa12e72a6d45..0000000000000 --- a/clippy_lints/src/manual_unwrap_or_default.rs +++ /dev/null @@ -1,212 +0,0 @@ -use rustc_errors::Applicability; -use rustc_hir::def::Res; -use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::GenericArgKind; -use rustc_session::declare_lint_pass; -use rustc_span::sym; - -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::higher::IfLetOrMatch; -use clippy_utils::sugg::Sugg; -use clippy_utils::ty::{expr_type_is_certain, implements_trait}; -use clippy_utils::{is_default_equivalent, is_in_const_context, path_res, peel_blocks, span_contains_comment}; - -declare_clippy_lint! { - /// ### What it does - /// Checks if a `match` or `if let` expression can be simplified using - /// `.unwrap_or_default()`. - /// - /// ### Why is this bad? - /// It can be done in one call with `.unwrap_or_default()`. - /// - /// ### Example - /// ```no_run - /// let x: Option = Some(String::new()); - /// let y: String = match x { - /// Some(v) => v, - /// None => String::new(), - /// }; - /// - /// let x: Option> = Some(Vec::new()); - /// let y: Vec = if let Some(v) = x { - /// v - /// } else { - /// Vec::new() - /// }; - /// ``` - /// Use instead: - /// ```no_run - /// let x: Option = Some(String::new()); - /// let y: String = x.unwrap_or_default(); - /// - /// let x: Option> = Some(Vec::new()); - /// let y: Vec = x.unwrap_or_default(); - /// ``` - #[clippy::version = "1.79.0"] - pub MANUAL_UNWRAP_OR_DEFAULT, - suspicious, - "check if a `match` or `if let` can be simplified with `unwrap_or_default`" -} - -declare_lint_pass!(ManualUnwrapOrDefault => [MANUAL_UNWRAP_OR_DEFAULT]); - -fn get_some<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option { - if let PatKind::TupleStruct(QPath::Resolved(_, path), &[pat], _) = pat.kind - && let PatKind::Binding(_, pat_id, _, _) = pat.kind - && let Some(def_id) = path.res.opt_def_id() - // Since it comes from a pattern binding, we need to get the parent to actually match - // against it. - && let Some(def_id) = cx.tcx.opt_parent(def_id) - && (cx.tcx.lang_items().get(LangItem::OptionSome) == Some(def_id) - || cx.tcx.lang_items().get(LangItem::ResultOk) == Some(def_id)) - { - Some(pat_id) - } else { - None - } -} - -fn get_none<'tcx>(cx: &LateContext<'tcx>, arm: &Arm<'tcx>) -> Option<&'tcx Expr<'tcx>> { - if let PatKind::Expr(PatExpr { kind: PatExprKind::Path(QPath::Resolved(_, path)), .. }) = arm.pat.kind - && let Some(def_id) = path.res.opt_def_id() - // Since it comes from a pattern binding, we need to get the parent to actually match - // against it. - && let Some(def_id) = cx.tcx.opt_parent(def_id) - && cx.tcx.lang_items().get(LangItem::OptionNone) == Some(def_id) - { - Some(arm.body) - } else if let PatKind::TupleStruct(QPath::Resolved(_, path), _, _)= arm.pat.kind - && let Some(def_id) = path.res.opt_def_id() - // Since it comes from a pattern binding, we need to get the parent to actually match - // against it. - && let Some(def_id) = cx.tcx.opt_parent(def_id) - && cx.tcx.lang_items().get(LangItem::ResultErr) == Some(def_id) - { - Some(arm.body) - } else if let PatKind::Wild = arm.pat.kind { - // We consider that the `Some` check will filter it out if it's not right. - Some(arm.body) - } else { - None - } -} - -fn get_some_and_none_bodies<'tcx>( - cx: &LateContext<'tcx>, - arm1: &'tcx Arm<'tcx>, - arm2: &'tcx Arm<'tcx>, -) -> Option<((&'tcx Expr<'tcx>, HirId), &'tcx Expr<'tcx>)> { - if let Some(binding_id) = get_some(cx, arm1.pat) - && let Some(body_none) = get_none(cx, arm2) - { - Some(((arm1.body, binding_id), body_none)) - } else if let Some(binding_id) = get_some(cx, arm2.pat) - && let Some(body_none) = get_none(cx, arm1) - { - Some(((arm2.body, binding_id), body_none)) - } else { - None - } -} - -#[allow(clippy::needless_pass_by_value)] -fn handle<'tcx>(cx: &LateContext<'tcx>, if_let_or_match: IfLetOrMatch<'tcx>, expr: &'tcx Expr<'tcx>) { - // Get expr_name ("if let" or "match" depending on kind of expression), the condition, the body for - // the some arm, the body for the none arm and the binding id of the some arm - let (expr_name, condition, body_some, body_none, binding_id) = match if_let_or_match { - IfLetOrMatch::Match(condition, [arm1, arm2], MatchSource::Normal | MatchSource::ForLoopDesugar) - // Make sure there are no guards to keep things simple - if arm1.guard.is_none() - && arm2.guard.is_none() - // Get the some and none bodies and the binding id of the some arm - && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2) => - { - ("match", condition, body_some, body_none, binding_id) - }, - IfLetOrMatch::IfLet(condition, pat, if_expr, Some(else_expr), _) - if let Some(binding_id) = get_some(cx, pat) => - { - ("if let", condition, if_expr, else_expr, binding_id) - }, - _ => { - // All other cases (match with number of arms != 2, if let without else, etc.) - return; - }, - }; - - // We check if the return type of the expression implements Default. - let expr_type = cx.typeck_results().expr_ty(expr); - if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default) - && implements_trait(cx, expr_type, default_trait_id, &[]) - // We check if the initial condition implements Default. - && let Some(condition_ty) = cx.typeck_results().expr_ty(condition).walk().nth(1) - && let GenericArgKind::Type(condition_ty) = condition_ty.unpack() - && implements_trait(cx, condition_ty, default_trait_id, &[]) - // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`. - && let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind - && let Res::Local(local_id) = path.res - && local_id == binding_id - // We now check the `None` arm is calling a method equivalent to `Default::default`. - && let body_none = peel_blocks(body_none) - && is_default_equivalent(cx, body_none) - && let Some(receiver) = Sugg::hir_opt(cx, condition).map(Sugg::maybe_paren) - { - // Machine applicable only if there are no comments present - let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) { - Applicability::MaybeIncorrect - } else { - Applicability::MachineApplicable - }; - - // We now check if the condition is a None variant, in which case we need to specify the type - if path_res(cx, condition) - .opt_def_id() - .is_some_and(|id| Some(cx.tcx.parent(id)) == cx.tcx.lang_items().option_none_variant()) - { - return span_lint_and_sugg( - cx, - MANUAL_UNWRAP_OR_DEFAULT, - expr.span, - format!("{expr_name} can be simplified with `.unwrap_or_default()`"), - "replace it with", - format!("{receiver}::<{expr_type}>.unwrap_or_default()"), - applicability, - ); - } - - // We check if the expression type is still uncertain, in which case we ask the user to specify it - if !expr_type_is_certain(cx, condition) { - return span_lint_and_sugg( - cx, - MANUAL_UNWRAP_OR_DEFAULT, - expr.span, - format!("{expr_name} can be simplified with `.unwrap_or_default()`"), - format!("ascribe the type {expr_type} and replace your expression with"), - format!("{receiver}.unwrap_or_default()"), - Applicability::Unspecified, - ); - } - - span_lint_and_sugg( - cx, - MANUAL_UNWRAP_OR_DEFAULT, - expr.span, - format!("{expr_name} can be simplified with `.unwrap_or_default()`"), - "replace it with", - format!("{receiver}.unwrap_or_default()"), - applicability, - ); - } -} - -impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if let Some(if_let_or_match) = IfLetOrMatch::parse(cx, expr) - && !expr.span.from_expansion() - && !is_in_const_context(cx) - { - handle(cx, if_let_or_match, expr); - } - } -} diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs index 5394b7af8ff8e..b64ae0b24d818 100644 --- a/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/clippy_lints/src/matches/manual_unwrap_or.rs @@ -1,133 +1,219 @@ use clippy_utils::consts::ConstEvalCtxt; -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{SpanRangeExt, indent_of, reindent_multiline}; -use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::usage::contains_return_break_continue_macro; -use clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg}; +use clippy_utils::source::{SpanRangeExt as _, indent_of, reindent_multiline}; use rustc_errors::Applicability; -use rustc_hir::LangItem::{OptionNone, ResultErr}; -use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Arm, Expr, Pat, PatExpr, PatExprKind, PatKind}; -use rustc_lint::LateContext; -use rustc_middle::ty::Ty; +use rustc_hir::def::Res; +use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, Pat, PatExpr, PatExprKind, PatKind, QPath}; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::ty::{GenericArgKind, Ty}; use rustc_span::sym; -use super::MANUAL_UNWRAP_OR; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::{expr_type_is_certain, get_type_diagnostic_name, implements_trait}; +use clippy_utils::{is_default_equivalent, is_lint_allowed, path_res, peel_blocks, span_contains_comment}; -pub(super) fn check_match<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx Expr<'tcx>, - scrutinee: &'tcx Expr<'_>, - arms: &'tcx [Arm<'_>], -) { - let ty = cx.typeck_results().expr_ty(scrutinee); - if let Some((or_arm, unwrap_arm)) = applicable_or_arm(cx, arms) { - check_and_lint(cx, expr, unwrap_arm.pat, scrutinee, unwrap_arm.body, or_arm.body, ty); +use super::{MANUAL_UNWRAP_OR, MANUAL_UNWRAP_OR_DEFAULT}; + +fn get_some(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option { + if let PatKind::TupleStruct(QPath::Resolved(_, path), &[pat], _) = pat.kind + && let PatKind::Binding(_, pat_id, _, _) = pat.kind + && let Some(def_id) = path.res.opt_def_id() + // Since it comes from a pattern binding, we need to get the parent to actually match + // against it. + && let Some(def_id) = cx.tcx.opt_parent(def_id) + && let Some(lang_item) = cx.tcx.lang_items().from_def_id(def_id) + && matches!(lang_item, LangItem::OptionSome | LangItem::ResultOk) + { + Some(pat_id) + } else { + None } } -pub(super) fn check_if_let<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx Expr<'_>, - let_pat: &'tcx Pat<'_>, - let_expr: &'tcx Expr<'_>, - then_expr: &'tcx Expr<'_>, - else_expr: &'tcx Expr<'_>, -) { - let ty = cx.typeck_results().expr_ty(let_expr); - let then_ty = cx.typeck_results().expr_ty(then_expr); - // The signature is `fn unwrap_or(self: Option, default: T) -> T`. - // When `expr_adjustments(then_expr).is_empty()`, `T` should equate to `default`'s type. - // Otherwise, type error will occur. - if cx.typeck_results().expr_adjustments(then_expr).is_empty() - && let rustc_middle::ty::Adt(_did, args) = ty.kind() - && let Some(some_ty) = args.first().and_then(|arg| arg.as_type()) - && some_ty != then_ty +fn get_none<'tcx>(cx: &LateContext<'_>, arm: &Arm<'tcx>) -> Option<&'tcx Expr<'tcx>> { + if let PatKind::Expr(PatExpr { kind: PatExprKind::Path(QPath::Resolved(_, path)), .. }) = arm.pat.kind + && let Some(def_id) = path.res.opt_def_id() + // Since it comes from a pattern binding, we need to get the parent to actually match + // against it. + && let Some(def_id) = cx.tcx.opt_parent(def_id) + && cx.tcx.lang_items().get(LangItem::OptionNone) == Some(def_id) { - return; + Some(arm.body) + } else if let PatKind::TupleStruct(QPath::Resolved(_, path), _, _)= arm.pat.kind + && let Some(def_id) = path.res.opt_def_id() + // Since it comes from a pattern binding, we need to get the parent to actually match + // against it. + && let Some(def_id) = cx.tcx.opt_parent(def_id) + && cx.tcx.lang_items().get(LangItem::ResultErr) == Some(def_id) + { + Some(arm.body) + } else if let PatKind::Wild = arm.pat.kind { + // We consider that the `Some` check will filter it out if it's not right. + Some(arm.body) + } else { + None } - check_and_lint(cx, expr, let_pat, let_expr, then_expr, peel_blocks(else_expr), ty); } -fn check_and_lint<'tcx>( +fn get_some_and_none_bodies<'tcx>( cx: &LateContext<'tcx>, - expr: &'tcx Expr<'_>, - let_pat: &'tcx Pat<'_>, - let_expr: &'tcx Expr<'_>, - then_expr: &'tcx Expr<'_>, - else_expr: &'tcx Expr<'_>, - ty: Ty<'tcx>, + arm1: &'tcx Arm<'tcx>, + arm2: &'tcx Arm<'tcx>, +) -> Option<((&'tcx Expr<'tcx>, HirId), &'tcx Expr<'tcx>)> { + if let Some(binding_id) = get_some(cx, arm1.pat) + && let Some(body_none) = get_none(cx, arm2) + { + Some(((arm1.body, binding_id), body_none)) + } else if let Some(binding_id) = get_some(cx, arm2.pat) + && let Some(body_none) = get_none(cx, arm1) + { + Some(((arm2.body, binding_id), body_none)) + } else { + None + } +} + +fn handle( + cx: &LateContext<'_>, + expr: &Expr<'_>, + expr_name: &'static str, + condition: &Expr<'_>, + body_some: &Expr<'_>, + body_none: &Expr<'_>, + binding_id: HirId, ) { - if let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = let_pat.kind - && let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id) - && let Some(variant_id) = cx.tcx.opt_parent(ctor_id) - && (cx.tcx.lang_items().option_some_variant() == Some(variant_id) - || cx.tcx.lang_items().result_ok_variant() == Some(variant_id)) - && let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind - && path_to_local_id(peel_blocks(then_expr), binding_hir_id) - && cx.typeck_results().expr_adjustments(then_expr).is_empty() - && let Some(ty_name) = find_type_name(cx, ty) - && let Some(or_body_snippet) = else_expr.span.get_source_text(cx) - && let Some(indent) = indent_of(cx, expr.span) - && ConstEvalCtxt::new(cx).eval_simple(else_expr).is_some() + // Only deal with situations where both alternatives return the same non-adjusted type. + if cx.typeck_results().expr_ty(body_some) != cx.typeck_results().expr_ty(body_none) { + return; + } + + let expr_type = cx.typeck_results().expr_ty(expr); + // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`. + if let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind + && let Res::Local(local_id) = path.res + && local_id == binding_id { - lint(cx, expr, let_expr, ty_name, &or_body_snippet, indent); + // Machine applicable only if there are no comments present + let mut applicability = if span_contains_comment(cx.sess().source_map(), expr.span) { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + }; + let receiver = Sugg::hir_with_applicability(cx, condition, "_", &mut applicability).maybe_paren(); + + // We now check the `None` arm is calling a method equivalent to `Default::default`. + if !is_lint_allowed(cx, MANUAL_UNWRAP_OR_DEFAULT, expr.hir_id) + // We check if the return type of the expression implements Default. + && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default) + && implements_trait(cx, expr_type, default_trait_id, &[]) + // We check if the initial condition implements Default. + && let Some(condition_ty) = cx.typeck_results().expr_ty(condition).walk().nth(1) + && let GenericArgKind::Type(condition_ty) = condition_ty.unpack() + && implements_trait(cx, condition_ty, default_trait_id, &[]) + && is_default_equivalent(cx, peel_blocks(body_none)) + { + // We now check if the condition is a None variant, in which case we need to specify the type + if path_res(cx, condition) + .opt_def_id() + .is_some_and(|id| Some(cx.tcx.parent(id)) == cx.tcx.lang_items().option_none_variant()) + { + return span_lint_and_sugg( + cx, + MANUAL_UNWRAP_OR_DEFAULT, + expr.span, + format!("{expr_name} can be simplified with `.unwrap_or_default()`"), + "replace it with", + format!("{receiver}::<{expr_type}>.unwrap_or_default()"), + applicability, + ); + } + + // We check if the expression type is still uncertain, in which case we ask the user to specify it + if !expr_type_is_certain(cx, condition) { + return span_lint_and_sugg( + cx, + MANUAL_UNWRAP_OR_DEFAULT, + expr.span, + format!("{expr_name} can be simplified with `.unwrap_or_default()`"), + format!("ascribe the type {expr_type} and replace your expression with"), + format!("{receiver}.unwrap_or_default()"), + Applicability::Unspecified, + ); + } + + span_lint_and_sugg( + cx, + MANUAL_UNWRAP_OR_DEFAULT, + expr.span, + format!("{expr_name} can be simplified with `.unwrap_or_default()`"), + "replace it with", + format!("{receiver}.unwrap_or_default()"), + applicability, + ); + } else if let Some(ty_name) = find_type_name(cx, cx.typeck_results().expr_ty(condition)) + && cx.typeck_results().expr_adjustments(body_some).is_empty() + && let Some(or_body_snippet) = peel_blocks(body_none).span.get_source_text(cx) + && let Some(indent) = indent_of(cx, expr.span) + && ConstEvalCtxt::new(cx).eval_simple(body_none).is_some() + { + let reindented_or_body = reindent_multiline(&or_body_snippet, true, Some(indent)); + let mut app = Applicability::MachineApplicable; + let suggestion = Sugg::hir_with_context(cx, condition, expr.span.ctxt(), "..", &mut app).maybe_paren(); + span_lint_and_sugg( + cx, + MANUAL_UNWRAP_OR, + expr.span, + format!("this pattern reimplements `{ty_name}::unwrap_or`"), + "replace with", + format!("{suggestion}.unwrap_or({reindented_or_body})",), + app, + ); + } } } fn find_type_name<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<&'static str> { - if is_type_diagnostic_item(cx, ty, sym::Option) { - Some("Option") - } else if is_type_diagnostic_item(cx, ty, sym::Result) { - Some("Result") - } else { - None + match get_type_diagnostic_name(cx, ty)? { + sym::Option => Some("Option"), + sym::Result => Some("Result"), + _ => None, } } -fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<(&'a Arm<'a>, &'a Arm<'a>)> { - if arms.len() == 2 - && arms.iter().all(|arm| arm.guard.is_none()) - && let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| match arm.pat.kind { - PatKind::Expr(PatExpr { - hir_id, - kind: PatExprKind::Path(qpath), - .. - }) => is_res_lang_ctor(cx, cx.qpath_res(qpath, *hir_id), OptionNone), - PatKind::TupleStruct(ref qpath, [pat], _) => { - matches!(pat.kind, PatKind::Wild) - && is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr) - }, - _ => false, - }) - && let unwrap_arm = &arms[1 - idx] - && !contains_return_break_continue_macro(or_arm.body) +pub fn check_match<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + scrutinee: &'tcx Expr<'tcx>, + arms: &'tcx [Arm<'tcx>], +) { + if let [arm1, arm2] = arms + // Make sure there are no guards to keep things simple + && arm1.guard.is_none() + && arm2.guard.is_none() + // Get the some and none bodies and the binding id of the some arm + && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2) { - Some((or_arm, unwrap_arm)) - } else { - None + handle(cx, expr, "match", scrutinee, body_some, body_none, binding_id); } } -fn lint<'tcx>( +pub fn check_if_let<'tcx>( cx: &LateContext<'tcx>, - expr: &Expr<'tcx>, - scrutinee: &'tcx Expr<'_>, - ty_name: &str, - or_body_snippet: &str, - indent: usize, + expr: &'tcx Expr<'tcx>, + pat: &'tcx Pat<'tcx>, + scrutinee: &'tcx Expr<'tcx>, + then_expr: &'tcx Expr<'tcx>, + else_expr: &'tcx Expr<'tcx>, ) { - let reindented_or_body = reindent_multiline(or_body_snippet, true, Some(indent)); - - let mut app = Applicability::MachineApplicable; - let suggestion = sugg::Sugg::hir_with_context(cx, scrutinee, expr.span.ctxt(), "..", &mut app).maybe_paren(); - span_lint_and_sugg( - cx, - MANUAL_UNWRAP_OR, - expr.span, - format!("this pattern reimplements `{ty_name}::unwrap_or`"), - "replace with", - format!("{suggestion}.unwrap_or({reindented_or_body})",), - app, - ); + if let Some(binding_id) = get_some(cx, pat) { + handle( + cx, + expr, + "if let", + scrutinee, + peel_blocks(then_expr), + peel_blocks(else_expr), + binding_id, + ); + } } diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 2b9173e6f4122..ad299ae8f0f1a 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -722,6 +722,43 @@ declare_clippy_lint! { "finds patterns that can be encoded more concisely with `Option::unwrap_or` or `Result::unwrap_or`" } +declare_clippy_lint! { + /// ### What it does + /// Checks if a `match` or `if let` expression can be simplified using + /// `.unwrap_or_default()`. + /// + /// ### Why is this bad? + /// It can be done in one call with `.unwrap_or_default()`. + /// + /// ### Example + /// ```no_run + /// let x: Option = Some(String::new()); + /// let y: String = match x { + /// Some(v) => v, + /// None => String::new(), + /// }; + /// + /// let x: Option> = Some(Vec::new()); + /// let y: Vec = if let Some(v) = x { + /// v + /// } else { + /// Vec::new() + /// }; + /// ``` + /// Use instead: + /// ```no_run + /// let x: Option = Some(String::new()); + /// let y: String = x.unwrap_or_default(); + /// + /// let x: Option> = Some(Vec::new()); + /// let y: Vec = x.unwrap_or_default(); + /// ``` + #[clippy::version = "1.79.0"] + pub MANUAL_UNWRAP_OR_DEFAULT, + suspicious, + "check if a `match` or `if let` can be simplified with `unwrap_or_default`" +} + declare_clippy_lint! { /// ### What it does /// Checks for `match vec[idx]` or `match vec[n..m]`. @@ -1040,6 +1077,7 @@ impl_lint_pass!(Matches => [ NEEDLESS_MATCH, COLLAPSIBLE_MATCH, MANUAL_UNWRAP_OR, + MANUAL_UNWRAP_OR_DEFAULT, MATCH_ON_VEC_ITEMS, MATCH_STR_CASE_MISMATCH, SIGNIFICANT_DROP_IN_SCRUTINEE, diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs index c4d00002292c9..852378d50e8b4 100644 --- a/clippy_utils/src/higher.rs +++ b/clippy_utils/src/higher.rs @@ -176,6 +176,12 @@ impl<'hir> IfLetOrMatch<'hir> { ), } } + + pub fn scrutinee(&self) -> &'hir Expr<'hir> { + match self { + Self::Match(scrutinee, _, _) | Self::IfLet(scrutinee, _, _, _, _) => scrutinee, + } + } } /// An `if` or `if let` expression diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 1307ff79bc5dd..5f39af811cd99 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1027,6 +1027,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { ExprKind::Call(from_func, [arg]) => is_default_equivalent_from(cx, from_func, arg), ExprKind::Path(qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, e.hir_id), OptionNone), ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])), + ExprKind::Block(Block { stmts: [], expr, .. }, _) => expr.is_some_and(|e| is_default_equivalent(cx, e)), _ => false, } } diff --git a/tests/ui/manual_unwrap_or.fixed b/tests/ui/manual_unwrap_or.fixed index 07e4bdd483a8c..e12287a709395 100644 --- a/tests/ui/manual_unwrap_or.fixed +++ b/tests/ui/manual_unwrap_or.fixed @@ -18,11 +18,9 @@ fn option_unwrap_or() { // multiline case #[rustfmt::skip] - Some(1).unwrap_or({ - 42 + 42 - + 42 + 42 + 42 - + 42 + 42 + 42 - }); + Some(1).unwrap_or(42 + 42 + + 42 + 42 + 42 + + 42 + 42 + 42); // string case Some("Bob").unwrap_or("Alice"); @@ -125,11 +123,9 @@ fn result_unwrap_or() { // multiline case #[rustfmt::skip] - Ok::(1).unwrap_or({ - 42 + 42 - + 42 + 42 + 42 - + 42 + 42 + 42 - }); + Ok::(1).unwrap_or(42 + 42 + + 42 + 42 + 42 + + 42 + 42 + 42); // string case Ok::<&str, &str>("Bob").unwrap_or("Alice"); @@ -159,11 +155,7 @@ fn result_unwrap_or() { Ok(s) => s, Err(s) => s, }; - // could lint, but unused_variables takes care of it - match Ok::<&str, &str>("Alice") { - Ok(s) => s, - Err(s) => "Bob", - }; + Ok::<&str, &str>("Alice").unwrap_or("Bob"); Ok::(1).unwrap_or(42); @@ -250,4 +242,12 @@ mod issue_13018 { } } +fn implicit_deref(v: Vec) { + let _ = if let Some(s) = v.first() { s } else { "" }; +} + +fn allowed_manual_unwrap_or_zero() -> u32 { + Some(42).unwrap_or(0) +} + fn main() {} diff --git a/tests/ui/manual_unwrap_or.rs b/tests/ui/manual_unwrap_or.rs index c88b6f95da68e..53cffcab5b56c 100644 --- a/tests/ui/manual_unwrap_or.rs +++ b/tests/ui/manual_unwrap_or.rs @@ -216,8 +216,8 @@ fn result_unwrap_or() { Ok(s) => s, Err(s) => s, }; - // could lint, but unused_variables takes care of it match Ok::<&str, &str>("Alice") { + //~^ manual_unwrap_or Ok(s) => s, Err(s) => "Bob", }; @@ -316,4 +316,17 @@ mod issue_13018 { } } +fn implicit_deref(v: Vec) { + let _ = if let Some(s) = v.first() { s } else { "" }; +} + +fn allowed_manual_unwrap_or_zero() -> u32 { + if let Some(x) = Some(42) { + //~^ manual_unwrap_or + x + } else { + 0 + } +} + fn main() {} diff --git a/tests/ui/manual_unwrap_or.stderr b/tests/ui/manual_unwrap_or.stderr index a5deb55786e96..320e895fb8237 100644 --- a/tests/ui/manual_unwrap_or.stderr +++ b/tests/ui/manual_unwrap_or.stderr @@ -44,11 +44,9 @@ LL | | }; | help: replace with | -LL ~ Some(1).unwrap_or({ -LL + 42 + 42 -LL + + 42 + 42 + 42 -LL + + 42 + 42 + 42 -LL ~ }); +LL ~ Some(1).unwrap_or(42 + 42 +LL + + 42 + 42 + 42 +LL ~ + 42 + 42 + 42); | error: this pattern reimplements `Option::unwrap_or` @@ -145,11 +143,9 @@ LL | | }; | help: replace with | -LL ~ Ok::(1).unwrap_or({ -LL + 42 + 42 -LL + + 42 + 42 + 42 -LL + + 42 + 42 + 42 -LL ~ }); +LL ~ Ok::(1).unwrap_or(42 + 42 +LL + + 42 + 42 + 42 +LL ~ + 42 + 42 + 42); | error: this pattern reimplements `Result::unwrap_or` @@ -162,6 +158,16 @@ LL | | Err(_) => "Alice", LL | | }; | |_____^ help: replace with: `Ok::<&str, &str>("Bob").unwrap_or("Alice")` +error: this pattern reimplements `Result::unwrap_or` + --> tests/ui/manual_unwrap_or.rs:219:5 + | +LL | / match Ok::<&str, &str>("Alice") { +LL | | +LL | | Ok(s) => s, +LL | | Err(s) => "Bob", +LL | | }; + | |_____^ help: replace with: `Ok::<&str, &str>("Alice").unwrap_or("Bob")` + error: this pattern reimplements `Result::unwrap_or` --> tests/ui/manual_unwrap_or.rs:225:5 | @@ -184,5 +190,16 @@ LL | | None => 0, LL | | }; | |_________^ help: replace with: `some_macro!().unwrap_or(0)` -error: aborting due to 16 previous errors +error: this pattern reimplements `Option::unwrap_or` + --> tests/ui/manual_unwrap_or.rs:324:5 + | +LL | / if let Some(x) = Some(42) { +LL | | +LL | | x +LL | | } else { +LL | | 0 +LL | | } + | |_____^ help: replace with: `Some(42).unwrap_or(0)` + +error: aborting due to 18 previous errors diff --git a/tests/ui/manual_unwrap_or_default.fixed b/tests/ui/manual_unwrap_or_default.fixed index 832376fa5af15..f4a78ee761962 100644 --- a/tests/ui/manual_unwrap_or_default.fixed +++ b/tests/ui/manual_unwrap_or_default.fixed @@ -1,5 +1,5 @@ #![warn(clippy::manual_unwrap_or_default)] -#![allow(clippy::unnecessary_literal_unwrap, clippy::manual_unwrap_or)] +#![allow(clippy::unnecessary_literal_unwrap)] fn main() { let x: Option> = None; @@ -99,3 +99,8 @@ fn issue_12928() { let y = if let Some(Y(a, _)) = x { a } else { 0 }; let y = if let Some(Y(a, ..)) = x { a } else { 0 }; } + +// For symetry with `manual_unwrap_or` test +fn allowed_manual_unwrap_or_zero() -> u32 { + Some(42).unwrap_or_default() +} diff --git a/tests/ui/manual_unwrap_or_default.rs b/tests/ui/manual_unwrap_or_default.rs index bedb3f0af0f3e..60b84b621f611 100644 --- a/tests/ui/manual_unwrap_or_default.rs +++ b/tests/ui/manual_unwrap_or_default.rs @@ -1,5 +1,5 @@ #![warn(clippy::manual_unwrap_or_default)] -#![allow(clippy::unnecessary_literal_unwrap, clippy::manual_unwrap_or)] +#![allow(clippy::unnecessary_literal_unwrap)] fn main() { let x: Option> = None; @@ -135,3 +135,13 @@ fn issue_12928() { let y = if let Some(Y(a, _)) = x { a } else { 0 }; let y = if let Some(Y(a, ..)) = x { a } else { 0 }; } + +// For symetry with `manual_unwrap_or` test +fn allowed_manual_unwrap_or_zero() -> u32 { + if let Some(x) = Some(42) { + //~^ manual_unwrap_or_default + x + } else { + 0 + } +} diff --git a/tests/ui/manual_unwrap_or_default.stderr b/tests/ui/manual_unwrap_or_default.stderr index ca9aa159152e3..1e92f20a757e9 100644 --- a/tests/ui/manual_unwrap_or_default.stderr +++ b/tests/ui/manual_unwrap_or_default.stderr @@ -86,5 +86,16 @@ LL | | _ => 0, LL | | }, | |_________^ help: replace it with: `(*b).unwrap_or_default()` -error: aborting due to 8 previous errors +error: if let can be simplified with `.unwrap_or_default()` + --> tests/ui/manual_unwrap_or_default.rs:141:5 + | +LL | / if let Some(x) = Some(42) { +LL | | +LL | | x +LL | | } else { +LL | | 0 +LL | | } + | |_____^ help: replace it with: `Some(42).unwrap_or_default()` + +error: aborting due to 9 previous errors From 6509de3bfb06ba9d951cd4403512b1347f872d69 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 16 Feb 2025 16:27:09 +0100 Subject: [PATCH 0304/2248] Fix situations identified by `collapsible_if` new hits --- clippy.toml | 2 ++ clippy_lints/src/escape.rs | 9 +++--- clippy_lints/src/item_name_repetitions.rs | 21 +++++++------ clippy_lints/src/mem_replace.rs | 12 ++++---- clippy_lints/src/methods/map_clone.rs | 20 ++++++------- clippy_lints/src/methods/seek_from_current.rs | 10 +++---- .../src/mixed_read_write_in_expression.rs | 30 +++++++++---------- lintcheck/ci-config/clippy.toml | 1 + tests/clippy.toml | 1 + 9 files changed, 51 insertions(+), 55 deletions(-) diff --git a/clippy.toml b/clippy.toml index 7872933552b43..77573105d86a3 100644 --- a/clippy.toml +++ b/clippy.toml @@ -2,6 +2,8 @@ avoid-breaking-exported-api = false check-inconsistent-struct-field-initializers = true +lint-commented-code = true + [[disallowed-methods]] path = "rustc_lint::context::LintContext::lint" reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead" diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index de0fc2b1bf4bb..831d47ac48779 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -93,12 +93,11 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { // find `self` ty for this trait if relevant if let ItemKind::Trait(_, _, _, _, _, items) = item.kind { for trait_item in items { - if trait_item.id.owner_id.def_id == fn_def_id { + if trait_item.id.owner_id.def_id == fn_def_id // be sure we have `self` parameter in this function - if trait_item.kind == (AssocItemKind::Fn { has_self: true }) { - trait_self_ty = - Some(TraitRef::identity(cx.tcx, trait_item.id.owner_id.to_def_id()).self_ty()); - } + && trait_item.kind == (AssocItemKind::Fn { has_self: true }) + { + trait_self_ty = Some(TraitRef::identity(cx.tcx, trait_item.id.owner_id.to_def_id()).self_ty()); } } } diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs index 977fd5fce15be..0f800a68cdbf4 100644 --- a/clippy_lints/src/item_name_repetitions.rs +++ b/clippy_lints/src/item_name_repetitions.rs @@ -377,22 +377,21 @@ impl ItemNameRepetitions { "field name starts with the struct's name", ); } - if field_words.len() > item_name_words.len() { + if field_words.len() > item_name_words.len() // lint only if the end is not covered by the start - if field_words + && field_words .iter() .rev() .zip(item_name_words.iter().rev()) .all(|(a, b)| a == b) - { - span_lint_hir( - cx, - STRUCT_FIELD_NAMES, - field.hir_id, - field.span, - "field name ends with the struct's name", - ); - } + { + span_lint_hir( + cx, + STRUCT_FIELD_NAMES, + field.hir_id, + field.span, + "field name ends with the struct's name", + ); } } } diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 982e0695d7795..a54d835b538c1 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -304,14 +304,12 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace { && let ExprKind::Path(ref func_qpath) = func.kind && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id() && cx.tcx.is_diagnostic_item(sym::mem_replace, def_id) - { // Check that second argument is `Option::None` - if !check_replace_option_with_none(cx, src, dest, expr.span) - && !check_replace_option_with_some(cx, src, dest, expr.span, self.msrv) - && !check_replace_with_default(cx, src, dest, expr, self.msrv) - { - check_replace_with_uninit(cx, src, dest, expr.span); - } + && !check_replace_option_with_none(cx, src, dest, expr.span) + && !check_replace_option_with_some(cx, src, dest, expr.span, self.msrv) + && !check_replace_with_default(cx, src, dest, expr, self.msrv) + { + check_replace_with_uninit(cx, src, dest, expr.span); } } } diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index 128b3695f48b7..50b7578085fa2 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -114,19 +114,17 @@ fn handle_path( ) { if let Some(path_def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id() && cx.tcx.lang_items().get(LangItem::CloneFn) == Some(path_def_id) - { // The `copied` and `cloned` methods are only available on `&T` and `&mut T` in `Option` // and `Result`. - if let ty::Adt(_, args) = cx.typeck_results().expr_ty(recv).kind() - && let args = args.as_slice() - && let Some(ty) = args.iter().find_map(|generic_arg| generic_arg.as_type()) - && let ty::Ref(_, ty, Mutability::Not) = ty.kind() - && let ty::FnDef(_, lst) = cx.typeck_results().expr_ty(arg).kind() - && lst.iter().all(|l| l.as_type() == Some(*ty)) - && !should_call_clone_as_function(cx, *ty) - { - lint_path(cx, e.span, recv.span, is_copy(cx, ty.peel_refs())); - } + && let ty::Adt(_, args) = cx.typeck_results().expr_ty(recv).kind() + && let args = args.as_slice() + && let Some(ty) = args.iter().find_map(|generic_arg| generic_arg.as_type()) + && let ty::Ref(_, ty, Mutability::Not) = ty.kind() + && let ty::FnDef(_, lst) = cx.typeck_results().expr_ty(arg).kind() + && lst.iter().all(|l| l.as_type() == Some(*ty)) + && !should_call_clone_as_function(cx, *ty) + { + lint_path(cx, e.span, recv.span, is_copy(cx, ty.peel_refs())); } } diff --git a/clippy_lints/src/methods/seek_from_current.rs b/clippy_lints/src/methods/seek_from_current.rs index d318462e58415..28bf2d5aeec5b 100644 --- a/clippy_lints/src/methods/seek_from_current.rs +++ b/clippy_lints/src/methods/seek_from_current.rs @@ -38,13 +38,11 @@ fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) && let ExprKind::Path(ref path) = f.kind && let Some(ctor_call_id) = cx.qpath_res(path, f.hir_id).opt_def_id() && is_enum_variant_ctor(cx, sym::SeekFrom, sym!(Current), ctor_call_id) - { // check if argument of `SeekFrom::Current` is `0` - if let ExprKind::Lit(lit) = arg.kind - && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node - { - return true; - } + && let ExprKind::Lit(lit) = arg.kind + && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node + { + return true; } false diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index be728e6c8b74b..274438ac0491e 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -327,22 +327,22 @@ impl<'tcx> Visitor<'tcx> for ReadVisitor<'_, 'tcx> { return; } - if path_to_local_id(expr, self.var) { + if path_to_local_id(expr, self.var) // Check that this is a read, not a write. - if !is_in_assignment_position(self.cx, expr) { - span_lint_and_then( - self.cx, - MIXED_READ_WRITE_IN_EXPRESSION, - expr.span, - format!("unsequenced read of `{}`", self.cx.tcx.hir_name(self.var)), - |diag| { - diag.span_note( - self.write_expr.span, - "whether read occurs before this write depends on evaluation order", - ); - }, - ); - } + && !is_in_assignment_position(self.cx, expr) + { + span_lint_and_then( + self.cx, + MIXED_READ_WRITE_IN_EXPRESSION, + expr.span, + format!("unsequenced read of `{}`", self.cx.tcx.hir_name(self.var)), + |diag| { + diag.span_note( + self.write_expr.span, + "whether read occurs before this write depends on evaluation order", + ); + }, + ); } match expr.kind { // We're about to descend a closure. Since we don't know when (or diff --git a/lintcheck/ci-config/clippy.toml b/lintcheck/ci-config/clippy.toml index d9eb2ef90dba2..9853465c83f00 100644 --- a/lintcheck/ci-config/clippy.toml +++ b/lintcheck/ci-config/clippy.toml @@ -4,3 +4,4 @@ # to `$PWD/lintcheck/ci-config`. avoid-breaking-exported-api = false +lint-commented-code = false diff --git a/tests/clippy.toml b/tests/clippy.toml index 5eb7ac0354198..91a2e55180b97 100644 --- a/tests/clippy.toml +++ b/tests/clippy.toml @@ -1 +1,2 @@ # default config for tests, overrides clippy.toml at the project root +lint-commented-code = false From 1da567b619d531184d558f5daafa4c30e8cd34eb Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 14 Feb 2025 12:50:37 +0100 Subject: [PATCH 0305/2248] Deprecate `match_on_vec_items` lint This lint does more harm than good: in its description, it proposes to rewrite `match` on `Vec<_>` indexes or slices by a version which cannot panic but masks the failure by choosing the default variant. The `clippy::indexing_slicing` restriction lint covers those cases more safely, by suggesting to use a non-panicking version to retrieve the value from the container, without suggesting to fallback to the default success variant in case of failure. --- clippy_lints/src/declared_lints.rs | 1 - clippy_lints/src/deprecated_lints.rs | 2 + .../src/matches/match_on_vec_items.rs | 50 ------ clippy_lints/src/matches/mod.rs | 39 ----- tests/ui/deprecated.rs | 1 + tests/ui/deprecated.stderr | 8 +- tests/ui/match_on_vec_items.rs | 161 ------------------ tests/ui/match_on_vec_items.stderr | 53 ------ 8 files changed, 10 insertions(+), 305 deletions(-) delete mode 100644 clippy_lints/src/matches/match_on_vec_items.rs delete mode 100644 tests/ui/match_on_vec_items.rs delete mode 100644 tests/ui/match_on_vec_items.stderr diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index c2274f0a619cf..a60167a5eedf3 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -348,7 +348,6 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::matches::MATCH_AS_REF_INFO, crate::matches::MATCH_BOOL_INFO, crate::matches::MATCH_LIKE_MATCHES_MACRO_INFO, - crate::matches::MATCH_ON_VEC_ITEMS_INFO, crate::matches::MATCH_OVERLAPPING_ARM_INFO, crate::matches::MATCH_REF_PATS_INFO, crate::matches::MATCH_SAME_ARMS_INFO, diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 0031da406f17f..c0e7bfe32c10f 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -42,6 +42,8 @@ declare_with_version! { DEPRECATED(DEPRECATED_VERSION): &[(&str, &str)] = &[ ("clippy::wrong_pub_self_convention", "`clippy::wrong_self_convention` now covers this case via the `avoid-breaking-exported-api` config"), #[clippy::version = "1.86.0"] ("clippy::option_map_or_err_ok", "`clippy::manual_ok_or` covers this case"), + #[clippy::version = "1.86.0"] + ("clippy::match_on_vec_items", "`clippy::indexing_slicing` covers indexing and slicing on `Vec<_>`"), // end deprecated lints. used by `cargo dev deprecate_lint` ]} diff --git a/clippy_lints/src/matches/match_on_vec_items.rs b/clippy_lints/src/matches/match_on_vec_items.rs deleted file mode 100644 index dd71560e169ea..0000000000000 --- a/clippy_lints/src/matches/match_on_vec_items.rs +++ /dev/null @@ -1,50 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet; -use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; -use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, LangItem}; -use rustc_lint::LateContext; -use rustc_span::sym; - -use super::MATCH_ON_VEC_ITEMS; - -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>) { - if let Some(idx_expr) = is_vec_indexing(cx, scrutinee) - && let ExprKind::Index(vec, idx, _) = idx_expr.kind - { - // FIXME: could be improved to suggest surrounding every pattern with Some(_), - // but only when `or_patterns` are stabilized. - span_lint_and_sugg( - cx, - MATCH_ON_VEC_ITEMS, - scrutinee.span, - "indexing into a vector may panic", - "try", - format!("{}.get({})", snippet(cx, vec.span, ".."), snippet(cx, idx.span, "..")), - Applicability::MaybeIncorrect, - ); - } -} - -fn is_vec_indexing<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { - if let ExprKind::Index(array, index, _) = expr.kind - && is_vector(cx, array) - && !is_full_range(cx, index) - { - return Some(expr); - } - - None -} - -fn is_vector(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - let ty = cx.typeck_results().expr_ty(expr); - let ty = ty.peel_refs(); - is_type_diagnostic_item(cx, ty, sym::Vec) -} - -fn is_full_range(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - let ty = cx.typeck_results().expr_ty(expr); - let ty = ty.peel_refs(); - is_type_lang_item(cx, ty, LangItem::RangeFull) -} diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index ad299ae8f0f1a..c6ebd6144c76f 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -8,7 +8,6 @@ mod manual_utils; mod match_as_ref; mod match_bool; mod match_like_matches; -mod match_on_vec_items; mod match_ref_pats; mod match_same_arms; mod match_single_binding; @@ -759,42 +758,6 @@ declare_clippy_lint! { "check if a `match` or `if let` can be simplified with `unwrap_or_default`" } -declare_clippy_lint! { - /// ### What it does - /// Checks for `match vec[idx]` or `match vec[n..m]`. - /// - /// ### Why is this bad? - /// This can panic at runtime. - /// - /// ### Example - /// ```rust, no_run - /// let arr = vec![0, 1, 2, 3]; - /// let idx = 1; - /// - /// match arr[idx] { - /// 0 => println!("{}", 0), - /// 1 => println!("{}", 3), - /// _ => {}, - /// } - /// ``` - /// - /// Use instead: - /// ```rust, no_run - /// let arr = vec![0, 1, 2, 3]; - /// let idx = 1; - /// - /// match arr.get(idx) { - /// Some(0) => println!("{}", 0), - /// Some(1) => println!("{}", 3), - /// _ => {}, - /// } - /// ``` - #[clippy::version = "1.45.0"] - pub MATCH_ON_VEC_ITEMS, - pedantic, - "matching on vector elements can panic" -} - declare_clippy_lint! { /// ### What it does /// Checks for `match` expressions modifying the case of a string with non-compliant arms @@ -1078,7 +1041,6 @@ impl_lint_pass!(Matches => [ COLLAPSIBLE_MATCH, MANUAL_UNWRAP_OR, MANUAL_UNWRAP_OR_DEFAULT, - MATCH_ON_VEC_ITEMS, MATCH_STR_CASE_MISMATCH, SIGNIFICANT_DROP_IN_SCRUTINEE, TRY_ERR, @@ -1156,7 +1118,6 @@ impl<'tcx> LateLintPass<'tcx> for Matches { match_wild_enum::check(cx, ex, arms); match_as_ref::check(cx, ex, arms, expr); needless_match::check_match(cx, ex, arms, expr); - match_on_vec_items::check(cx, ex); match_str_case_mismatch::check(cx, ex, arms); redundant_guards::check(cx, arms, self.msrv); diff --git a/tests/ui/deprecated.rs b/tests/ui/deprecated.rs index 35646e1c23919..2787f6406fe39 100644 --- a/tests/ui/deprecated.rs +++ b/tests/ui/deprecated.rs @@ -16,5 +16,6 @@ #![warn(clippy::pub_enum_variant_names)] //~ ERROR: lint `clippy::pub_enum_variant_names` #![warn(clippy::wrong_pub_self_convention)] //~ ERROR: lint `clippy::wrong_pub_self_convention` #![warn(clippy::option_map_or_err_ok)] //~ ERROR: lint `clippy::option_map_or_err_ok` +#![warn(clippy::match_on_vec_items)] //~ ERROR: lint `clippy::match_on_vec_items` fn main() {} diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index d7be1e583b08b..604732405c370 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -85,5 +85,11 @@ error: lint `clippy::option_map_or_err_ok` has been removed: `clippy::manual_ok_ LL | #![warn(clippy::option_map_or_err_ok)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: lint `clippy::match_on_vec_items` has been removed: `clippy::indexing_slicing` covers indexing and slicing on `Vec<_>` + --> tests/ui/deprecated.rs:19:9 + | +LL | #![warn(clippy::match_on_vec_items)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 15 previous errors diff --git a/tests/ui/match_on_vec_items.rs b/tests/ui/match_on_vec_items.rs deleted file mode 100644 index f3174ec9734df..0000000000000 --- a/tests/ui/match_on_vec_items.rs +++ /dev/null @@ -1,161 +0,0 @@ -#![warn(clippy::match_on_vec_items)] -#![allow(clippy::redundant_at_rest_pattern, clippy::useless_vec)] -//@no-rustfix -fn match_with_wildcard() { - let arr = vec![0, 1, 2, 3]; - let range = 1..3; - let idx = 1; - - // Lint, may panic - match arr[idx] { - //~^ match_on_vec_items - 0 => println!("0"), - 1 => println!("1"), - _ => {}, - } - - // Lint, may panic - match arr[range] { - //~^ match_on_vec_items - [0, 1] => println!("0 1"), - [1, 2] => println!("1 2"), - _ => {}, - } -} - -fn match_without_wildcard() { - let arr = vec![0, 1, 2, 3]; - let range = 1..3; - let idx = 2; - - // Lint, may panic - match arr[idx] { - //~^ match_on_vec_items - 0 => println!("0"), - 1 => println!("1"), - num => {}, - } - - // Lint, may panic - match arr[range] { - //~^ match_on_vec_items - [0, 1] => println!("0 1"), - [1, 2] => println!("1 2"), - [ref sub @ ..] => {}, - } -} - -fn match_wildcard_and_action() { - let arr = vec![0, 1, 2, 3]; - let range = 1..3; - let idx = 3; - - // Lint, may panic - match arr[idx] { - //~^ match_on_vec_items - 0 => println!("0"), - 1 => println!("1"), - _ => println!("Hello, World!"), - } - - // Lint, may panic - match arr[range] { - //~^ match_on_vec_items - [0, 1] => println!("0 1"), - [1, 2] => println!("1 2"), - _ => println!("Hello, World!"), - } -} - -fn match_vec_ref() { - let arr = &vec![0, 1, 2, 3]; - let range = 1..3; - let idx = 3; - - // Lint, may panic - match arr[idx] { - //~^ match_on_vec_items - 0 => println!("0"), - 1 => println!("1"), - _ => {}, - } - - // Lint, may panic - match arr[range] { - //~^ match_on_vec_items - [0, 1] => println!("0 1"), - [1, 2] => println!("1 2"), - _ => {}, - } -} - -fn match_with_get() { - let arr = vec![0, 1, 2, 3]; - let range = 1..3; - let idx = 3; - - // Ok - match arr.get(idx) { - Some(0) => println!("0"), - Some(1) => println!("1"), - _ => {}, - } - - // Ok - match arr.get(range) { - Some(&[0, 1]) => println!("0 1"), - Some(&[1, 2]) => println!("1 2"), - _ => {}, - } -} - -fn match_with_array() { - let arr = [0, 1, 2, 3]; - let range = 1..3; - let idx = 3; - - // Ok - match arr[idx] { - 0 => println!("0"), - 1 => println!("1"), - _ => {}, - } - - // Ok - match arr[range] { - [0, 1] => println!("0 1"), - [1, 2] => println!("1 2"), - _ => {}, - } -} - -fn match_with_endless_range() { - let arr = vec![0, 1, 2, 3]; - let range = ..; - - // Ok - match arr[range] { - [0, 1] => println!("0 1"), - [1, 2] => println!("1 2"), - [0, 1, 2, 3] => println!("0, 1, 2, 3"), - _ => {}, - } - - // Ok - match arr[..] { - [0, 1] => println!("0 1"), - [1, 2] => println!("1 2"), - [0, 1, 2, 3] => println!("0, 1, 2, 3"), - _ => {}, - } -} - -fn main() { - match_with_wildcard(); - match_without_wildcard(); - match_wildcard_and_action(); - match_vec_ref(); - match_with_get(); - match_with_array(); - match_with_endless_range(); -} diff --git a/tests/ui/match_on_vec_items.stderr b/tests/ui/match_on_vec_items.stderr deleted file mode 100644 index ae79e1305f7fd..0000000000000 --- a/tests/ui/match_on_vec_items.stderr +++ /dev/null @@ -1,53 +0,0 @@ -error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:10:11 - | -LL | match arr[idx] { - | ^^^^^^^^ help: try: `arr.get(idx)` - | - = note: `-D clippy::match-on-vec-items` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::match_on_vec_items)]` - -error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:18:11 - | -LL | match arr[range] { - | ^^^^^^^^^^ help: try: `arr.get(range)` - -error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:32:11 - | -LL | match arr[idx] { - | ^^^^^^^^ help: try: `arr.get(idx)` - -error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:40:11 - | -LL | match arr[range] { - | ^^^^^^^^^^ help: try: `arr.get(range)` - -error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:54:11 - | -LL | match arr[idx] { - | ^^^^^^^^ help: try: `arr.get(idx)` - -error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:62:11 - | -LL | match arr[range] { - | ^^^^^^^^^^ help: try: `arr.get(range)` - -error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:76:11 - | -LL | match arr[idx] { - | ^^^^^^^^ help: try: `arr.get(idx)` - -error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:84:11 - | -LL | match arr[range] { - | ^^^^^^^^^^ help: try: `arr.get(range)` - -error: aborting due to 8 previous errors - From 328846c6eb650580f93addb687a8f5fd863bd892 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 19 Aug 2024 15:20:02 +0200 Subject: [PATCH 0306/2248] 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 5743d381af27a24d12e5272043fa4e21dfa5794a Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 19 Aug 2024 15:20:02 +0200 Subject: [PATCH 0307/2248] Rename `is_like_osx` to `is_like_darwin` --- src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/consts.rs b/src/consts.rs index c514b7a428bc6..0dc0a91829886 100644 --- a/src/consts.rs +++ b/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). From fc126df5a7bf6cf74a8fcf16d2f8c2902c7d9e73 Mon Sep 17 00:00:00 2001 From: Hegui Dai Date: Wed, 26 Mar 2025 08:23:43 +0800 Subject: [PATCH 0308/2248] Update the index.html of Option to make the summary more comprehensive --- library/core/src/option.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 7ec0ac7127142..ee755f6629e5b 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -159,11 +159,17 @@ //! //! ## Querying the variant //! -//! The [`is_some`] and [`is_none`] methods return [`true`] if the [`Option`] -//! is [`Some`] or [`None`], respectively. +//! The [`is_some`] and [`is_none`] methods take a borrow of the [`Option`] +//! and return [`true`] if the [`Option`] is [`Some`] or [`None`], respectively. +//! +//! The [`is_some_and`] and [`is_none_or`] methods take ownership of the [`Option`] +//! and apply the provided function to make a decision. +//! The methods return the same boolean value as the function returns. //! //! [`is_none`]: Option::is_none //! [`is_some`]: Option::is_some +//! [`is_some_and`]: Option::is_some_and +//! [`is_none_or`]: Option::is_none_or //! //! ## Adapters for working with references //! @@ -177,6 +183,10 @@ //! [Option]<[Pin]<[&]T>> //! * [`as_pin_mut`] converts from [Pin]<[&mut] [Option]\> to //! [Option]<[Pin]<[&mut] T>> +//! * [`as_slice`] returns a slice of the contained value, if any. +//! If this is [`None`], an empty slice is returned. +//! * [`as_mut_slice`] returns a mutable slice of the contained value, if any. +//! If this is [`None`], an empty slice is returned. //! //! [&]: reference "shared reference" //! [&mut]: reference "mutable reference" @@ -187,6 +197,8 @@ //! [`as_pin_mut`]: Option::as_pin_mut //! [`as_pin_ref`]: Option::as_pin_ref //! [`as_ref`]: Option::as_ref +//! [`as_slice`]: Option::as_slice +//! [`as_mut_slice`]: Option::as_mut_slice //! //! ## Extracting the contained value //! @@ -200,12 +212,16 @@ //! (which must implement the [`Default`] trait) //! * [`unwrap_or_else`] returns the result of evaluating the provided //! function +//! * [`unwrap_unchecked`] returns the contained value, without checking +//! calling this method on None is *[undefined behavior]* //! //! [`expect`]: Option::expect //! [`unwrap`]: Option::unwrap //! [`unwrap_or`]: Option::unwrap_or //! [`unwrap_or_default`]: Option::unwrap_or_default //! [`unwrap_or_else`]: Option::unwrap_or_else +//! [`unwrap_unchecked`]: Option::unwrap_unchecked +//! [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html //! //! ## Transforming contained values //! @@ -232,6 +248,8 @@ //! if the function returns `true`; otherwise, returns [`None`] //! * [`flatten`] removes one level of nesting from an //! [`Option>`] +//! * [`insert`] calls the provided function with a reference to +//! the contained value if [`Some`] //! * [`map`] transforms [`Option`] to [`Option`] by applying the //! provided function to the contained value of [`Some`] and leaving //! [`None`] values unchanged @@ -239,6 +257,7 @@ //! [`Some(t)`]: Some //! [`filter`]: Option::filter //! [`flatten`]: Option::flatten +//! [`insert`]: Option::insert //! [`map`]: Option::map //! //! These methods transform [`Option`] to a value of a possibly From 049bb266873ff98ce8219c7d2d5d56c7cbe3eaf3 Mon Sep 17 00:00:00 2001 From: beetrees Date: Sun, 23 Mar 2025 22:50:28 +0000 Subject: [PATCH 0309/2248] Add target-specific NaN payloads for the missing tier 2 targets --- library/core/src/primitive_docs.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 89c856fe10746..6c59e71194b4e 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1309,10 +1309,12 @@ mod prim_f16 {} // FIXME: Is there a better place to put this? /// /// | `target_arch` | Extra payloads possible on this platform | -/// |---------------|---------| -/// | `x86`, `x86_64`, `arm`, `aarch64`, `riscv32`, `riscv64` | None | +/// |---------------|------------------------------------------| +// Sorted alphabetically +/// | `aarch64`, `arm`, `arm64ec`, `loongarch64`, `powerpc` (except when `target_abi = "spe"`), `powerpc64`, `riscv32`, `riscv64`, `s390x`, `x86`, `x86_64` | None | +/// | `nvptx64` | All payloads | /// | `sparc`, `sparc64` | The all-one payload | -/// | `wasm32`, `wasm64` | If all input NaNs are quiet with all-zero payload: None.
Otherwise: all possible payloads. | +/// | `wasm32`, `wasm64` | If all input NaNs are quiet with all-zero payload: None.
Otherwise: all payloads. | /// /// For targets not in this table, all payloads are possible. From 441eb005f97031a123192a809a706a30b6305fc4 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Sat, 22 Mar 2025 22:05:26 -0600 Subject: [PATCH 0310/2248] Tidy up drop glue notification This combines the memory layout and drop information on one line, and makes the wording more succinct. Closes #19410 --- .../crates/ide/src/hover/render.rs | 30 +- .../crates/ide/src/hover/tests.rs | 498 ++++-------------- 2 files changed, 107 insertions(+), 421 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index a4cb869ac1f6c..7bb88006f6d1c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -718,18 +718,17 @@ pub(super) fn definition( } _ => return None, }; - let rendered_drop_glue = match drop_info.drop_glue { - DropGlue::None => "does not contain types with destructors (drop glue)", - DropGlue::DependOnParams => { - "may contain types with destructors (drop glue) depending on type parameters" + let rendered_drop_glue = if drop_info.has_dtor == Some(true) { + "impl Drop" + } else { + match drop_info.drop_glue { + DropGlue::HasDropGlue => "needs Drop", + DropGlue::None => "no Drop", + DropGlue::DependOnParams => "type param may need Drop", } - DropGlue::HasDropGlue => "contain types with destructors (drop glue)", }; - Some(match drop_info.has_dtor { - Some(true) => format!("{}; has a destructor", rendered_drop_glue), - Some(false) => format!("{}; doesn't have a destructor", rendered_drop_glue), - None => rendered_drop_glue.to_owned(), - }) + + Some(rendered_drop_glue.to_owned()) }; let dyn_compatibility_info = || match def { @@ -761,15 +760,18 @@ pub(super) fn definition( if let Some(layout_info) = layout_info() { extra.push_str("\n___\n"); extra.push_str(&layout_info); + if let Some(drop_info) = drop_info() { + extra.push_str(", "); + extra.push_str(&drop_info) + } + } else if let Some(drop_info) = drop_info() { + extra.push_str("\n___\n"); + extra.push_str(&drop_info); } if let Some(dyn_compatibility_info) = dyn_compatibility_info() { extra.push_str("\n___\n"); extra.push_str(&dyn_compatibility_info); } - if let Some(drop_info) = drop_info() { - extra.push_str("\n___\n"); - extra.push_str(&drop_info); - } } let mut desc = String::new(); desc.push_str(&label); diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index c5f87910302e5..a3258627170be 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -567,11 +567,7 @@ fn main() { --- - size = 8, align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 8, align = 4, no Drop "#]], ); } @@ -816,11 +812,7 @@ struct Foo { fiel$0d_a: u8, field_b: i32, field_c: i16 } --- - size = 1, align = 1, offset = 6 - - --- - - does not contain types with destructors (drop glue) + size = 1, align = 1, offset = 6, no Drop "#]], ); } @@ -871,11 +863,7 @@ fn main() { --- - size = 4, align = 4, offset = 0 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 4, offset = 0, no Drop "#]], ); } @@ -945,11 +933,7 @@ struct Foo$0(pub u32) where u32: Copy; --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 4, align = 4, no Drop "#]], ); } @@ -975,11 +959,7 @@ struct Foo$0 { field: u32 } --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 4, align = 4, no Drop "#]], ); check( @@ -1004,11 +984,7 @@ struct Foo$0 where u32: Copy { field: u32 } --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 4, align = 4, no Drop "#]], ); } @@ -1037,11 +1013,7 @@ fn hover_record_struct_limit() { --- - size = 12 (0xC), align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 12 (0xC), align = 4, no Drop "#]], ); check_hover_fields_limit( @@ -1064,11 +1036,7 @@ fn hover_record_struct_limit() { --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 4, align = 4, no Drop "#]], ); check_hover_fields_limit( @@ -1094,11 +1062,7 @@ fn hover_record_struct_limit() { --- - size = 16 (0x10), align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 16 (0x10), align = 4, no Drop "#]], ); check_hover_fields_limit( @@ -1119,11 +1083,7 @@ fn hover_record_struct_limit() { --- - size = 12 (0xC), align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 12 (0xC), align = 4, no Drop "#]], ); check_hover_fields_limit( @@ -1144,11 +1104,7 @@ fn hover_record_struct_limit() { --- - size = 12 (0xC), align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 12 (0xC), align = 4, no Drop "#]], ); @@ -1171,11 +1127,7 @@ fn hover_record_struct_limit() { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 0, align = 1, no Drop "#]], ); } @@ -1200,11 +1152,7 @@ fn hover_record_variant_limit() { --- - size = 12 (0xC), align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 12 (0xC), align = 4, no Drop "#]], ); check_hover_fields_limit( @@ -1225,11 +1173,7 @@ fn hover_record_variant_limit() { --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 4, no Drop "#]], ); check_hover_fields_limit( @@ -1250,11 +1194,7 @@ fn hover_record_variant_limit() { --- - size = 16 (0x10), align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 16 (0x10), align = 4, no Drop "#]], ); check_hover_fields_limit( @@ -1275,11 +1215,7 @@ fn hover_record_variant_limit() { --- - size = 12 (0xC), align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 12 (0xC), align = 4, no Drop "#]], ); check_hover_fields_limit( @@ -1300,11 +1236,7 @@ fn hover_record_variant_limit() { --- - size = 12 (0xC), align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 12 (0xC), align = 4, no Drop "#]], ); } @@ -1330,11 +1262,7 @@ fn hover_enum_limit() { --- - size = 1, align = 1, niches = 254 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 1, align = 1, niches = 254, no Drop "#]], ); check_hover_enum_variants_limit( @@ -1356,11 +1284,7 @@ fn hover_enum_limit() { --- - size = 1, align = 1, niches = 254 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 1, align = 1, niches = 254, no Drop "#]], ); check_hover_enum_variants_limit( @@ -1379,11 +1303,7 @@ fn hover_enum_limit() { --- - size = 1, align = 1, niches = 254 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 1, align = 1, niches = 254, no Drop "#]], ); check_hover_enum_variants_limit( @@ -1402,11 +1322,7 @@ fn hover_enum_limit() { --- - size = 1, align = 1, niches = 254 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 1, align = 1, niches = 254, no Drop "#]], ); check_hover_enum_variants_limit( @@ -1443,11 +1359,7 @@ fn hover_enum_limit() { --- - size = 12 (0xC), align = 4, niches = a lot - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 12 (0xC), align = 4, niches = a lot, no Drop "#]], ); } @@ -1473,11 +1385,7 @@ fn hover_union_limit() { --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 4, align = 4, no Drop "#]], ); check_hover_fields_limit( @@ -1499,11 +1407,7 @@ fn hover_union_limit() { --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 4, align = 4, no Drop "#]], ); check_hover_fields_limit( @@ -1522,11 +1426,7 @@ fn hover_union_limit() { --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 4, align = 4, no Drop "#]], ); check_hover_fields_limit( @@ -1545,11 +1445,7 @@ fn hover_union_limit() { --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 4, align = 4, no Drop "#]], ); } @@ -1575,11 +1471,7 @@ struct Foo$0 where u32: Copy; --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 0, align = 1, no Drop "#]], ); } @@ -1605,7 +1497,7 @@ type Fo$0o: Trait = S where T: Trait; --- - does not contain types with destructors (drop glue) + no Drop "#]], ); } @@ -1754,11 +1646,7 @@ fn main() { --- - size = 8, align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 8, align = 4, no Drop "#]], ); check_hover_range( @@ -1813,11 +1701,7 @@ fn main() { let b$0ar = Some(12); } --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 4, no Drop "#]], ); } @@ -1845,7 +1729,7 @@ enum Option { --- - does not contain types with destructors (drop glue) + no Drop --- @@ -1908,11 +1792,7 @@ fn hover_for_local_variable_pat() { --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 4, no Drop "#]], ) } @@ -1944,11 +1824,7 @@ fn hover_for_param_edge() { --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 4, no Drop "#]], ) } @@ -1974,7 +1850,7 @@ fn hover_for_param_with_multiple_traits() { --- - may contain types with destructors (drop glue) depending on type parameters + type param may need Drop "#]], ) } @@ -2000,11 +1876,7 @@ fn main() { let foo_$0test = Thing::new(); } --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 4, no Drop "#]], ) } @@ -2257,11 +2129,7 @@ where --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 0, align = 1, no Drop "#]], ); } @@ -2807,11 +2675,7 @@ fn test_hover_function_pointer_show_identifiers() { --- - size = 8, align = 8, niches = 1 - - --- - - does not contain types with destructors (drop glue) + size = 8, align = 8, niches = 1, no Drop "#]], ); } @@ -2833,11 +2697,7 @@ fn test_hover_function_pointer_no_identifier() { --- - size = 8, align = 8, niches = 1 - - --- - - does not contain types with destructors (drop glue) + size = 8, align = 8, niches = 1, no Drop "#]], ); } @@ -3080,11 +2940,7 @@ pub struct B$0ar --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 0, align = 1, no Drop --- @@ -3115,11 +2971,7 @@ pub struct B$0ar --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 0, align = 1, no Drop --- @@ -3212,11 +3064,7 @@ fn test_hover_layout_of_variant() { --- - size = 4, align = 2 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 2, no Drop "#]], ); } @@ -3241,7 +3089,7 @@ fn test_hover_layout_of_variant_generic() { --- - does not contain types with destructors (drop glue) + no Drop "#]], ); } @@ -3266,11 +3114,7 @@ struct S$0(core::marker::PhantomData); --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 0, align = 1, no Drop "#]], ); } @@ -3298,11 +3142,7 @@ fn test_hover_layout_of_enum() { --- - size = 16 (0x10), align = 8, niches = 254 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 16 (0x10), align = 8, niches = 254, no Drop "#]], ); } @@ -3324,7 +3164,7 @@ fn test_hover_no_memory_layout() { --- - does not contain types with destructors (drop glue) + no Drop "#]], ); @@ -4632,11 +4472,7 @@ fn main() { --- - size = 8, align = 8, niches = 1 - - --- - - does not contain types with destructors (drop glue) + size = 8, align = 8, niches = 1, no Drop --- @@ -4650,11 +4486,7 @@ fn main() { --- - size = 4, align = 4, offset = 0 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 4, offset = 0, no Drop "#]], ); } @@ -4679,11 +4511,7 @@ struct S$0T(T); --- - size = 0, align = 1 - - --- - - may contain types with destructors (drop glue) depending on type parameters; doesn't have a destructor + size = 0, align = 1, type param may need Drop "#]], ); } @@ -4708,11 +4536,7 @@ struct S$0T(T); --- - size = 0, align = 1 - - --- - - may contain types with destructors (drop glue) depending on type parameters; doesn't have a destructor + size = 0, align = 1, type param may need Drop "#]], ); } @@ -4738,11 +4562,7 @@ struct S$0T(T); --- - size = 0, align = 1 - - --- - - may contain types with destructors (drop glue) depending on type parameters; doesn't have a destructor + size = 0, align = 1, type param may need Drop "#]], ); } @@ -4766,11 +4586,7 @@ fn main() { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -4794,11 +4610,7 @@ fn main() { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -4822,11 +4634,7 @@ fn main() { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -4850,11 +4658,7 @@ fn main() { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -4878,11 +4682,7 @@ fn main() { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -4905,11 +4705,7 @@ impl Foo { --- - size = 8, align = 8, niches = 1 - - --- - - does not contain types with destructors (drop glue) + size = 8, align = 8, niches = 1, no Drop "#]], ); } @@ -4933,11 +4729,7 @@ impl Foo { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -5427,11 +5219,7 @@ type Fo$0o2 = Foo<2>; --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -5481,11 +5269,7 @@ enum E { --- - size = 1, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 1, align = 1, no Drop --- @@ -5514,11 +5298,7 @@ enum E { --- - size = 1, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 1, align = 1, no Drop --- @@ -5548,11 +5328,7 @@ enum E { --- - size = 1, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 1, align = 1, no Drop --- @@ -5582,11 +5358,7 @@ enum E { --- - size = 1, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 1, align = 1, no Drop --- @@ -6517,11 +6289,7 @@ fn main() { --- - size = 32 (0x20), align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 32 (0x20), align = 4, no Drop "#]], ); } @@ -7820,11 +7588,7 @@ enum Enum { --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 4, no Drop "#]], ); } @@ -7850,11 +7614,7 @@ enum Enum { --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 4, no Drop "#]], ); } @@ -8524,11 +8284,7 @@ fn test() { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -9177,11 +8933,7 @@ fn main(notable$0: u32) {} --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 4, no Drop "#]], ); } @@ -9273,11 +9025,7 @@ extern "C" { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -9423,11 +9171,7 @@ struct Pedro$0<'a> { --- - size = 16 (0x10), align = 8, niches = 1 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 16 (0x10), align = 8, niches = 1, no Drop "#]], ) } @@ -9448,7 +9192,7 @@ fn main(a$0: impl T) {} --- - may contain types with destructors (drop glue) depending on type parameters + type param may need Drop "#]], ); } @@ -9469,11 +9213,7 @@ fn main(a$0: T) {} --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -9526,11 +9266,7 @@ fn main() { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -9864,11 +9600,7 @@ type A$0 = B; --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop --- @@ -9901,11 +9633,7 @@ type A$0 = B; --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop --- @@ -9939,11 +9667,7 @@ type A$0 = B; --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop --- @@ -9975,11 +9699,7 @@ type A$0 = B; --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); @@ -10103,11 +9823,7 @@ fn main() { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); @@ -10135,11 +9851,7 @@ fn main() { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); @@ -10174,11 +9886,7 @@ fn main() { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); } @@ -10497,11 +10205,7 @@ fn bar() { --- - size = 4, align = 4 - - --- - - does not contain types with destructors (drop glue) + size = 4, align = 4, no Drop --- @@ -10515,7 +10219,7 @@ fn bar() { --- - may contain types with destructors (drop glue) depending on type parameters + type param may need Drop --- @@ -10748,11 +10452,7 @@ struct NoDrop$0; --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue); doesn't have a destructor + size = 0, align = 1, no Drop "#]], ); check( @@ -10776,11 +10476,7 @@ impl Drop for NeedsDrop { --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue); has a destructor + size = 0, align = 1, impl Drop "#]], ); check( @@ -10805,11 +10501,7 @@ type NoDrop$0 = core::mem::ManuallyDrop; --- - size = 0, align = 1 - - --- - - does not contain types with destructors (drop glue) + size = 0, align = 1, no Drop "#]], ); check( @@ -10840,11 +10532,7 @@ struct DropField$0 { --- - size = 4, align = 4 - - --- - - contain types with destructors (drop glue); doesn't have a destructor + size = 4, align = 4, needs Drop "#]], ); check( @@ -10865,7 +10553,7 @@ type Foo$0 = impl Sized; --- - contain types with destructors (drop glue) + needs Drop "#]], ); check( @@ -10893,11 +10581,7 @@ enum Enum { --- - size = 16 (0x10), align = 8, niches = 1 - - --- - - does not contain types with destructors (drop glue) + size = 16 (0x10), align = 8, niches = 1, no Drop "#]], ); check( @@ -10917,7 +10601,7 @@ struct Foo$0(T); --- - may contain types with destructors (drop glue) depending on type parameters; doesn't have a destructor + type param may need Drop "#]], ); check( @@ -10940,7 +10624,7 @@ struct Foo$0(T); --- - does not contain types with destructors (drop glue); doesn't have a destructor + no Drop "#]], ); check( @@ -10966,7 +10650,7 @@ struct Foo$0(T::Assoc); --- - does not contain types with destructors (drop glue); doesn't have a destructor + no Drop "#]], ); check( @@ -10997,7 +10681,7 @@ pub struct ManuallyDrop$0 { --- - does not contain types with destructors (drop glue); doesn't have a destructor + no Drop "#]], ); } From 89625360ec4fa11bdc073a74607c7ff0f624fb96 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Wed, 26 Mar 2025 11:27:52 +0800 Subject: [PATCH 0311/2248] Add ui test cast-array-issue-138836 Signed-off-by: xizheyin --- tests/ui/cast/cast-array-issue-138836.rs | 5 +++++ tests/ui/cast/cast-array-issue-138836.stderr | 12 ++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/ui/cast/cast-array-issue-138836.rs create mode 100644 tests/ui/cast/cast-array-issue-138836.stderr diff --git a/tests/ui/cast/cast-array-issue-138836.rs b/tests/ui/cast/cast-array-issue-138836.rs new file mode 100644 index 0000000000000..6fd65d5878ac9 --- /dev/null +++ b/tests/ui/cast/cast-array-issue-138836.rs @@ -0,0 +1,5 @@ +fn main() { + let a: [u8; 3] = [1,2,3]; + let b = &a; + let c = b as *const [u32; 3]; //~ ERROR mismatched types [E0308] +} diff --git a/tests/ui/cast/cast-array-issue-138836.stderr b/tests/ui/cast/cast-array-issue-138836.stderr new file mode 100644 index 0000000000000..fe20d429a4989 --- /dev/null +++ b/tests/ui/cast/cast-array-issue-138836.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/cast-array-issue-138836.rs:4:13 + | +LL | let c = b as *const [u32; 3]; + | ^^^^^^^^^^^^^^^^^^^^ expected `[u8; 3]`, found `[u32; 3]` + | + = note: expected array `[u8; 3]` + found array `[u32; 3]` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 2043e36a8879543c3a309cf883eb16ddcb53f3e3 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 26 Mar 2025 06:46:49 +0100 Subject: [PATCH 0312/2248] refactor: Use MEDIUM durability for crate-graph changes, high for library source files The idea here is that the crate graph may change over time, but library source file contents *never* will (or really never should). Disconnecting the two means that queries that depend on library sources will not need to re-validatewhen the crate graph changes (unless they depend on the crate graph in some capacity). --- .../rust-analyzer/crates/base-db/src/change.rs | 10 +++++++--- .../rust-analyzer/crates/base-db/src/input.rs | 14 +++++++------- .../crates/ide-db/src/apply_change.rs | 4 ++-- src/tools/rust-analyzer/crates/ide-db/src/lib.rs | 6 +++--- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/tools/rust-analyzer/crates/base-db/src/change.rs b/src/tools/rust-analyzer/crates/base-db/src/change.rs index b5964ff5b4abe..114b4cbf24b70 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/change.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/change.rs @@ -55,7 +55,7 @@ impl FileChange { if let Some(roots) = self.roots { for (idx, root) in roots.into_iter().enumerate() { let root_id = SourceRootId(idx as u32); - let durability = durability(&root); + let durability = source_root_durability(&root); for file_id in root.iter() { db.set_file_source_root_with_durability(file_id, root_id, durability); } @@ -68,7 +68,7 @@ impl FileChange { let source_root_id = db.file_source_root(file_id); let source_root = db.source_root(source_root_id.source_root_id(db)); - let durability = durability(&source_root.source_root(db)); + let durability = file_text_durability(&source_root.source_root(db)); // XXX: can't actually remove the file, just reset the text let text = text.unwrap_or_default(); db.set_file_text_with_durability(file_id, &text, durability) @@ -81,6 +81,10 @@ impl FileChange { } } -fn durability(source_root: &SourceRoot) -> Durability { +fn source_root_durability(source_root: &SourceRoot) -> Durability { + if source_root.is_library { Durability::MEDIUM } else { Durability::LOW } +} + +fn file_text_durability(source_root: &SourceRoot) -> Durability { if source_root.is_library { Durability::HIGH } else { Durability::LOW } } diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index 2fe4f688f5674..343aba1a169cf 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -491,7 +491,7 @@ impl CrateGraphBuilder { if **old_all_crates != *all_crates { db.set_all_crates_with_durability( Arc::new(all_crates.into_boxed_slice()), - Durability::HIGH, + Durability::MEDIUM, ); } @@ -549,30 +549,30 @@ impl CrateGraphBuilder { Entry::Occupied(entry) => { let old_crate = *entry.get(); if crate_data != *old_crate.data(db) { - old_crate.set_data(db).with_durability(Durability::HIGH).to(crate_data); + old_crate.set_data(db).with_durability(Durability::MEDIUM).to(crate_data); } if krate.extra != *old_crate.extra_data(db) { old_crate .set_extra_data(db) - .with_durability(Durability::HIGH) + .with_durability(Durability::MEDIUM) .to(krate.extra.clone()); } if krate.cfg_options != *old_crate.cfg_options(db) { old_crate .set_cfg_options(db) - .with_durability(Durability::HIGH) + .with_durability(Durability::MEDIUM) .to(krate.cfg_options.clone()); } if krate.env != *old_crate.env(db) { old_crate .set_env(db) - .with_durability(Durability::HIGH) + .with_durability(Durability::MEDIUM) .to(krate.env.clone()); } if krate.ws_data != *old_crate.workspace_data(db) { old_crate .set_workspace_data(db) - .with_durability(Durability::HIGH) + .with_durability(Durability::MEDIUM) .to(krate.ws_data.clone()); } old_crate @@ -585,7 +585,7 @@ impl CrateGraphBuilder { krate.cfg_options.clone(), krate.env.clone(), ) - .durability(Durability::HIGH) + .durability(Durability::MEDIUM) .new(db); entry.insert(input); input diff --git a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs index 36745b012b00d..008b6fdbe2c68 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs @@ -29,8 +29,8 @@ impl RootDatabase { local_roots.insert(root_id); } } - self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); - self.set_library_roots_with_durability(Arc::new(library_roots), Durability::HIGH); + self.set_local_roots_with_durability(Arc::new(local_roots), Durability::MEDIUM); + self.set_library_roots_with_durability(Arc::new(library_roots), Durability::MEDIUM); } change.apply(self); } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs index c6bd8031281c1..b5b4a9eeacdf5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -220,9 +220,9 @@ impl RootDatabase { // This needs to be here otherwise `CrateGraphBuilder` will panic. db.set_all_crates(Arc::new(Box::new([]))); CrateGraphBuilder::default().set_in_db(&mut db); - db.set_proc_macros_with_durability(Default::default(), Durability::HIGH); - db.set_local_roots_with_durability(Default::default(), Durability::HIGH); - db.set_library_roots_with_durability(Default::default(), Durability::HIGH); + db.set_proc_macros_with_durability(Default::default(), Durability::MEDIUM); + db.set_local_roots_with_durability(Default::default(), Durability::MEDIUM); + db.set_library_roots_with_durability(Default::default(), Durability::MEDIUM); db.set_expand_proc_attr_macros_with_durability(false, Durability::HIGH); db.update_base_query_lru_capacities(lru_capacity); db From 13303a5b8e719ef952ab9b060b67e45f74130882 Mon Sep 17 00:00:00 2001 From: Hegui Dai Date: Wed, 26 Mar 2025 14:37:06 +0800 Subject: [PATCH 0313/2248] Update the index of Result to make the summary more comprehensive --- library/core/src/result.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 48ab9267f216c..494b3745bc234 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -256,11 +256,26 @@ //! //! ## Querying the variant //! -//! The [`is_ok`] and [`is_err`] methods return [`true`] if the [`Result`] -//! is [`Ok`] or [`Err`], respectively. +//! The [`is_ok`] and [`is_err`] methods take the borrow of the [`Result`] +//! and return [`true`] if the [`Result`] is [`Ok`] or [`Err`], respectively. +//! +//! The [`is_ok_and`] and [`is_err_and`] methods take ownership of the [`Result`] +//! and apply the provided function to make a decision. +//! The methods return the same boolean value as the function returns. //! //! [`is_err`]: Result::is_err //! [`is_ok`]: Result::is_ok +//! [`is_ok_and`]: Result::is_ok_and +//! [`is_err_and`]: Result::is_err_and +//! +//! ## Inspecting the variant +//! +//! The [`inspect`] and [`inspect_err`] methods take ownership of the [`Result`] +//! and apply the provided function to the contained value by reference if [`Ok`] +//! or [`Err`], respectively. And then, the [`Result`] is returned. +//! +//! [`inspect`]: Result::inspect +//! [`inspect_err`]: Result::inspect_err //! //! ## Adapters for working with references //! @@ -287,6 +302,7 @@ //! (which must implement the [`Default`] trait) //! * [`unwrap_or_else`] returns the result of evaluating the provided //! function +//! * [`unwrap_unchecked`] is *[undefined behavior]* //! //! The panicking methods [`expect`] and [`unwrap`] require `E` to //! implement the [`Debug`] trait. @@ -297,6 +313,8 @@ //! [`unwrap_or`]: Result::unwrap_or //! [`unwrap_or_default`]: Result::unwrap_or_default //! [`unwrap_or_else`]: Result::unwrap_or_else +//! [`unwrap_unchecked`]: Result::unwrap_unchecked +//! [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html //! //! These methods extract the contained value in a [`Result`] when it //! is the [`Err`] variant. They require `T` to implement the [`Debug`] @@ -304,10 +322,13 @@ //! //! * [`expect_err`] panics with a provided custom message //! * [`unwrap_err`] panics with a generic message +//! * [`unwrap_err_unchecked`] is *[undefined behavior]* //! //! [`Debug`]: crate::fmt::Debug //! [`expect_err`]: Result::expect_err //! [`unwrap_err`]: Result::unwrap_err +//! [`unwrap_err_unchecked`]: Result::unwrap_err_unchecked +//! [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html //! //! ## Transforming contained values //! From 159ae8fcee04302d24c9d1afc077697b8f266e11 Mon Sep 17 00:00:00 2001 From: Hegui Dai Date: Wed, 26 Mar 2025 14:50:03 +0800 Subject: [PATCH 0314/2248] Keeps the inspect() classification the same as in Result --- library/core/src/option.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index ee755f6629e5b..a1f0224c7791f 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -171,6 +171,13 @@ //! [`is_some_and`]: Option::is_some_and //! [`is_none_or`]: Option::is_none_or //! +//! ## Inspecting the variant +//! +//! The [`inspect`] method takes ownership of the [`Option`] +//! and applies the provided function to the contained value by reference if [`Some`] +//! +//! [`inspect`]: Option::inspect +//! //! ## Adapters for working with references //! //! * [`as_ref`] converts from [&][][Option]\ to [Option]<[&]T> @@ -248,8 +255,6 @@ //! if the function returns `true`; otherwise, returns [`None`] //! * [`flatten`] removes one level of nesting from an //! [`Option>`] -//! * [`insert`] calls the provided function with a reference to -//! the contained value if [`Some`] //! * [`map`] transforms [`Option`] to [`Option`] by applying the //! provided function to the contained value of [`Some`] and leaving //! [`None`] values unchanged @@ -257,7 +262,6 @@ //! [`Some(t)`]: Some //! [`filter`]: Option::filter //! [`flatten`]: Option::flatten -//! [`insert`]: Option::insert //! [`map`]: Option::map //! //! These methods transform [`Option`] to a value of a possibly From cf26d82dafc95d73484b5688ccfc4eec8a9d3e52 Mon Sep 17 00:00:00 2001 From: pudongair <744355276@qq.com> Date: Wed, 26 Mar 2025 15:28:51 +0800 Subject: [PATCH 0315/2248] chore: remove redundant words in comment Signed-off-by: pudongair <744355276@qq.com> --- compiler/rustc_error_codes/src/error_codes/E0207.md | 2 +- library/core/src/clone.rs | 2 +- library/core/src/macros/mod.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0207.md b/compiler/rustc_error_codes/src/error_codes/E0207.md index 5b35748f4723c..f80b0093ecc53 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0207.md +++ b/compiler/rustc_error_codes/src/error_codes/E0207.md @@ -195,7 +195,7 @@ impl<'a> Contains for Foo { Please note that unconstrained lifetime parameters are not supported if they are being used by an associated type. -In cases where the associated type's lifetime is meant to be tied to the the +In cases where the associated type's lifetime is meant to be tied to the self type, and none of the methods on the trait need ownership or different mutability, then an option is to implement the trait on a borrowed type: diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index e0ac0bfc5289f..647463098610d 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -427,7 +427,7 @@ pub unsafe trait CloneToUninit { /// read or dropped, because even if it was previously valid, it may have been partially /// overwritten. /// - /// The caller may wish to to take care to deallocate the allocation pointed to by `dest`, + /// The caller may wish to take care to deallocate the allocation pointed to by `dest`, /// if applicable, to avoid a memory leak (but this is not a requirement). /// /// Implementors should avoid leaking values by, upon unwinding, dropping all component values diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 5f200b31d1ae7..c06f1b56399d2 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1743,8 +1743,8 @@ pub(crate) mod builtin { /* compiler built-in */ } - /// Provide a list of type aliases and other opaque-type-containing type definitions. - /// This list will be used in the body of the item it is applied to define opaque + /// Provide a list of type aliases and other opaque-type-containing type definitions + /// to an item with a body. This list will be used in that body to define opaque /// types' hidden types. /// Can only be applied to things that have bodies. #[unstable( From a8bfafe92962e6dcd1776ac2d2eb2e85072001df Mon Sep 17 00:00:00 2001 From: todaymoon Date: Wed, 26 Mar 2025 15:36:08 +0800 Subject: [PATCH 0316/2248] chore: fix some comments Signed-off-by: todaymoon --- clippy_lints/src/operators/identity_op.rs | 2 +- rustc_tools_util/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/operators/identity_op.rs b/clippy_lints/src/operators/identity_op.rs index 0358232282786..e1fd09549a4b8 100644 --- a/clippy_lints/src/operators/identity_op.rs +++ b/clippy_lints/src/operators/identity_op.rs @@ -103,7 +103,7 @@ enum Parens { /// /// e.g. `-(x + y + 0)` cannot be reduced to `-x + y`, as the behavior changes silently. /// e.g. `1u64 + ((x + y + 0i32) as u64)` cannot be reduced to `1u64 + x + y as u64`, since -/// the the cast expression will not apply to the same expression. +/// the cast expression will not apply to the same expression. /// e.g. `0 + if b { 1 } else { 2 } + if b { 3 } else { 4 }` cannot be reduced /// to `if b { 1 } else { 2 } + if b { 3 } else { 4 }` where the `if` could be /// interpreted as a statement. The same behavior happens for `match`, `loop`, diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index 423154a69fa0b..b45edf2345585 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -121,7 +121,7 @@ fn get_output(cmd: &str, args: &[&str]) -> Option { pub fn rerun_if_git_changes() -> Option<()> { // Make sure we get rerun when the git commit changes. // We want to watch two files: HEAD, which tracks which branch we are on, - // and the file for that branch that tracks which commit is is on. + // and the file for that branch that tracks which commit is checked out. // First, find the `HEAD` file. This should work even with worktrees. let git_head_file = PathBuf::from(get_output("git", &["rev-parse", "--git-path", "HEAD"])?); From 1b92712f3f11a7a5c0f1b50343d533844c5fb134 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 22 Mar 2025 21:42:34 +0300 Subject: [PATCH 0317/2248] expand: Leave traces when expanding `cfg` attributes --- clippy_lints/src/attrs/duplicated_attributes.rs | 3 +-- clippy_lints/src/cfg_not_test.rs | 2 +- clippy_lints/src/methods/is_empty.rs | 2 +- clippy_utils/src/lib.rs | 8 ++++---- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/attrs/duplicated_attributes.rs b/clippy_lints/src/attrs/duplicated_attributes.rs index 5c486eb90cc2b..4c84e61b1f26c 100644 --- a/clippy_lints/src/attrs/duplicated_attributes.rs +++ b/clippy_lints/src/attrs/duplicated_attributes.rs @@ -37,7 +37,6 @@ fn check_duplicated_attr( let Some(ident) = attr.ident() else { return }; let name = ident.name; if name == sym::doc - || name == sym::cfg_attr || name == sym::cfg_attr_trace || name == sym::rustc_on_unimplemented || name == sym::reason { @@ -47,7 +46,7 @@ fn check_duplicated_attr( return; } if let Some(direct_parent) = parent.last() - && ["cfg", "cfg_attr"].contains(&direct_parent.as_str()) + && direct_parent == sym::cfg_trace.as_str() && [sym::all, sym::not, sym::any].contains(&name) { // FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one diff --git a/clippy_lints/src/cfg_not_test.rs b/clippy_lints/src/cfg_not_test.rs index 84136a2e6c28f..7590fe96fd214 100644 --- a/clippy_lints/src/cfg_not_test.rs +++ b/clippy_lints/src/cfg_not_test.rs @@ -32,7 +32,7 @@ declare_lint_pass!(CfgNotTest => [CFG_NOT_TEST]); impl EarlyLintPass for CfgNotTest { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &rustc_ast::Attribute) { - if attr.has_name(rustc_span::sym::cfg) && contains_not_test(attr.meta_item_list().as_deref(), false) { + if attr.has_name(rustc_span::sym::cfg_trace) && contains_not_test(attr.meta_item_list().as_deref(), false) { span_lint_and_then( cx, CFG_NOT_TEST, diff --git a/clippy_lints/src/methods/is_empty.rs b/clippy_lints/src/methods/is_empty.rs index 7c190e123b72e..4c81b22861b4c 100644 --- a/clippy_lints/src/methods/is_empty.rs +++ b/clippy_lints/src/methods/is_empty.rs @@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_ fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool { cx.tcx .hir_parent_id_iter(id) - .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg))) + .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg_trace))) } /// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 1307ff79bc5dd..668b0cb69e204 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2629,7 +2629,7 @@ pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir> pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind { if let Res::Def(_, def_id) = path.res { - return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr); + return cx.tcx.has_attr(def_id, sym::cfg_trace) || cx.tcx.has_attr(def_id, sym::cfg_attr); } } false @@ -2699,7 +2699,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool { /// use [`is_in_cfg_test`] pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { tcx.hir_attrs(id).iter().any(|attr| { - if attr.has_name(sym::cfg) + if attr.has_name(sym::cfg_trace) && let Some(items) = attr.meta_item_list() && let [item] = &*items && item.has_name(sym::test) @@ -2723,11 +2723,11 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool { /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied. pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - tcx.has_attr(def_id, sym::cfg) + tcx.has_attr(def_id, sym::cfg_trace) || tcx .hir_parent_iter(tcx.local_def_id_to_hir_id(def_id)) .flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id)) - .any(|attr| attr.has_name(sym::cfg)) + .any(|attr| attr.has_name(sym::cfg_trace)) } /// Walks up the HIR tree from the given expression in an attempt to find where the value is From 0a05677d22825f66018361c3b6a55148bfc85650 Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 26 Mar 2025 06:37:56 -0700 Subject: [PATCH 0318/2248] `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 0319/2248] 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 2c70c8a6e0b220377536e4e13172bfdfcd95c50f Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Wed, 26 Mar 2025 13:52:22 -0400 Subject: [PATCH 0320/2248] mark cfg_match! semitransparent --- library/core/src/macros/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 5f200b31d1ae7..5571d8ad594a1 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -237,9 +237,10 @@ pub macro assert_matches { /// ``` #[unstable(feature = "cfg_match", issue = "115585")] #[rustc_diagnostic_item = "cfg_match"] +#[rustc_macro_transparency = "semitransparent"] pub macro cfg_match { ({ $($tt:tt)* }) => {{ - cfg_match! { $($tt)* } + $crate::cfg_match! { $($tt)* } }}, (_ => { $($output:tt)* }) => { $($output)* @@ -249,10 +250,10 @@ pub macro cfg_match { $($( $rest:tt )+)? ) => { #[cfg($cfg)] - cfg_match! { _ => $output } + $crate::cfg_match! { _ => $output } $( #[cfg(not($cfg))] - cfg_match! { $($rest)+ } + $crate::cfg_match! { $($rest)+ } )? }, } From 9b1945d9fb57516c585f7aea9dfe638ad3c7a397 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 26 Mar 2025 19:38:09 +0100 Subject: [PATCH 0321/2248] Prevent including preceeding whitespaces if line contains non blanks This extra condition prevents a problem when removing the '}' in: ```rust ( // There was an opening bracket after the parenthesis, which has been removed // This is a comment }) ``` Removing the whitespaces, including the linefeed, before the '}', would put the closing parenthesis at the end of the `// This is a comment` line, which would make it part of the comment as well. In this case, it is best to keep the span on the '}' alone. --- clippy_utils/src/source.rs | 25 ++++++++++++++++--- .../collapsible_if/collapsible_if.fixed | 4 +-- .../collapsible_if/collapsible_if.stderr | 4 +-- tests/ui/collapsible_if.fixed | 10 ++++++++ tests/ui/collapsible_if.rs | 10 ++++++++ tests/ui/collapsible_if.stderr | 20 ++++++++++++++- tests/ui/manual_inspect.fixed | 11 +++++++- tests/ui/manual_inspect.rs | 9 +++++++ tests/ui/manual_inspect.stderr | 17 +++++++++++-- 9 files changed, 98 insertions(+), 12 deletions(-) diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs index 80066e9702d34..f15906df627f4 100644 --- a/clippy_utils/src/source.rs +++ b/clippy_utils/src/source.rs @@ -142,7 +142,19 @@ pub trait SpanRangeExt: SpanRange { map_range(cx.sess().source_map(), self.into_range(), f) } - /// Extends the range to include all preceding whitespace characters. + /// Extends the range to include all preceding whitespace characters, unless there + /// are non-whitespace characters left on the same line after `self`. + /// + /// This extra condition prevents a problem when removing the '}' in: + /// ```ignore + /// ( // There was an opening bracket after the parenthesis, which has been removed + /// // This is a comment + /// }) + /// ``` + /// Removing the whitespaces, including the linefeed, before the '}', would put the + /// closing parenthesis at the end of the `// This is a comment` line, which would + /// make it part of the comment as well. In this case, it is best to keep the span + /// on the '}' alone. fn with_leading_whitespace(self, cx: &impl HasSession) -> Range { with_leading_whitespace(cx.sess().source_map(), self.into_range()) } @@ -263,10 +275,15 @@ fn map_range( } fn with_leading_whitespace(sm: &SourceMap, sp: Range) -> Range { - map_range(sm, sp.clone(), |src, range| { - Some(src.get(..range.start)?.trim_end().len()..range.end) + map_range(sm, sp, |src, range| { + let non_blank_after = src.len() - src.get(range.end..)?.trim_start().len(); + if src.get(range.end..non_blank_after)?.contains(['\r', '\n']) { + Some(src.get(..range.start)?.trim_end().len()..range.end) + } else { + Some(range) + } }) - .unwrap_or(sp) + .unwrap() } fn trim_start(sm: &SourceMap, sp: Range) -> Range { diff --git a/tests/ui-toml/collapsible_if/collapsible_if.fixed b/tests/ui-toml/collapsible_if/collapsible_if.fixed index f695f9804d59c..6f5cc47ba6c75 100644 --- a/tests/ui-toml/collapsible_if/collapsible_if.fixed +++ b/tests/ui-toml/collapsible_if/collapsible_if.fixed @@ -13,7 +13,7 @@ fn main() { //~^^^^^^ collapsible_if // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798 - if x == "hello" // Inner comment + if x == "hello" // Inner comment && y == "world" { println!("Hello world!"); } @@ -26,7 +26,7 @@ fn main() { } //~^^^^^^ collapsible_if - if x == "hello" /* Inner comment */ + if x == "hello" /* Inner comment */ && y == "world" { println!("Hello world!"); } diff --git a/tests/ui-toml/collapsible_if/collapsible_if.stderr b/tests/ui-toml/collapsible_if/collapsible_if.stderr index a12c2112f5877..357ce4ad32deb 100644 --- a/tests/ui-toml/collapsible_if/collapsible_if.stderr +++ b/tests/ui-toml/collapsible_if/collapsible_if.stderr @@ -32,7 +32,7 @@ LL | | } | help: collapse nested if block | -LL ~ if x == "hello" // Inner comment +LL ~ if x == "hello" // Inner comment LL ~ && y == "world" { LL | println!("Hello world!"); LL ~ } @@ -70,7 +70,7 @@ LL | | } | help: collapse nested if block | -LL ~ if x == "hello" /* Inner comment */ +LL ~ if x == "hello" /* Inner comment */ LL ~ && y == "world" { LL | println!("Hello world!"); LL ~ } diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index df281651ab14f..e1ceb04f9cb89 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -152,3 +152,13 @@ fn main() { } } } + +#[rustfmt::skip] +fn layout_check() -> u32 { + if true + && true { + } + // This is a comment, do not collapse code to it + ; 3 + //~^^^^^ collapsible_if +} diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index ce979568cc895..0b996dca22e85 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -162,3 +162,13 @@ fn main() { } } } + +#[rustfmt::skip] +fn layout_check() -> u32 { + if true { + if true { + } + // This is a comment, do not collapse code to it + }; 3 + //~^^^^^ collapsible_if +} diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 559db238cb182..532811462393b 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -172,5 +172,23 @@ LL | println!("No comment, linted"); LL ~ } | -error: aborting due to 10 previous errors +error: this `if` statement can be collapsed + --> tests/ui/collapsible_if.rs:168:5 + | +LL | / if true { +LL | | if true { +... | +LL | | }; 3 + | |_____^ + | +help: collapse nested if block + | +LL ~ if true +LL ~ && true { +LL | } +LL | // This is a comment, do not collapse code to it +LL ~ ; 3 + | + +error: aborting due to 11 previous errors diff --git a/tests/ui/manual_inspect.fixed b/tests/ui/manual_inspect.fixed index 8d045c48ceb04..ec87fe217aee6 100644 --- a/tests/ui/manual_inspect.fixed +++ b/tests/ui/manual_inspect.fixed @@ -107,7 +107,7 @@ fn main() { let _ = || { let _x = x; }; - return; + return ; } println!("test"); }); @@ -185,3 +185,12 @@ fn main() { }); } } + +#[rustfmt::skip] +fn layout_check() { + if let Some(x) = Some(1).inspect(|&x| { println!("{x}"); //~ manual_inspect + // Do not collapse code into this comment + }) { + println!("{x}"); + } +} diff --git a/tests/ui/manual_inspect.rs b/tests/ui/manual_inspect.rs index a89d28dab689c..e679636201e6a 100644 --- a/tests/ui/manual_inspect.rs +++ b/tests/ui/manual_inspect.rs @@ -197,3 +197,12 @@ fn main() { }); } } + +#[rustfmt::skip] +fn layout_check() { + if let Some(x) = Some(1).map(|x| { println!("{x}"); //~ manual_inspect + // Do not collapse code into this comment + x }) { + println!("{x}"); + } +} diff --git a/tests/ui/manual_inspect.stderr b/tests/ui/manual_inspect.stderr index 510325d2baaa9..eb98f9f5995a3 100644 --- a/tests/ui/manual_inspect.stderr +++ b/tests/ui/manual_inspect.stderr @@ -98,7 +98,7 @@ LL | if x.is_empty() { LL | let _ = || { LL ~ let _x = x; LL | }; -LL ~ return; +LL ~ return ; LL | } LL ~ println!("test"); | @@ -187,5 +187,18 @@ LL | LL ~ println!("{}", x); | -error: aborting due to 13 previous errors +error: using `map` over `inspect` + --> tests/ui/manual_inspect.rs:203:30 + | +LL | if let Some(x) = Some(1).map(|x| { println!("{x}"); + | ^^^ + | +help: try + | +LL ~ if let Some(x) = Some(1).inspect(|&x| { println!("{x}"); +LL | // Do not collapse code into this comment +LL ~ }) { + | + +error: aborting due to 14 previous errors From d872845eae7f9988995fb8ca35f86d08de999409 Mon Sep 17 00:00:00 2001 From: James Wainwright Date: Wed, 26 Mar 2025 20:45:55 +0000 Subject: [PATCH 0322/2248] Expose `Unique::from` in const internally --- library/core/src/ptr/unique.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 4810ebe01f9bb..d688ce2a07a6a 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -100,6 +100,12 @@ impl Unique { } } + /// Create a new `Unique` from a `NonNull` in const context. + #[inline] + pub const fn from_non_null(pointer: NonNull) -> Self { + Unique { pointer, _marker: PhantomData } + } + /// Acquires the underlying `*mut` pointer. #[must_use = "`self` will be dropped if the result is not used"] #[inline] @@ -202,6 +208,6 @@ impl From> for Unique { /// This conversion is infallible since `NonNull` cannot be null. #[inline] fn from(pointer: NonNull) -> Self { - Unique { pointer, _marker: PhantomData } + Unique::from_non_null(pointer) } } From 78e962139020df03174f03da6af91acc5cbb37e3 Mon Sep 17 00:00:00 2001 From: James Wainwright Date: Tue, 25 Mar 2025 21:43:19 +0000 Subject: [PATCH 0323/2248] Pass `Alignment` for `RawVecInner::new_in` Encodes the safety constraint that `Unique`'s pointer must be non-zero into the API. --- library/alloc/src/lib.rs | 1 + library/alloc/src/raw_vec/mod.rs | 9 +++++---- library/alloctests/lib.rs | 1 + library/core/src/alloc/layout.rs | 8 ++++++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f0cdb1e4e0f78..04858667230b3 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -135,6 +135,7 @@ #![feature(pattern)] #![feature(pin_coerce_unsized_trait)] #![feature(pointer_like_trait)] +#![feature(ptr_alignment_type)] #![feature(ptr_internals)] #![feature(ptr_metadata)] #![feature(set_ptr_value)] diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 99ebc5c4bfca8..83facd9d93216 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -6,7 +6,7 @@ use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; -use core::ptr::{self, NonNull, Unique}; +use core::ptr::{self, Alignment, NonNull, Unique}; use core::{cmp, hint}; #[cfg(not(no_global_oom_handling))] @@ -177,7 +177,7 @@ impl RawVec { /// the returned `RawVec`. #[inline] pub(crate) const fn new_in(alloc: A) -> Self { - Self { inner: RawVecInner::new_in(alloc, align_of::()), _marker: PhantomData } + Self { inner: RawVecInner::new_in(alloc, Alignment::of::()), _marker: PhantomData } } /// Like `with_capacity`, but parameterized over the choice of @@ -409,7 +409,8 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { impl RawVecInner { #[inline] - const fn new_in(alloc: A, align: usize) -> Self { + const fn new_in(alloc: A, align: Alignment) -> Self { + // SAFETY: `Alignment` is non-zero. let ptr = unsafe { core::mem::transmute(align) }; // `cap: 0` means "unallocated". zero-sized types are ignored. Self { ptr, cap: ZERO_CAP, alloc } @@ -465,7 +466,7 @@ impl RawVecInner { // Don't allocate here because `Drop` will not deallocate when `capacity` is 0. if layout.size() == 0 { - return Ok(Self::new_in(alloc, elem_layout.align())); + return Ok(Self::new_in(alloc, elem_layout.alignment())); } if let Err(err) = alloc_guard(layout.size()) { diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 6ce8a6d9ca174..3241b4b00454b 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -28,6 +28,7 @@ #![feature(iter_next_chunk)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array_transpose)] +#![feature(ptr_alignment_type)] #![feature(ptr_internals)] #![feature(sized_type_properties)] #![feature(slice_iter_mut_as_mut_slice)] diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 1595a3af883d1..e8a03aadc3390 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -520,6 +520,14 @@ impl Layout { unsafe { Ok(Layout::from_size_align_unchecked(array_size, align.as_usize())) } } } + + /// Perma-unstable access to `align` as `Alignment` type. + #[unstable(issue = "none", feature = "std_internals")] + #[doc(hidden)] + #[inline] + pub const fn alignment(&self) -> Alignment { + self.align + } } #[stable(feature = "alloc_layout", since = "1.28.0")] From aadfd810f62e2e07440672cc20a0540c9904d69b Mon Sep 17 00:00:00 2001 From: James Wainwright Date: Tue, 25 Mar 2025 21:44:54 +0000 Subject: [PATCH 0324/2248] Swap usize -> ptr transmute for strict_pov API Removes some unsafety and reduces the number of `usize` -> `ptr` transmutes which might be helpful for CHERI-like targets in the future. --- library/alloc/src/raw_vec/mod.rs | 3 +-- library/alloctests/lib.rs | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 83facd9d93216..a989e5b55b3d1 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -410,8 +410,7 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { impl RawVecInner { #[inline] const fn new_in(alloc: A, align: Alignment) -> Self { - // SAFETY: `Alignment` is non-zero. - let ptr = unsafe { core::mem::transmute(align) }; + let ptr = Unique::from_non_null(NonNull::without_provenance(align.as_nonzero())); // `cap: 0` means "unallocated". zero-sized types are ignored. Self { ptr, cap: ZERO_CAP, alloc } } diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 3241b4b00454b..56e60ed4c8448 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -28,6 +28,7 @@ #![feature(iter_next_chunk)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array_transpose)] +#![feature(nonnull_provenance)] #![feature(ptr_alignment_type)] #![feature(ptr_internals)] #![feature(sized_type_properties)] From af7359ee4fd25ac5fd92fa20c8b37405ac0d0c05 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 26 Mar 2025 12:10:47 -0700 Subject: [PATCH 0325/2248] 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 0326/2248] 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 a34c42fefabc774af2d8b2c5a5a100c0697d2ba9 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Wed, 26 Mar 2025 11:31:58 +0800 Subject: [PATCH 0327/2248] Expect an array when expected and acutal types are both arrays during cast Signed-off-by: xizheyin --- compiler/rustc_hir_typeck/src/cast.rs | 39 ++++++++++---------- tests/ui/cast/cast-array-issue-138836.rs | 2 +- tests/ui/cast/cast-array-issue-138836.stderr | 9 ++--- tests/ui/consts/const-cast-wrong-type.rs | 2 +- tests/ui/consts/const-cast-wrong-type.stderr | 6 +-- 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 8f5fddd19d7f6..b19d9efe2c6f5 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -1042,30 +1042,31 @@ impl<'a, 'tcx> CastCheck<'tcx> { m_cast: ty::TypeAndMut<'tcx>, ) -> Result> { // array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const - if m_expr.mutbl >= m_cast.mutbl { - if let ty::Array(ety, _) = m_expr.ty.kind() { - // Due to the limitations of LLVM global constants, - // region pointers end up pointing at copies of - // vector elements instead of the original values. - // To allow raw pointers to work correctly, we - // need to special-case obtaining a raw pointer - // from a region pointer to a vector. - - // Coerce to a raw pointer so that we generate RawPtr in MIR. - let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl); - fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None) - .unwrap_or_else(|_| { - bug!( + if m_expr.mutbl >= m_cast.mutbl + && let ty::Array(ety, _) = m_expr.ty.kind() + && fcx.can_eq(fcx.param_env, *ety, m_cast.ty) + { + // Due to the limitations of LLVM global constants, + // region pointers end up pointing at copies of + // vector elements instead of the original values. + // To allow raw pointers to work correctly, we + // need to special-case obtaining a raw pointer + // from a region pointer to a vector. + + // Coerce to a raw pointer so that we generate RawPtr in MIR. + let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl); + fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None) + .unwrap_or_else(|_| { + bug!( "could not cast from reference to array to pointer to array ({:?} to {:?})", self.expr_ty, array_ptr_type, ) - }); + }); - // this will report a type mismatch if needed - fcx.demand_eqtype(self.span, *ety, m_cast.ty); - return Ok(CastKind::ArrayPtrCast); - } + // this will report a type mismatch if needed + fcx.demand_eqtype(self.span, *ety, m_cast.ty); + return Ok(CastKind::ArrayPtrCast); } Err(CastError::IllegalCast) diff --git a/tests/ui/cast/cast-array-issue-138836.rs b/tests/ui/cast/cast-array-issue-138836.rs index 6fd65d5878ac9..3f8098e76fd29 100644 --- a/tests/ui/cast/cast-array-issue-138836.rs +++ b/tests/ui/cast/cast-array-issue-138836.rs @@ -1,5 +1,5 @@ fn main() { let a: [u8; 3] = [1,2,3]; let b = &a; - let c = b as *const [u32; 3]; //~ ERROR mismatched types [E0308] + let c = b as *const [u32; 3]; //~ ERROR casting `&[u8; 3]` as `*const [u32; 3]` is invalid } diff --git a/tests/ui/cast/cast-array-issue-138836.stderr b/tests/ui/cast/cast-array-issue-138836.stderr index fe20d429a4989..309474c29f933 100644 --- a/tests/ui/cast/cast-array-issue-138836.stderr +++ b/tests/ui/cast/cast-array-issue-138836.stderr @@ -1,12 +1,9 @@ -error[E0308]: mismatched types +error[E0606]: casting `&[u8; 3]` as `*const [u32; 3]` is invalid --> $DIR/cast-array-issue-138836.rs:4:13 | LL | let c = b as *const [u32; 3]; - | ^^^^^^^^^^^^^^^^^^^^ expected `[u8; 3]`, found `[u32; 3]` - | - = note: expected array `[u8; 3]` - found array `[u32; 3]` + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/consts/const-cast-wrong-type.rs b/tests/ui/consts/const-cast-wrong-type.rs index 6e055a2bcd340..9936a660936b0 100644 --- a/tests/ui/consts/const-cast-wrong-type.rs +++ b/tests/ui/consts/const-cast-wrong-type.rs @@ -1,5 +1,5 @@ const a: [u8; 3] = ['h' as u8, 'i' as u8, 0 as u8]; -const b: *const i8 = &a as *const i8; //~ ERROR mismatched types +const b: *const i8 = &a as *const i8; //~ ERROR casting `&[u8; 3]` as `*const i8` is invalid fn main() { } diff --git a/tests/ui/consts/const-cast-wrong-type.stderr b/tests/ui/consts/const-cast-wrong-type.stderr index 44361f15d8a98..0730bac22354d 100644 --- a/tests/ui/consts/const-cast-wrong-type.stderr +++ b/tests/ui/consts/const-cast-wrong-type.stderr @@ -1,9 +1,9 @@ -error[E0308]: mismatched types +error[E0606]: casting `&[u8; 3]` as `*const i8` is invalid --> $DIR/const-cast-wrong-type.rs:2:22 | LL | const b: *const i8 = &a as *const i8; - | ^^^^^^^^^^^^^^^ expected `u8`, found `i8` + | ^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0606`. From ad913a40619aa55787844994840a5cf4a44df132 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 26 Mar 2025 19:29:11 +0100 Subject: [PATCH 0328/2248] chore: Remove salsa dependency from proc-macro server again --- .../rust-analyzer/.github/workflows/ci.yaml | 3 ++ .../crates/proc-macro-srv-cli/Cargo.toml | 1 + .../rust-analyzer/crates/span/Cargo.toml | 5 +- .../rust-analyzer/crates/span/src/hygiene.rs | 46 ++++++++++++++----- .../rust-analyzer/crates/span/src/lib.rs | 20 ++++++++ 5 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index 8479d006319fa..610f8d00aae33 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -70,6 +70,9 @@ jobs: - name: Test run: cargo test --features sysroot-abi -p proc-macro-srv -p proc-macro-srv-cli -p proc-macro-api -- --quiet + - name: Check salsa dependency + run: "! (cargo tree -p proc-macro-srv-cli | grep -q salsa)" + rust: if: github.repository == 'rust-lang/rust-analyzer' name: Rust diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml index 57a28b00365f6..ab421021b8bfd 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml @@ -8,6 +8,7 @@ authors.workspace = true edition.workspace = true license.workspace = true rust-version.workspace = true +publish = false [dependencies] proc-macro-srv.workspace = true diff --git a/src/tools/rust-analyzer/crates/span/Cargo.toml b/src/tools/rust-analyzer/crates/span/Cargo.toml index 3381dac0b4255..b3b401c3db44a 100644 --- a/src/tools/rust-analyzer/crates/span/Cargo.toml +++ b/src/tools/rust-analyzer/crates/span/Cargo.toml @@ -12,7 +12,7 @@ authors.workspace = true [dependencies] la-arena.workspace = true -salsa.workspace = true +salsa = { workspace = true, optional = true } rustc-hash.workspace = true hashbrown.workspace = true text-size.workspace = true @@ -22,5 +22,8 @@ vfs.workspace = true syntax.workspace = true stdx.workspace = true +[features] +default = ["salsa"] + [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/span/src/hygiene.rs b/src/tools/rust-analyzer/crates/span/src/hygiene.rs index 9ecd188a3cc33..a2923cd22334d 100644 --- a/src/tools/rust-analyzer/crates/span/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/span/src/hygiene.rs @@ -21,16 +21,19 @@ //! `ExpnData::call_site` in rustc, [`MacroCallLoc::call_site`] in rust-analyzer. use std::fmt; -use crate::{Edition, MacroCallId}; +use crate::Edition; /// A syntax context describes a hierarchy tracking order of macro definitions. +#[cfg(feature = "salsa")] #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] pub struct SyntaxContext( salsa::Id, std::marker::PhantomData<&'static salsa::plumbing::interned::Value>, ); +#[cfg(feature = "salsa")] const _: () = { + use crate::MacroCallId; use salsa::plumbing as zalsa_; use salsa::plumbing::interned as zalsa_struct_; @@ -291,8 +294,6 @@ const _: () = { }; impl SyntaxContext { - const MAX_ID: u32 = salsa::Id::MAX_U32 - 1; - pub fn is_root(self) -> bool { (SyntaxContext::MAX_ID - Edition::LATEST as u32) <= self.into_u32() && self.into_u32() <= (SyntaxContext::MAX_ID - Edition::Edition2015 as u32) @@ -308,20 +309,43 @@ impl SyntaxContext { /// The root context, which is the parent of all other contexts. All [`FileId`]s have this context. pub const fn root(edition: Edition) -> Self { let edition = edition as u32; - SyntaxContext( - salsa::Id::from_u32(SyntaxContext::MAX_ID - edition), - std::marker::PhantomData, - ) + SyntaxContext::from_u32(SyntaxContext::MAX_ID - edition) } +} + +#[cfg(feature = "salsa")] +impl SyntaxContext { + const MAX_ID: u32 = salsa::Id::MAX_U32 - 1; - pub fn into_u32(self) -> u32 { + pub const fn into_u32(self) -> u32 { self.0.as_u32() } - pub fn from_u32(u32: u32) -> Self { + pub const fn from_u32(u32: u32) -> Self { Self(salsa::Id::from_u32(u32), std::marker::PhantomData) } } +#[cfg(not(feature = "salsa"))] +#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +pub struct SyntaxContext(u32); + +#[allow(dead_code)] +const SALSA_MAX_ID_MIRROR: u32 = u32::MAX - 0xFF; +#[cfg(feature = "salsa")] +const _: () = assert!(salsa::Id::MAX_U32 == SALSA_MAX_ID_MIRROR); + +#[cfg(not(feature = "salsa"))] +impl SyntaxContext { + const MAX_ID: u32 = SALSA_MAX_ID_MIRROR - 1; + + pub const fn into_u32(self) -> u32 { + self.0 + } + + pub const fn from_u32(u32: u32) -> Self { + Self(u32) + } +} /// A property of a macro expansion that determines how identifiers /// produced by that expansion are resolved. @@ -354,9 +378,9 @@ impl Transparency { impl fmt::Display for SyntaxContext { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.is_root() { - write!(f, "ROOT{}", Edition::from_u32(SyntaxContext::MAX_ID - self.0.as_u32()).number()) + write!(f, "ROOT{}", Edition::from_u32(SyntaxContext::MAX_ID - self.into_u32()).number()) } else { - write!(f, "{}", self.0.as_u32()) + write!(f, "{}", self.into_u32()) } } } diff --git a/src/tools/rust-analyzer/crates/span/src/lib.rs b/src/tools/rust-analyzer/crates/span/src/lib.rs index fbd1b25cffcaf..f3f6d80ad2743 100644 --- a/src/tools/rust-analyzer/crates/span/src/lib.rs +++ b/src/tools/rust-analyzer/crates/span/src/lib.rs @@ -180,6 +180,22 @@ impl EditionedFileId { } } +#[cfg(not(feature = "salsa"))] +mod salsa { + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] + pub(crate) struct Id(u32); + + impl Id { + pub(crate) const fn from_u32(u32: u32) -> Self { + Self(u32) + } + + pub(crate) const fn as_u32(self) -> u32 { + self.0 + } + } +} + /// Input to the analyzer is a set of files, where each file is identified by /// `FileId` and contains source code. However, another source of source code in /// Rust are macros: each macro can be thought of as producing a "temporary @@ -201,12 +217,14 @@ impl EditionedFileId { #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct HirFileId(salsa::Id); +#[cfg(feature = "salsa")] impl salsa::plumbing::AsId for HirFileId { fn as_id(&self) -> salsa::Id { self.0 } } +#[cfg(feature = "salsa")] impl salsa::plumbing::FromId for HirFileId { fn from_id(id: salsa::Id) -> Self { HirFileId(id) @@ -273,12 +291,14 @@ pub struct MacroFileId { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct MacroCallId(salsa::Id); +#[cfg(feature = "salsa")] impl salsa::plumbing::AsId for MacroCallId { fn as_id(&self) -> salsa::Id { self.0 } } +#[cfg(feature = "salsa")] impl salsa::plumbing::FromId for MacroCallId { fn from_id(id: salsa::Id) -> Self { MacroCallId(id) From 217eccfc3aac8a3a0721938cca6921c0e3ca0c46 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 27 Mar 2025 08:41:33 +0100 Subject: [PATCH 0329/2248] refactor: Shuffle some unsafety around in proc-macro-srv --- .../crates/proc-macro-srv/src/dylib.rs | 52 ++++++++++++++----- .../crates/proc-macro-srv/src/lib.rs | 2 +- .../crates/proc-macro-srv/src/proc_macros.rs | 28 +--------- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs index 245b064387e59..c49159df9916d 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs @@ -21,13 +21,32 @@ use crate::{ProcMacroKind, ProcMacroSrvSpan, proc_macros::ProcMacros, server_imp /// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1) /// /// It seems that on Windows that behaviour is default, so we do nothing in that case. +/// +/// # Safety +/// +/// The caller is responsible for ensuring that the path is valid proc-macro library #[cfg(windows)] -fn load_library(file: &Utf8Path) -> Result { +unsafe fn load_library(file: &Utf8Path) -> Result { + // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library unsafe { Library::new(file) } } +/// Loads dynamic library in platform dependent manner. +/// +/// For unix, you have to use RTLD_DEEPBIND flag to escape problems described +/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample) +/// and [here](https://github.com/rust-lang/rust/issues/60593). +/// +/// Usage of RTLD_DEEPBIND +/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1) +/// +/// It seems that on Windows that behaviour is default, so we do nothing in that case. +/// +/// # Safety +/// +/// The caller is responsible for ensuring that the path is valid proc-macro library #[cfg(unix)] -fn load_library(file: &Utf8Path) -> Result { +unsafe fn load_library(file: &Utf8Path) -> Result { // not defined by POSIX, different values on mips vs other targets #[cfg(target_env = "gnu")] use libc::RTLD_DEEPBIND; @@ -39,6 +58,7 @@ fn load_library(file: &Utf8Path) -> Result { #[cfg(not(target_env = "gnu"))] const RTLD_DEEPBIND: std::os::raw::c_int = 0x0; + // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library unsafe { UnixLibrary::open(Some(file), RTLD_NOW | RTLD_DEEPBIND).map(|lib| lib.into()) } } @@ -84,26 +104,32 @@ struct ProcMacroLibrary { impl ProcMacroLibrary { fn open(path: &Utf8Path) -> Result { let file = fs::File::open(path)?; + #[allow(clippy::undocumented_unsafe_blocks)] // FIXME let file = unsafe { memmap2::Mmap::map(&file) }?; let obj = object::File::parse(&*file) .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; let version_info = version::read_dylib_info(&obj)?; + if version_info.version_string != crate::RUSTC_VERSION_STRING { + return Err(LoadProcMacroDylibError::AbiMismatch(version_info.version_string)); + } + let symbol_name = find_registrar_symbol(&obj).map_err(invalid_data_err)?.ok_or_else(|| { invalid_data_err(format!("Cannot find registrar symbol in file {path}")) })?; - let lib = load_library(path).map_err(invalid_data_err)?; - let proc_macros = unsafe { - // SAFETY: We extend the lifetime here to avoid referential borrow problems - // We never reveal proc_macros to the outside and drop it before _lib - std::mem::transmute::<&ProcMacros, &'static ProcMacros>(ProcMacros::from_lib( - &lib, - symbol_name, - &version_info.version_string, - )?) - }; - Ok(ProcMacroLibrary { _lib: lib, proc_macros }) + // SAFETY: We have verified the validity of the dylib as a proc-macro library + let lib = unsafe { load_library(path) }.map_err(invalid_data_err)?; + // SAFETY: We have verified the validity of the dylib as a proc-macro library + // The 'static lifetime is a lie, it's actually the lifetime of the library but unavoidable + // due to self-referentiality + // But we make sure that we do not drop it before the symbol is dropped + let proc_macros = + unsafe { lib.get::<&'static &'static ProcMacros>(symbol_name.as_bytes()) }; + match proc_macros { + Ok(proc_macros) => Ok(ProcMacroLibrary { proc_macros: *proc_macros, _lib: lib }), + Err(e) => Err(e.into()), + } } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index 2623b2d45cd43..223c5a54b7034 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -15,7 +15,7 @@ #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)] #![allow(unreachable_pub, internal_features, clippy::disallowed_types, clippy::print_stderr)] -#![deny(deprecated_safe)] +#![deny(deprecated_safe, clippy::undocumented_unsafe_blocks)] extern crate proc_macro; #[cfg(feature = "in-rust-tree")] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs index a5fa7f6e71a6d..42474ab59264b 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs @@ -2,11 +2,7 @@ use proc_macro::bridge; -use libloading::Library; - -use crate::{ - ProcMacroKind, ProcMacroSrvSpan, dylib::LoadProcMacroDylibError, server_impl::TopSubtree, -}; +use crate::{ProcMacroKind, ProcMacroSrvSpan, server_impl::TopSubtree}; #[repr(transparent)] pub(crate) struct ProcMacros([bridge::client::ProcMacro]); @@ -18,28 +14,6 @@ impl From for crate::PanicMessage { } impl ProcMacros { - /// Load a new ABI. - /// - /// # Arguments - /// - /// *`lib` - The dynamic library containing the macro implementations - /// *`symbol_name` - The symbol name the macros can be found attributes - /// *`info` - RustCInfo about the compiler that was used to compile the - /// macro crate. This is the information we use to figure out - /// which ABI to return - pub(crate) fn from_lib<'l>( - lib: &'l Library, - symbol_name: String, - version_string: &str, - ) -> Result<&'l ProcMacros, LoadProcMacroDylibError> { - if version_string != crate::RUSTC_VERSION_STRING { - return Err(LoadProcMacroDylibError::AbiMismatch(version_string.to_owned())); - } - unsafe { lib.get::<&'l &'l ProcMacros>(symbol_name.as_bytes()) } - .map(|it| **it) - .map_err(Into::into) - } - pub(crate) fn expand( &self, macro_name: &str, From 27ece57615cc6fbf727af86f73d449535307a13b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 27 Mar 2025 08:55:09 +0100 Subject: [PATCH 0330/2248] fix: Fix `format_args` lowering using wrong integer suffix --- src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs | 3 ++- src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 86f31dcaf009b..8059023f0bb89 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -2400,7 +2400,8 @@ impl ExprCollector<'_> { Some(FormatCount::Literal(n)) => { let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint( *n as u128, - Some(BuiltinUint::Usize), + // FIXME: Change this to Some(BuiltinUint::U16) once we drop support for toolchains < 1.88 + None, ))); let count_is = match LangItem::FormatCount.ty_rel_path( self.db, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs index a6fcfaa445e3e..55b95eb87546a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs @@ -216,7 +216,7 @@ fn main() { 8u32, builtin#lang(Count::Implied), builtin#lang(Count::Is)( - 2usize, + 2, ), ), builtin#lang(Placeholder::new)( 1usize, From d9913dd6ad07f113aa83b835da8253bdca4342a9 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 9 Mar 2025 08:36:37 +0100 Subject: [PATCH 0331/2248] Do not warn about shadowing in a destructuring assigment When lowering a destructuring assignment from AST to HIR, the compiler will reuse the same identifier name (namely `sym::lhs`) for all the fields. The desugaring must be checked for to avoid a false positive of the `shadow_unrelated` lint. --- clippy_lints/src/shadow.rs | 15 ++++++++++++++- tests/ui/shadow.rs | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index ee282ee1dfb71..10e03ac19bd1f 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -8,7 +8,9 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::Res; use rustc_hir::def_id::LocalDefId; use rustc_hir::hir_id::ItemLocalId; -use rustc_hir::{Block, Body, BodyOwnerKind, Expr, ExprKind, HirId, LetExpr, Node, Pat, PatKind, QPath, UnOp}; +use rustc_hir::{ + Block, Body, BodyOwnerKind, Expr, ExprKind, HirId, LetExpr, LocalSource, Node, Pat, PatKind, QPath, UnOp, +}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::{Span, Symbol}; @@ -125,6 +127,17 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { return; } + // Desugaring of a destructuring assignment may reuse the same identifier internally. + // Peel `Pat` and `PatField` nodes and check if we reach a desugared `Let` assignment. + if let Some((_, Node::LetStmt(let_stmt))) = cx + .tcx + .hir_parent_iter(pat.hir_id) + .find(|(_, node)| !matches!(node, Node::Pat(_) | Node::PatField(_))) + && let LocalSource::AssignDesugar(_) = let_stmt.source + { + return; + } + let HirId { owner, local_id } = id; // get (or insert) the list of items for this owner and symbol let (ref mut data, scope_owner) = *self.bindings.last_mut().unwrap(); diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index 7d503a1cf6c17..05009b2ddd416 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -167,4 +167,19 @@ fn issue13795(value: Issue13795) { //~^ shadow_same } +fn issue14377() { + let a; + let b; + (a, b) = (0, 1); + + struct S { + c: i32, + d: i32, + } + + let c; + let d; + S { c, d } = S { c: 1, d: 2 }; +} + fn main() {} From 87325a41b55959ee02ca2cf93e54cbfbbf76f681 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 16 Mar 2025 13:24:11 +0200 Subject: [PATCH 0332/2248] Allow crate authors to control completion of their things Via the new `#[rust_analyzer::completions(...)]` attribute. Also fix a bug with existing settings for that where the paths wouldn't resolve correctly. --- .../rust-analyzer/crates/hir-def/src/data.rs | 166 +++++++++++++----- .../crates/hir-def/src/data/adt.rs | 9 +- .../crates/hir-def/src/import_map.rs | 38 ++-- .../crates/hir-def/src/item_scope.rs | 2 +- .../crates/hir-def/src/item_tree.rs | 18 +- .../crates/hir-def/src/item_tree/lower.rs | 31 ++-- .../crates/hir-def/src/item_tree/pretty.rs | 22 +-- .../rust-analyzer/crates/hir-def/src/lib.rs | 81 ++++++++- .../hir-ty/src/diagnostics/decl_check.rs | 2 +- .../hir-ty/src/diagnostics/unsafe_check.rs | 4 +- .../rust-analyzer/crates/hir-ty/src/lower.rs | 2 +- .../crates/hir-ty/src/method_resolution.rs | 10 +- .../crates/hir-ty/src/mir/eval.rs | 2 +- .../rust-analyzer/crates/hir/src/display.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 72 +++++++- .../rust-analyzer/crates/hir/src/symbols.rs | 98 +++++++---- .../replace_derive_with_manual_impl.rs | 2 +- .../ide-completion/src/completions/dot.rs | 6 +- .../ide-completion/src/completions/expr.rs | 14 +- .../src/completions/flyimport.rs | 55 +++--- .../crates/ide-completion/src/context.rs | 21 +-- .../crates/ide-completion/src/render.rs | 2 +- .../crates/ide-completion/src/snippet.rs | 2 +- .../ide-completion/src/tests/expression.rs | 147 +++++++++------- .../ide-completion/src/tests/flyimport.rs | 117 +++++++++++- .../ide-db/src/imports/import_assets.rs | 69 ++++++-- .../crates/ide-db/src/items_locator.rs | 23 +-- .../ide-db/src/test_data/test_doc_alias.txt | 7 + .../test_symbol_index_collection.txt | 31 ++++ .../crates/intern/src/symbol/symbols.rs | 4 + 30 files changed, 768 insertions(+), 291 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index b251564016c7e..e1fe13f9af059 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -12,7 +12,7 @@ use crate::{ ConstId, ExternCrateId, FunctionId, HasModule, ImplId, ItemContainerId, ItemLoc, Lookup, Macro2Id, MacroRulesId, ProcMacroId, StaticId, TraitAliasId, TraitId, TypeAliasId, db::DefDatabase, - item_tree::{self, FnFlags, ModItem}, + item_tree::{self, FnFlags, ModItem, StaticFlags}, nameres::proc_macro::{ProcMacroKind, parse_macro_name_and_helper_attrs}, path::ImportAlias, type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap}, @@ -27,9 +27,8 @@ pub struct FunctionData { pub visibility: RawVisibility, pub abi: Option, pub legacy_const_generics_indices: Option>>, - pub rustc_allow_incoherent_impl: bool, pub types_map: Arc, - flags: FnFlags, + pub flags: FnFlags, } impl FunctionData { @@ -72,7 +71,9 @@ impl FunctionData { } let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); - let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists(); + if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() { + flags |= FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL; + } if flags.contains(FnFlags::HAS_UNSAFE_KW) && attrs.by_key(&sym::rustc_deprecated_safe_2024).exists() { @@ -101,51 +102,65 @@ impl FunctionData { legacy_const_generics_indices: attrs.rustc_legacy_const_generics(), types_map: func.types_map.clone(), flags, - rustc_allow_incoherent_impl, }) } + #[inline] pub fn has_body(&self) -> bool { self.flags.contains(FnFlags::HAS_BODY) } /// True if the first param is `self`. This is relevant to decide whether this /// can be called as a method. + #[inline] pub fn has_self_param(&self) -> bool { self.flags.contains(FnFlags::HAS_SELF_PARAM) } + #[inline] pub fn is_default(&self) -> bool { self.flags.contains(FnFlags::HAS_DEFAULT_KW) } + #[inline] pub fn is_const(&self) -> bool { self.flags.contains(FnFlags::HAS_CONST_KW) } + #[inline] pub fn is_async(&self) -> bool { self.flags.contains(FnFlags::HAS_ASYNC_KW) } + #[inline] pub fn is_unsafe(&self) -> bool { self.flags.contains(FnFlags::HAS_UNSAFE_KW) } + #[inline] pub fn is_deprecated_safe_2024(&self) -> bool { self.flags.contains(FnFlags::DEPRECATED_SAFE_2024) } + #[inline] pub fn is_safe(&self) -> bool { self.flags.contains(FnFlags::HAS_SAFE_KW) } + #[inline] pub fn is_varargs(&self) -> bool { self.flags.contains(FnFlags::IS_VARARGS) } + #[inline] pub fn has_target_feature(&self) -> bool { self.flags.contains(FnFlags::HAS_TARGET_FEATURE) } + + #[inline] + pub fn rustc_allow_incoherent_impl(&self) -> bool { + self.flags.contains(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL) + } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -153,15 +168,37 @@ pub struct TypeAliasData { pub name: Name, pub type_ref: Option, pub visibility: RawVisibility, - pub is_extern: bool, - pub rustc_has_incoherent_inherent_impls: bool, - pub rustc_allow_incoherent_impl: bool, + pub flags: TypeAliasFlags, /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). pub bounds: Box<[TypeBound]>, pub types_map: Arc, } +bitflags::bitflags! { + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct TypeAliasFlags: u8 { + const IS_EXTERN = 1 << 0; + const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 1; + const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 2; + } +} + impl TypeAliasData { + #[inline] + pub fn is_extern(&self) -> bool { + self.flags.contains(TypeAliasFlags::IS_EXTERN) + } + + #[inline] + pub fn rustc_has_incoherent_inherent_impls(&self) -> bool { + self.flags.contains(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) + } + + #[inline] + pub fn rustc_allow_incoherent_impl(&self) -> bool { + self.flags.contains(TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL) + } + pub(crate) fn type_alias_data_query( db: &dyn DefDatabase, typ: TypeAliasId, @@ -180,17 +217,24 @@ impl TypeAliasData { loc.container.module(db).krate(), ModItem::from(loc.id.value).into(), ); - let rustc_has_incoherent_inherent_impls = - attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists(); - let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists(); + + let mut flags = TypeAliasFlags::empty(); + + if matches!(loc.container, ItemContainerId::ExternBlockId(_)) { + flags |= TypeAliasFlags::IS_EXTERN; + } + if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() { + flags |= TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; + } + if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() { + flags |= TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL; + } Arc::new(TypeAliasData { name: typ.name.clone(), type_ref: typ.type_ref, visibility, - is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)), - rustc_has_incoherent_inherent_impls, - rustc_allow_incoherent_impl, + flags, bounds: typ.bounds.clone(), types_map: typ.types_map.clone(), }) @@ -199,7 +243,7 @@ impl TypeAliasData { bitflags::bitflags! { #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] - pub struct TraitFlags: u8 { + pub struct TraitFlags: u16 { const IS_AUTO = 1 << 0; const IS_UNSAFE = 1 << 1; const IS_FUNDAMENTAL = 1 << 2; @@ -332,9 +376,9 @@ impl Macro2Data { let loc = makro.lookup(db); let item_tree = loc.id.item_tree(db); let makro = &item_tree[loc.id.value]; + let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()); - let helpers = item_tree - .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()) + let helpers = attrs .by_key(&sym::rustc_builtin_macro) .tt_values() .next() @@ -362,11 +406,9 @@ impl MacroRulesData { let loc = makro.lookup(db); let item_tree = loc.id.item_tree(db); let makro = &item_tree[loc.id.value]; + let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()); - let macro_export = item_tree - .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()) - .by_key(&sym::macro_export) - .exists(); + let macro_export = attrs.by_key(&sym::macro_export).exists(); Arc::new(MacroRulesData { name: makro.name.clone(), macro_export }) } @@ -387,11 +429,9 @@ impl ProcMacroData { let loc = makro.lookup(db); let item_tree = loc.id.item_tree(db); let makro = &item_tree[loc.id.value]; + let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()); - let (name, helpers) = if let Some(def) = item_tree - .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()) - .parse_proc_macro_decl(&makro.name) - { + let (name, helpers) = if let Some(def) = attrs.parse_proc_macro_decl(&makro.name) { ( def.name, match def.kind { @@ -404,6 +444,7 @@ impl ProcMacroData { stdx::never!("proc macro declaration is not a proc macro"); (makro.name.clone(), None) }; + Arc::new(ProcMacroData { name, helpers }) } } @@ -450,9 +491,16 @@ pub struct ConstData { pub name: Option, pub type_ref: TypeRefId, pub visibility: RawVisibility, - pub rustc_allow_incoherent_impl: bool, - pub has_body: bool, pub types_map: Arc, + pub flags: ConstFlags, +} + +bitflags::bitflags! { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + pub struct ConstFlags: u8 { + const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 0; + const HAS_BODY = 1 << 1; + } } impl ConstData { @@ -465,21 +513,38 @@ impl ConstData { } else { item_tree[konst.visibility].clone() }; + let attrs = item_tree.attrs( + db, + loc.container.module(db).krate(), + ModItem::from(loc.id.value).into(), + ); - let rustc_allow_incoherent_impl = item_tree - .attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into()) - .by_key(&sym::rustc_allow_incoherent_impl) - .exists(); + let mut flags = ConstFlags::empty(); + if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() { + flags |= ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL; + } + if konst.has_body { + flags |= ConstFlags::HAS_BODY; + } Arc::new(ConstData { name: konst.name.clone(), type_ref: konst.type_ref, visibility, - rustc_allow_incoherent_impl, - has_body: konst.has_body, + flags, types_map: konst.types_map.clone(), }) } + + #[inline] + pub fn rustc_allow_incoherent_impl(&self) -> bool { + self.flags.contains(ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL) + } + + #[inline] + pub fn has_body(&self) -> bool { + self.flags.contains(ConstFlags::HAS_BODY) + } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -487,11 +552,8 @@ pub struct StaticData { pub name: Name, pub type_ref: TypeRefId, pub visibility: RawVisibility, - pub mutable: bool, - pub is_extern: bool, - pub has_safe_kw: bool, - pub has_unsafe_kw: bool, pub types_map: Arc, + pub flags: StaticFlags, } impl StaticData { @@ -500,17 +562,39 @@ impl StaticData { let item_tree = loc.id.item_tree(db); let statik = &item_tree[loc.id.value]; + let mut flags = statik.flags; + if matches!(loc.container, ItemContainerId::ExternBlockId(_)) { + flags |= StaticFlags::IS_EXTERN; + } + Arc::new(StaticData { name: statik.name.clone(), type_ref: statik.type_ref, visibility: item_tree[statik.visibility].clone(), - mutable: statik.mutable, - is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)), - has_safe_kw: statik.has_safe_kw, - has_unsafe_kw: statik.has_unsafe_kw, + flags, types_map: statik.types_map.clone(), }) } + + #[inline] + pub fn is_extern(&self) -> bool { + self.flags.contains(StaticFlags::IS_EXTERN) + } + + #[inline] + pub fn mutable(&self) -> bool { + self.flags.contains(StaticFlags::MUTABLE) + } + + #[inline] + pub fn has_safe_kw(&self) -> bool { + self.flags.contains(StaticFlags::HAS_SAFE_KW) + } + + #[inline] + pub fn has_unsafe_kw(&self) -> bool { + self.flags.contains(StaticFlags::HAS_UNSAFE_KW) + } } fn trait_vis(db: &dyn DefDatabase, trait_id: TraitId) -> RawVisibility { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index e470fe689b914..a54d7663ccacc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -226,6 +226,7 @@ impl StructData { let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); let mut flags = StructFlags::NO_FLAGS; + if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() { flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL; } @@ -290,10 +291,10 @@ impl EnumData { let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); - let rustc_has_incoherent_inherent_impls = item_tree - .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()) - .by_key(&sym::rustc_has_incoherent_inherent_impls) - .exists(); + let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()); + + let rustc_has_incoherent_inherent_impls = + attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists(); let enum_ = &item_tree[loc.id.value]; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs index 717566f9d7960..b1622eaf83739 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs @@ -9,11 +9,11 @@ use itertools::Itertools; use rustc_hash::FxHashSet; use smallvec::SmallVec; use span::Edition; -use stdx::{TupleExt, format_to}; +use stdx::format_to; use triomphe::Arc; use crate::{ - AssocItemId, FxIndexMap, ModuleDefId, ModuleId, TraitId, + AssocItemId, AttrDefId, Complete, FxIndexMap, ModuleDefId, ModuleId, TraitId, db::DefDatabase, item_scope::{ImportOrExternCrate, ItemInNs}, nameres::DefMap, @@ -31,6 +31,8 @@ pub struct ImportInfo { pub is_doc_hidden: bool, /// Whether this item is annotated with `#[unstable(..)]`. pub is_unstable: bool, + /// The value of `#[rust_analyzer::completions(...)]`, if exists. + pub complete: Complete, } /// A map from publicly exported items to its name. @@ -172,16 +174,22 @@ impl ImportMap { ItemInNs::Macros(id) => Some(id.into()), } }; - let (is_doc_hidden, is_unstable) = attr_id.map_or((false, false), |attr_id| { - let attrs = db.attrs(attr_id); - (attrs.has_doc_hidden(), attrs.is_unstable()) - }); + let (is_doc_hidden, is_unstable, do_not_complete) = match attr_id { + None => (false, false, Complete::Yes), + Some(attr_id) => { + let attrs = db.attrs(attr_id); + let do_not_complete = + Complete::extract(matches!(attr_id, AttrDefId::TraitId(_)), &attrs); + (attrs.has_doc_hidden(), attrs.is_unstable(), do_not_complete) + } + }; let import_info = ImportInfo { name: name.clone(), container: module, is_doc_hidden, is_unstable, + complete: do_not_complete, }; if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { @@ -235,12 +243,17 @@ impl ImportMap { ItemInNs::Values(module_def_id) }; - let attrs = &db.attrs(item.into()); + let attr_id = item.into(); + let attrs = &db.attrs(attr_id); + let item_do_not_complete = Complete::extract(false, attrs); + let do_not_complete = + Complete::for_trait_item(trait_import_info.complete, item_do_not_complete); let assoc_item_info = ImportInfo { container: trait_import_info.container, name: assoc_item_name.clone(), is_doc_hidden: attrs.has_doc_hidden(), is_unstable: attrs.is_unstable(), + complete: do_not_complete, }; let (infos, _) = @@ -398,7 +411,7 @@ pub fn search_dependencies( db: &dyn DefDatabase, krate: Crate, query: &Query, -) -> FxHashSet { +) -> FxHashSet<(ItemInNs, Complete)> { let _p = tracing::info_span!("search_dependencies", ?query).entered(); let import_maps: Vec<_> = @@ -439,7 +452,7 @@ fn search_maps( import_maps: &[Arc], mut stream: fst::map::Union<'_>, query: &Query, -) -> FxHashSet { +) -> FxHashSet<(ItemInNs, Complete)> { let mut res = FxHashSet::default(); while let Some((_, indexed_values)) = stream.next() { for &IndexedValue { index: import_map_idx, value } in indexed_values { @@ -459,8 +472,9 @@ fn search_maps( }) .filter(|&(_, info)| { query.search_mode.check(&query.query, query.case_sensitive, info.name.as_str()) - }); - res.extend(iter.map(TupleExt::head)); + }) + .map(|(item, import_info)| (item, import_info.complete)); + res.extend(iter); } } @@ -521,7 +535,7 @@ mod tests { let actual = search_dependencies(db.upcast(), krate, &query) .into_iter() - .filter_map(|dependency| { + .filter_map(|(dependency, _)| { let dependency_krate = dependency.krate(db.upcast())?; let dependency_imports = db.import_map(dependency_krate); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index 47ad020043ce0..a299cfbdd19ab 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -358,7 +358,7 @@ impl ItemScope { } /// Get a name from current module scope, legacy macros are not included - pub(crate) fn get(&self, name: &Name) -> PerNs { + pub fn get(&self, name: &Name) -> PerNs { PerNs { types: self.types.get(name).copied(), values: self.values.get(name).copied(), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 80d666a0aba10..1cabb665d0628 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -962,7 +962,7 @@ pub struct Param { bitflags::bitflags! { #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] - pub(crate) struct FnFlags: u16 { + pub struct FnFlags: u16 { const HAS_SELF_PARAM = 1 << 0; const HAS_BODY = 1 << 1; const HAS_DEFAULT_KW = 1 << 2; @@ -977,6 +977,7 @@ bitflags::bitflags! { /// it if needed. const HAS_TARGET_FEATURE = 1 << 8; const DEPRECATED_SAFE_2024 = 1 << 9; + const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 10; } } @@ -1050,15 +1051,22 @@ pub struct Const { pub struct Static { pub name: Name, pub visibility: RawVisibilityId, - // TODO: use bitflags when we have more flags - pub mutable: bool, - pub has_safe_kw: bool, - pub has_unsafe_kw: bool, + pub flags: StaticFlags, pub type_ref: TypeRefId, pub ast_id: FileAstId, pub types_map: Arc, } +bitflags::bitflags! { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + pub struct StaticFlags: u8 { + const MUTABLE = 1 << 0; + const IS_EXTERN = 1 << 1; + const HAS_SAFE_KW = 1 << 2; + const HAS_UNSAFE_KW = 1 << 3; + } +} + #[derive(Debug, Clone, Eq, PartialEq)] pub struct Trait { pub name: Name, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 5389ba49c577f..4a3deec5ffd22 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -29,8 +29,8 @@ use crate::{ GenericModItem, Idx, Impl, ImportAlias, Interned, ItemTree, ItemTreeData, ItemTreeSourceMaps, ItemTreeSourceMapsBuilder, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, ModPath, Mutability, Name, Param, Path, Range, RawAttrs, RawIdx, RawVisibilityId, - Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, - Variant, + Static, StaticFlags, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, + UseTreeKind, Variant, }, lower::LowerCtx, path::AssociatedTypeBinding, @@ -620,22 +620,23 @@ impl<'a> Ctx<'a> { let name = static_.name()?.as_name(); let type_ref = TypeRef::from_ast_opt(&mut body_ctx, static_.ty()); let visibility = self.lower_visibility(static_); - let mutable = static_.mut_token().is_some(); - let has_safe_kw = static_.safe_token().is_some(); - let has_unsafe_kw = static_.unsafe_token().is_some(); + + let mut flags = StaticFlags::empty(); + if static_.mut_token().is_some() { + flags |= StaticFlags::MUTABLE; + } + if static_.safe_token().is_some() { + flags |= StaticFlags::HAS_SAFE_KW; + } + if static_.unsafe_token().is_some() { + flags |= StaticFlags::HAS_UNSAFE_KW; + } + let ast_id = self.source_ast_id_map.ast_id(static_); types_map.shrink_to_fit(); types_source_map.shrink_to_fit(); - let res = Static { - name, - visibility, - mutable, - type_ref, - ast_id, - has_safe_kw, - has_unsafe_kw, - types_map: Arc::new(types_map), - }; + let res = + Static { name, visibility, type_ref, ast_id, flags, types_map: Arc::new(types_map) }; self.source_maps.statics.push(types_source_map); Some(id(self.data().statics.alloc(res))) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index f44a000ac1baf..b79b8a28b3ed6 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -11,8 +11,8 @@ use crate::{ AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldParent, FieldsShape, FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl, ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, Path, RawAttrs, - RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound, Union, Use, - UseTree, UseTreeKind, Variant, + RawVisibilityId, Static, StaticFlags, Struct, Trait, TraitAlias, TypeAlias, TypeBound, + Union, Use, UseTree, UseTreeKind, Variant, }, pretty::{print_path, print_type_bounds, print_type_ref}, type_ref::{TypeRefId, TypesMap}, @@ -418,26 +418,18 @@ impl Printer<'_> { wln!(self, " = _;"); } ModItem::Static(it) => { - let Static { - name, - visibility, - mutable, - type_ref, - ast_id, - has_safe_kw, - has_unsafe_kw, - types_map, - } = &self.tree[it]; + let Static { name, visibility, type_ref, ast_id, types_map, flags } = + &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); - if *has_safe_kw { + if flags.contains(StaticFlags::HAS_SAFE_KW) { w!(self, "safe "); } - if *has_unsafe_kw { + if flags.contains(StaticFlags::HAS_UNSAFE_KW) { w!(self, "unsafe "); } w!(self, "static "); - if *mutable { + if flags.contains(StaticFlags::MUTABLE) { w!(self, "mut "); } w!(self, "{}: ", name.display(self.db.upcast(), self.edition)); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 4601960c7efb2..ab897f4e36192 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -53,7 +53,7 @@ pub mod find_path; pub mod import_map; pub mod visibility; -use intern::Interned; +use intern::{Interned, sym}; pub use rustc_abi as layout; use triomphe::Arc; @@ -86,6 +86,7 @@ use syntax::{AstNode, ast}; pub use hir_expand::{Intern, Lookup, tt}; use crate::{ + attr::Attrs, builtin_type::BuiltinType, data::adt::VariantData, db::DefDatabase, @@ -1502,3 +1503,81 @@ pub struct UnresolvedMacro { #[derive(Default, Debug, Eq, PartialEq, Clone, Copy)] pub struct SyntheticSyntax; + +// Feature: Completions Attribute +// Crate authors can opt their type out of completions in some cases. +// This is done with the `#[rust_analyzer::completions(...)]` attribute. +// +// All completeable things support `#[rust_analyzer::completions(ignore_flyimport)]`, +// which causes the thing to get excluded from flyimport completion. It will still +// be completed when in scope. This is analogous to the setting `rust-analyzer.completion.autoimport.exclude` +// with `"type": "always"`. +// +// In addition, traits support two more modes: `#[rust_analyzer::completions(ignore_flyimport_methods)]`, +// which means the trait itself may still be flyimported but its methods won't, and +// `#[rust_analyzer::completions(ignore_methods)]`, which means the methods won't be completed even when +// the trait is in scope (but the trait itself may still be completed). The methods will still be completed +// on `dyn Trait`, `impl Trait` or where the trait is specified in bounds. These modes correspond to +// the settings `rust-analyzer.completion.autoimport.exclude` with `"type": "methods"` and +// `rust-analyzer.completion.excludeTraits`, respectively. +// +// Malformed attributes will be ignored without warnings. +// +// Note that users have no way to override this attribute, so be careful and only include things +// users definitely do not want to be completed! + +/// `#[rust_analyzer::completions(...)]` options. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Complete { + /// No `#[rust_analyzer::completions(...)]`. + Yes, + /// `#[rust_analyzer::completions(ignore_flyimport)]`. + IgnoreFlyimport, + /// `#[rust_analyzer::completions(ignore_flyimport_methods)]` (on a trait only). + IgnoreFlyimportMethods, + /// `#[rust_analyzer::completions(ignore_methods)]` (on a trait only). + IgnoreMethods, +} + +impl Complete { + pub fn extract(is_trait: bool, attrs: &Attrs) -> Complete { + let mut do_not_complete = Complete::Yes; + for ra_attr in attrs.rust_analyzer_tool() { + let segments = ra_attr.path.segments(); + if segments.len() != 2 { + continue; + } + let action = segments[1].symbol(); + if *action == sym::completions { + match ra_attr.token_tree_value().map(|tt| tt.token_trees().flat_tokens()) { + Some([tt::TokenTree::Leaf(tt::Leaf::Ident(ident))]) => { + if ident.sym == sym::ignore_flyimport { + do_not_complete = Complete::IgnoreFlyimport; + } else if is_trait { + if ident.sym == sym::ignore_methods { + do_not_complete = Complete::IgnoreMethods; + } else if ident.sym == sym::ignore_flyimport_methods { + do_not_complete = Complete::IgnoreFlyimportMethods; + } + } + } + _ => {} + } + } + } + do_not_complete + } + + #[inline] + pub fn for_trait_item(trait_attr: Complete, item_attr: Complete) -> Complete { + match (trait_attr, item_attr) { + ( + Complete::IgnoreFlyimportMethods + | Complete::IgnoreFlyimport + | Complete::IgnoreMethods, + _, + ) => Complete::IgnoreFlyimport, + _ => item_attr, + } + } +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index ce0ffb1792641..5fb8e8e60a157 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -558,7 +558,7 @@ impl<'a> DeclValidator<'a> { fn validate_static(&mut self, static_id: StaticId) { let data = self.db.static_data(static_id); - if data.is_extern { + if data.is_extern() { cov_mark::hit!(extern_static_incorrect_case_ignored); return; } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs index 562a9aa085a1f..b4fe417145311 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -362,9 +362,9 @@ impl<'a> UnsafeVisitor<'a> { self.resolver.resolve_path_in_value_ns(self.db.upcast(), path, hygiene); if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial { let static_data = self.db.static_data(id); - if static_data.mutable { + if static_data.mutable() { self.on_unsafe_op(node, UnsafetyReason::MutableStatic); - } else if static_data.is_extern && !static_data.has_safe_kw { + } else if static_data.is_extern() && !static_data.has_safe_kw() { self.on_unsafe_op(node, UnsafetyReason::ExternStatic); } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 9df8d9cebbe89..355a4031e9f24 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -1577,7 +1577,7 @@ pub(crate) fn type_for_type_alias_with_diagnostics_query( let mut ctx = TyLoweringContext::new(db, &resolver, &type_alias_data.types_map, t.into()) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) .with_type_param_mode(ParamLoweringMode::Variable); - let inner = if type_alias_data.is_extern { + let inner = if type_alias_data.is_extern() { TyKind::Foreign(crate::to_foreign_def_id(t)).intern(Interner) } else { type_alias_data diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index d887013b6ff30..895cc58147b14 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -401,7 +401,7 @@ pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option { let alias = from_foreign_def_id(id); - Some(if db.type_alias_data(alias).rustc_has_incoherent_inherent_impls { + Some(if db.type_alias_data(alias).rustc_has_incoherent_inherent_impls() { db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::ForeignType(id)) } else { smallvec![alias.module(db.upcast()).krate()] @@ -843,9 +843,11 @@ fn is_inherent_impl_coherent( rustc_has_incoherent_inherent_impls && !items.items.is_empty() && items.items.iter().all(|&(_, assoc)| match assoc { - AssocItemId::FunctionId(it) => db.function_data(it).rustc_allow_incoherent_impl, - AssocItemId::ConstId(it) => db.const_data(it).rustc_allow_incoherent_impl, - AssocItemId::TypeAliasId(it) => db.type_alias_data(it).rustc_allow_incoherent_impl, + AssocItemId::FunctionId(it) => db.function_data(it).rustc_allow_incoherent_impl(), + AssocItemId::ConstId(it) => db.const_data(it).rustc_allow_incoherent_impl(), + AssocItemId::TypeAliasId(it) => { + db.type_alias_data(it).rustc_allow_incoherent_impl() + } }) } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index ee412dd00b3a9..498d707bdafe5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -2756,7 +2756,7 @@ impl Evaluator<'_> { return Ok(*o); }; let static_data = self.db.static_data(st); - let result = if !static_data.is_extern { + let result = if !static_data.is_extern() { let konst = self.db.const_eval_static(st).map_err(|e| { MirEvalError::ConstEvalError(static_data.name.as_str().to_owned(), Box::new(e)) })?; diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs index ec34fd80ad689..673c336cc364b 100644 --- a/src/tools/rust-analyzer/crates/hir/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir/src/display.rs @@ -739,7 +739,7 @@ impl HirDisplay for Static { write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; let data = f.db.static_data(self.id); f.write_str("static ")?; - if data.mutable { + if data.mutable() { f.write_str("mut ")?; } write!(f, "{}: ", data.name.display(f.db.upcast(), f.edition()))?; diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 124cbd2ed1a35..c5ed0446839f2 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -114,6 +114,7 @@ pub use crate::{ pub use { cfg::{CfgAtom, CfgExpr, CfgOptions}, hir_def::{ + Complete, ImportPathConfig, attr::{AttrSourceMap, Attrs, AttrsWithOwner}, data::adt::StructKind, @@ -254,14 +255,17 @@ impl Crate { self, db: &dyn DefDatabase, query: import_map::Query, - ) -> impl Iterator> { + ) -> impl Iterator, Complete)> { let _p = tracing::info_span!("query_external_importables").entered(); - import_map::search_dependencies(db, self.into(), &query).into_iter().map(|item| { - match ItemInNs::from(item) { - ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id), - ItemInNs::Macros(mac_id) => Either::Right(mac_id), - } - }) + import_map::search_dependencies(db, self.into(), &query).into_iter().map( + |(item, do_not_complete)| { + let item = match ItemInNs::from(item) { + ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id), + ItemInNs::Macros(mac_id) => Either::Right(mac_id), + }; + (item, do_not_complete) + }, + ) } pub fn all(db: &dyn HirDatabase) -> Vec { @@ -811,7 +815,7 @@ impl Module { let items = &db.trait_items(trait_.into()).items; let required_items = items.iter().filter(|&(_, assoc)| match *assoc { AssocItemId::FunctionId(it) => !db.function_data(it).has_body(), - AssocItemId::ConstId(id) => !db.const_data(id).has_body, + AssocItemId::ConstId(id) => !db.const_data(id).has_body(), AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(), }); impl_assoc_items_scratch.extend(db.impl_items(impl_def.id).items.iter().cloned()); @@ -2812,7 +2816,7 @@ impl Static { } pub fn is_mut(self, db: &dyn HirDatabase) -> bool { - db.static_data(self.id).mutable + db.static_data(self.id).mutable() } pub fn value(self, db: &dyn HirDatabase) -> Option { @@ -2932,6 +2936,11 @@ impl Trait { .map(|it| it.as_ref().clone().into_boxed_slice()) .unwrap_or_default() } + + /// `#[rust_analyzer::completions(...)]` mode. + pub fn complete(self, db: &dyn HirDatabase) -> Complete { + Complete::extract(true, &self.attrs(db)) + } } impl HasVisibility for Trait { @@ -6359,3 +6368,48 @@ where self(item) } } + +pub fn resolve_absolute_path<'a, I: Iterator + Clone + 'a>( + db: &'a dyn HirDatabase, + mut segments: I, +) -> impl Iterator + use<'a, I> { + segments + .next() + .into_iter() + .flat_map(move |crate_name| { + db.all_crates() + .iter() + .filter(|&krate| { + krate + .extra_data(db) + .display_name + .as_ref() + .is_some_and(|name| *name.crate_name().symbol() == crate_name) + }) + .filter_map(|&krate| { + let segments = segments.clone(); + let mut def_map = db.crate_def_map(krate); + let mut module = &def_map[DefMap::ROOT]; + let mut segments = segments.with_position().peekable(); + while let Some((_, segment)) = segments.next_if(|&(position, _)| { + !matches!(position, itertools::Position::Last | itertools::Position::Only) + }) { + let res = module + .scope + .get(&Name::new_symbol_root(segment)) + .take_types() + .and_then(|res| match res { + ModuleDefId::ModuleId(it) => Some(it), + _ => None, + })?; + def_map = res.def_map(db.upcast()); + module = &def_map[res.local_id]; + } + let (_, item_name) = segments.next()?; + let res = module.scope.get(&Name::new_symbol_root(item_name)); + Some(res.iter_items().map(|(item, _)| item.into())) + }) + .collect::>() + }) + .flatten() +} diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index ae70f6f0ecc05..679f775e1bd94 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -2,7 +2,7 @@ use either::Either; use hir_def::{ - AdtId, AssocItemId, DefWithBodyId, ExternCrateId, HasModule, ImplId, Lookup, MacroId, + AdtId, AssocItemId, Complete, DefWithBodyId, ExternCrateId, HasModule, ImplId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, db::DefDatabase, item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob}, @@ -34,6 +34,7 @@ pub struct FileSymbol { /// Whether this symbol is a doc alias for the original symbol. pub is_alias: bool, pub is_assoc: bool, + pub do_not_complete: Complete, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -122,35 +123,43 @@ impl<'a> SymbolCollector<'a> { match def { ModuleDefId::ModuleId(id) => this.push_module(id, name), ModuleDefId::FunctionId(id) => { - this.push_decl(id, name, false); + this.push_decl(id, name, false, None); this.collect_from_body(id, Some(name.clone())); } - ModuleDefId::AdtId(AdtId::StructId(id)) => this.push_decl(id, name, false), - ModuleDefId::AdtId(AdtId::EnumId(id)) => this.push_decl(id, name, false), - ModuleDefId::AdtId(AdtId::UnionId(id)) => this.push_decl(id, name, false), + ModuleDefId::AdtId(AdtId::StructId(id)) => { + this.push_decl(id, name, false, None); + } + ModuleDefId::AdtId(AdtId::EnumId(id)) => { + this.push_decl(id, name, false, None); + } + ModuleDefId::AdtId(AdtId::UnionId(id)) => { + this.push_decl(id, name, false, None); + } ModuleDefId::ConstId(id) => { - this.push_decl(id, name, false); + this.push_decl(id, name, false, None); this.collect_from_body(id, Some(name.clone())); } ModuleDefId::StaticId(id) => { - this.push_decl(id, name, false); + this.push_decl(id, name, false, None); this.collect_from_body(id, Some(name.clone())); } ModuleDefId::TraitId(id) => { - this.push_decl(id, name, false); - this.collect_from_trait(id); + let trait_do_not_complete = this.push_decl(id, name, false, None); + this.collect_from_trait(id, trait_do_not_complete); } ModuleDefId::TraitAliasId(id) => { - this.push_decl(id, name, false); + this.push_decl(id, name, false, None); } ModuleDefId::TypeAliasId(id) => { - this.push_decl(id, name, false); + this.push_decl(id, name, false, None); + } + ModuleDefId::MacroId(id) => { + match id { + MacroId::Macro2Id(id) => this.push_decl(id, name, false, None), + MacroId::MacroRulesId(id) => this.push_decl(id, name, false, None), + MacroId::ProcMacroId(id) => this.push_decl(id, name, false, None), + }; } - ModuleDefId::MacroId(id) => match id { - MacroId::Macro2Id(id) => this.push_decl(id, name, false), - MacroId::MacroRulesId(id) => this.push_decl(id, name, false), - MacroId::ProcMacroId(id) => this.push_decl(id, name, false), - }, // Don't index these. ModuleDefId::BuiltinType(_) => {} ModuleDefId::EnumVariantId(_) => {} @@ -194,6 +203,7 @@ impl<'a> SymbolCollector<'a> { loc: dec_loc, is_alias: false, is_assoc: false, + do_not_complete: Complete::Yes, }); }; @@ -223,6 +233,7 @@ impl<'a> SymbolCollector<'a> { loc: dec_loc, is_alias: false, is_assoc: false, + do_not_complete: Complete::Yes, }); }; @@ -281,10 +292,10 @@ impl<'a> SymbolCollector<'a> { for &id in id { if id.module(self.db.upcast()) == module_id { match id { - MacroId::Macro2Id(id) => self.push_decl(id, name, false), - MacroId::MacroRulesId(id) => self.push_decl(id, name, false), - MacroId::ProcMacroId(id) => self.push_decl(id, name, false), - } + MacroId::Macro2Id(id) => self.push_decl(id, name, false, None), + MacroId::MacroRulesId(id) => self.push_decl(id, name, false, None), + MacroId::ProcMacroId(id) => self.push_decl(id, name, false, None), + }; } } } @@ -314,16 +325,16 @@ impl<'a> SymbolCollector<'a> { ); self.with_container_name(impl_name, |s| { for &(ref name, assoc_item_id) in &self.db.impl_items(impl_id).items { - s.push_assoc_item(assoc_item_id, name) + s.push_assoc_item(assoc_item_id, name, None) } }) } - fn collect_from_trait(&mut self, trait_id: TraitId) { + fn collect_from_trait(&mut self, trait_id: TraitId, trait_do_not_complete: Complete) { let trait_data = self.db.trait_data(trait_id); self.with_container_name(Some(trait_data.name.as_str().into()), |s| { for &(ref name, assoc_item_id) in &self.db.trait_items(trait_id).items { - s.push_assoc_item(assoc_item_id, name); + s.push_assoc_item(assoc_item_id, name, Some(trait_do_not_complete)); } }); } @@ -338,15 +349,26 @@ impl<'a> SymbolCollector<'a> { } } - fn push_assoc_item(&mut self, assoc_item_id: AssocItemId, name: &Name) { + fn push_assoc_item( + &mut self, + assoc_item_id: AssocItemId, + name: &Name, + trait_do_not_complete: Option, + ) { match assoc_item_id { - AssocItemId::FunctionId(id) => self.push_decl(id, name, true), - AssocItemId::ConstId(id) => self.push_decl(id, name, true), - AssocItemId::TypeAliasId(id) => self.push_decl(id, name, true), - } + AssocItemId::FunctionId(id) => self.push_decl(id, name, true, trait_do_not_complete), + AssocItemId::ConstId(id) => self.push_decl(id, name, true, trait_do_not_complete), + AssocItemId::TypeAliasId(id) => self.push_decl(id, name, true, trait_do_not_complete), + }; } - fn push_decl(&mut self, id: L, name: &Name, is_assoc: bool) + fn push_decl( + &mut self, + id: L, + name: &Name, + is_assoc: bool, + trait_do_not_complete: Option, + ) -> Complete where L: Lookup + Into, ::Data: HasSource, @@ -354,7 +376,7 @@ impl<'a> SymbolCollector<'a> { { let loc = id.lookup(self.db.upcast()); let source = loc.source(self.db.upcast()); - let Some(name_node) = source.value.name() else { return }; + let Some(name_node) = source.value.name() else { return Complete::Yes }; let def = ModuleDef::from(id.into()); let dec_loc = DeclarationLocation { hir_file_id: source.file_id, @@ -362,7 +384,14 @@ impl<'a> SymbolCollector<'a> { name_ptr: AstPtr::new(&name_node).wrap_left(), }; + let mut do_not_complete = Complete::Yes; + if let Some(attrs) = def.attrs(self.db) { + do_not_complete = Complete::extract(matches!(def, ModuleDef::Trait(_)), &attrs); + if let Some(trait_do_not_complete) = trait_do_not_complete { + do_not_complete = Complete::for_trait_item(trait_do_not_complete, do_not_complete); + } + for alias in attrs.doc_aliases() { self.symbols.insert(FileSymbol { name: alias.clone(), @@ -371,6 +400,7 @@ impl<'a> SymbolCollector<'a> { container_name: self.current_container_name.clone(), is_alias: true, is_assoc, + do_not_complete, }); } } @@ -382,7 +412,10 @@ impl<'a> SymbolCollector<'a> { loc: dec_loc, is_alias: false, is_assoc, + do_not_complete, }); + + do_not_complete } fn push_module(&mut self, module_id: ModuleId, name: &Name) { @@ -399,7 +432,10 @@ impl<'a> SymbolCollector<'a> { let def = ModuleDef::Module(module_id.into()); + let mut do_not_complete = Complete::Yes; if let Some(attrs) = def.attrs(self.db) { + do_not_complete = Complete::extract(matches!(def, ModuleDef::Trait(_)), &attrs); + for alias in attrs.doc_aliases() { self.symbols.insert(FileSymbol { name: alias.clone(), @@ -408,6 +444,7 @@ impl<'a> SymbolCollector<'a> { container_name: self.current_container_name.clone(), is_alias: true, is_assoc: false, + do_not_complete, }); } } @@ -419,6 +456,7 @@ impl<'a> SymbolCollector<'a> { loc: dec_loc, is_alias: false, is_assoc: false, + do_not_complete, }); } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index 691ae931f8ade..feeea8872a44a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -78,7 +78,7 @@ pub(crate) fn replace_derive_with_manual_impl( NameToImport::exact_case_sensitive(path.segments().last()?.to_string()), items_locator::AssocSearchMode::Exclude, ) - .filter_map(|item| match item.into_module_def() { + .filter_map(|(item, _)| match item.into_module_def() { ModuleDef::Trait(trait_) => Some(trait_), _ => None, }) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs index dea983b6ea812..4f21136d214ee 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs @@ -2,7 +2,7 @@ use std::ops::ControlFlow; -use hir::{HasContainer, ItemContainer, MethodCandidateCallback, Name}; +use hir::{Complete, HasContainer, ItemContainer, MethodCandidateCallback, Name}; use ide_db::FxHashSet; use syntax::SmolStr; @@ -259,7 +259,9 @@ fn complete_methods( // This needs to come before the `seen_methods` test, so that if we see the same method twice, // once as inherent and once not, we will include it. if let ItemContainer::Trait(trait_) = func.container(self.ctx.db) { - if self.ctx.exclude_traits.contains(&trait_) { + if self.ctx.exclude_traits.contains(&trait_) + || trait_.complete(self.ctx.db) == Complete::IgnoreMethods + { return ControlFlow::Continue(()); } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index 7219a5f1b011a..0494d4223d184 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -2,7 +2,7 @@ use std::ops::ControlFlow; -use hir::{Name, PathCandidateCallback, ScopeDef, sym}; +use hir::{Complete, Name, PathCandidateCallback, ScopeDef, sym}; use ide_db::FxHashSet; use syntax::ast; @@ -33,10 +33,10 @@ where fn on_trait_item(&mut self, item: hir::AssocItem) -> ControlFlow<()> { // The excluded check needs to come before the `seen` test, so that if we see the same method twice, // once as inherent and once not, we will include it. - if item - .container_trait(self.ctx.db) - .is_none_or(|trait_| !self.ctx.exclude_traits.contains(&trait_)) - && self.seen.insert(item) + if item.container_trait(self.ctx.db).is_none_or(|trait_| { + !self.ctx.exclude_traits.contains(&trait_) + && trait_.complete(self.ctx.db) != Complete::IgnoreMethods + }) && self.seen.insert(item) { (self.add_assoc_item)(self.acc, item); } @@ -104,7 +104,9 @@ pub(crate) fn complete_expr_path( .iter() .copied() .map(hir::Trait::from) - .filter(|it| !ctx.exclude_traits.contains(it)) + .filter(|it| { + !ctx.exclude_traits.contains(it) && it.complete(ctx.db) != Complete::IgnoreMethods + }) .flat_map(|it| it.items(ctx.sema.db)) .for_each(|item| add_assoc_item(acc, item)), Qualified::TypeAnchor { trait_: Some(trait_), .. } => { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs index b3ba076489307..a747561380906 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs @@ -268,19 +268,7 @@ fn import_on_the_fly( && !ctx.is_item_hidden(original_item) && ctx.check_stability(original_item.attrs(ctx.db).as_deref()) }) - .filter(|import| { - let def = import.item_to_import.into_module_def(); - if let Some(&kind) = ctx.exclude_flyimport.get(&def) { - if kind == AutoImportExclusionType::Always { - return false; - } - let method_imported = import.item_to_import != import.original_item; - if method_imported { - return false; - } - } - true - }) + .filter(|import| filter_excluded_flyimport(ctx, import)) .sorted_by(|a, b| { let key = |import_path| { ( @@ -366,24 +354,7 @@ fn import_on_the_fly_method( !ctx.is_item_hidden(&import.item_to_import) && !ctx.is_item_hidden(&import.original_item) }) - .filter(|import| { - let def = import.item_to_import.into_module_def(); - if let Some(&kind) = ctx.exclude_flyimport.get(&def) { - if kind == AutoImportExclusionType::Always { - return false; - } - let method_imported = import.item_to_import != import.original_item; - if method_imported { - return false; - } - } - - if let ModuleDef::Trait(_) = import.item_to_import.into_module_def() { - !ctx.exclude_flyimport.contains_key(&def) - } else { - true - } - }) + .filter(|import| filter_excluded_flyimport(ctx, import)) .sorted_by(|a, b| { let key = |import_path| { ( @@ -401,6 +372,28 @@ fn import_on_the_fly_method( Some(()) } +fn filter_excluded_flyimport(ctx: &CompletionContext<'_>, import: &LocatedImport) -> bool { + let def = import.item_to_import.into_module_def(); + let is_exclude_flyimport = ctx.exclude_flyimport.get(&def).copied(); + + if matches!(is_exclude_flyimport, Some(AutoImportExclusionType::Always)) + || !import.complete_in_flyimport.0 + { + return false; + } + let method_imported = import.item_to_import != import.original_item; + if method_imported + && (is_exclude_flyimport.is_some() + || ctx.exclude_flyimport.contains_key(&import.original_item.into_module_def())) + { + // If this is a method, exclude it either if it was excluded itself (which may not be caught above, + // because `item_to_import` is the trait), or if its trait was excluded. We don't need to check + // the attributes here, since they pass from trait to methods on import map construction. + return false; + } + true +} + fn import_name(ctx: &CompletionContext<'_>) -> String { let token_kind = ctx.token.kind(); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index 304379603199d..fd25ee05e0399 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -8,8 +8,8 @@ use std::{iter, ops::ControlFlow}; use base_db::{RootQueryDb as _, salsa::AsDynDatabase}; use hir::{ - DisplayTarget, HasAttrs, Local, ModPath, ModuleDef, ModuleSource, Name, PathResolution, - ScopeDef, Semantics, SemanticsScope, Symbol, Type, TypeInfo, + DisplayTarget, HasAttrs, Local, ModuleDef, ModuleSource, Name, PathResolution, ScopeDef, + Semantics, SemanticsScope, Symbol, Type, TypeInfo, }; use ide_db::{ FilePosition, FxHashMap, FxHashSet, RootDatabase, famous_defs::FamousDefs, @@ -796,15 +796,12 @@ impl<'a> CompletionContext<'a> { .exclude_traits .iter() .filter_map(|path| { - scope - .resolve_mod_path(&ModPath::from_segments( - hir::PathKind::Plain, - path.split("::").map(Symbol::intern).map(Name::new_symbol_root), - )) - .find_map(|it| match it { + hir::resolve_absolute_path(db, path.split("::").map(Symbol::intern)).find_map( + |it| match it { hir::ItemInNs::Types(ModuleDef::Trait(t)) => Some(t), _ => None, - }) + }, + ) }) .collect(); @@ -812,11 +809,7 @@ impl<'a> CompletionContext<'a> { .exclude_flyimport .iter() .flat_map(|(path, kind)| { - scope - .resolve_mod_path(&ModPath::from_segments( - hir::PathKind::Plain, - path.split("::").map(Symbol::intern).map(Name::new_symbol_root), - )) + hir::resolve_absolute_path(db, path.split("::").map(Symbol::intern)) .map(|it| (it.into_module_def(), *kind)) }) .collect(); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 82c12662c433d..b0adbad74ed12 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -334,7 +334,7 @@ pub(crate) fn render_expr( continue; }; - item.add_import(LocatedImport::new(path, trait_item, trait_item)); + item.add_import(LocatedImport::new_no_completion(path, trait_item, trait_item)); } Some(item) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs index 07f33a826e4c7..9dc0c0234dc56 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs @@ -174,7 +174,7 @@ fn import_edits(ctx: &CompletionContext<'_>, requires: &[ModPath]) -> Option 1).then(|| LocatedImport::new(path.clone(), item, item))) + Some((path.len() > 1).then(|| LocatedImport::new_no_completion(path.clone(), item, item))) }; let mut res = Vec::with_capacity(requires.len()); for import in requires { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index 22d42ba750ed1..98da2cbf0780f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -1555,7 +1555,10 @@ fn main() { #[test] fn excluded_trait_method_is_excluded() { check_with_config( - CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG }, + CompletionConfig { + exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()], + ..TEST_CONFIG + }, r#" trait ExcludedTrait { fn foo(&self) {} @@ -1575,23 +1578,20 @@ fn foo() { } "#, expect![[r#" - me bar() (as ExcludedTrait) fn(&self) - me baz() (as ExcludedTrait) fn(&self) - me foo() (as ExcludedTrait) fn(&self) - me inherent() fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me inherent() fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -1599,7 +1599,10 @@ fn foo() { #[test] fn excluded_trait_not_excluded_when_inherent() { check_with_config( - CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG }, + CompletionConfig { + exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()], + ..TEST_CONFIG + }, r#" trait ExcludedTrait { fn foo(&self) {} @@ -1633,7 +1636,10 @@ fn foo(v: &dyn ExcludedTrait) { "#]], ); check_with_config( - CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG }, + CompletionConfig { + exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()], + ..TEST_CONFIG + }, r#" trait ExcludedTrait { fn foo(&self) {} @@ -1667,7 +1673,10 @@ fn foo(v: impl ExcludedTrait) { "#]], ); check_with_config( - CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG }, + CompletionConfig { + exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()], + ..TEST_CONFIG + }, r#" trait ExcludedTrait { fn foo(&self) {} @@ -1706,7 +1715,7 @@ fn foo(v: T) { fn excluded_trait_method_is_excluded_from_flyimport() { check_with_config( CompletionConfig { - exclude_traits: &["test::module2::ExcludedTrait".to_owned()], + exclude_traits: &["ra_test_fixture::module2::ExcludedTrait".to_owned()], ..TEST_CONFIG }, r#" @@ -1730,23 +1739,20 @@ fn foo() { } "#, expect![[r#" - me bar() (use module2::ExcludedTrait) fn(&self) - me baz() (use module2::ExcludedTrait) fn(&self) - me foo() (use module2::ExcludedTrait) fn(&self) - me inherent() fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me inherent() fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -1756,7 +1762,7 @@ fn flyimport_excluded_trait_method_is_excluded_from_flyimport() { check_with_config( CompletionConfig { exclude_flyimport: vec![( - "test::module2::ExcludedTrait".to_owned(), + "ra_test_fixture::module2::ExcludedTrait".to_owned(), AutoImportExclusionType::Methods, )], ..TEST_CONFIG @@ -1782,23 +1788,20 @@ fn foo() { } "#, expect![[r#" - me bar() (use module2::ExcludedTrait) fn(&self) - me baz() (use module2::ExcludedTrait) fn(&self) - me foo() (use module2::ExcludedTrait) fn(&self) - me inherent() fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me inherent() fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -1806,7 +1809,10 @@ fn foo() { #[test] fn excluded_trait_method_is_excluded_from_path_completion() { check_with_config( - CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG }, + CompletionConfig { + exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()], + ..TEST_CONFIG + }, r#" pub trait ExcludedTrait { fn foo(&self) {} @@ -1826,10 +1832,7 @@ fn foo() { } "#, expect![[r#" - me bar(…) (as ExcludedTrait) fn(&self) - me baz(…) (as ExcludedTrait) fn(&self) - me foo(…) (as ExcludedTrait) fn(&self) - me inherent(…) fn(&self) + me inherent(…) fn(&self) "#]], ); } @@ -1837,7 +1840,10 @@ fn foo() { #[test] fn excluded_trait_method_is_not_excluded_when_trait_is_specified() { check_with_config( - CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG }, + CompletionConfig { + exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()], + ..TEST_CONFIG + }, r#" pub trait ExcludedTrait { fn foo(&self) {} @@ -1863,7 +1869,10 @@ fn foo() { "#]], ); check_with_config( - CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG }, + CompletionConfig { + exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()], + ..TEST_CONFIG + }, r#" pub trait ExcludedTrait { fn foo(&self) {} @@ -1893,7 +1902,10 @@ fn foo() { #[test] fn excluded_trait_not_excluded_when_inherent_path() { check_with_config( - CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG }, + CompletionConfig { + exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()], + ..TEST_CONFIG + }, r#" trait ExcludedTrait { fn foo(&self) {} @@ -1914,7 +1926,10 @@ fn foo() { "#]], ); check_with_config( - CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG }, + CompletionConfig { + exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()], + ..TEST_CONFIG + }, r#" trait ExcludedTrait { fn foo(&self) {} diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index 8bba44c12bf60..27c91bc7c4558 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -1810,9 +1810,10 @@ fn function() { #[test] fn excluded_trait_item_included_when_exact_match() { + // FIXME: This does not work, we need to change the code. check_with_config( CompletionConfig { - exclude_traits: &["test::module2::ExcludedTrait".to_owned()], + exclude_traits: &["ra_test_fixture::module2::ExcludedTrait".to_owned()], ..TEST_CONFIG }, r#" @@ -1828,10 +1829,122 @@ mod module2 { fn foo() { true.foo$0 +} + "#, + expect![""], + ); +} + +#[test] +fn excluded_via_attr() { + check( + r#" +mod module2 { + #[rust_analyzer::completions(ignore_flyimport)] + pub trait ExcludedTrait { + fn foo(&self) {} + fn bar(&self) {} + fn baz(&self) {} + } + + impl ExcludedTrait for T {} +} + +fn foo() { + true.$0 +} + "#, + expect![""], + ); + check( + r#" +mod module2 { + #[rust_analyzer::completions(ignore_flyimport_methods)] + pub trait ExcludedTrait { + fn foo(&self) {} + fn bar(&self) {} + fn baz(&self) {} + } + + impl ExcludedTrait for T {} +} + +fn foo() { + true.$0 +} + "#, + expect![""], + ); + check( + r#" +mod module2 { + #[rust_analyzer::completions(ignore_methods)] + pub trait ExcludedTrait { + fn foo(&self) {} + fn bar(&self) {} + fn baz(&self) {} + } + + impl ExcludedTrait for T {} +} + +fn foo() { + true.$0 +} + "#, + expect![""], + ); + check( + r#" +mod module2 { + #[rust_analyzer::completions(ignore_flyimport)] + pub trait ExcludedTrait { + fn foo(&self) {} + fn bar(&self) {} + fn baz(&self) {} + } + + impl ExcludedTrait for T {} +} + +fn foo() { + ExcludedTrait$0 +} + "#, + expect![""], + ); + check( + r#" +mod module2 { + #[rust_analyzer::completions(ignore_methods)] + pub trait ExcludedTrait { + fn foo(&self) {} + fn bar(&self) {} + fn baz(&self) {} + } + + impl ExcludedTrait for T {} +} + +fn foo() { + ExcludedTrait$0 } "#, expect![[r#" - me foo() (use module2::ExcludedTrait) fn(&self) + tt ExcludedTrait (use module2::ExcludedTrait) "#]], ); + check( + r#" +mod module2 { + #[rust_analyzer::completions(ignore_flyimport)] + pub struct Foo {} +} + +fn foo() { + Foo$0 +} + "#, + expect![""], + ); } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index 650c957ca4581..ac592dfe93cf9 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -3,8 +3,8 @@ use std::ops::ControlFlow; use hir::{ - AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ImportPathConfig, ItemInNs, - ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics, + AsAssocItem, AssocItem, AssocItemContainer, Complete, Crate, HasCrate, ImportPathConfig, + ItemInNs, ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics, SemanticsScope, Trait, TyFingerprint, Type, db::HirDatabase, }; use itertools::Itertools; @@ -183,6 +183,9 @@ impl ImportAssets { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct CompleteInFlyimport(pub bool); + /// An import (not necessary the only one) that corresponds a certain given [`PathImportCandidate`]. /// (the structure is not entirely correct, since there can be situations requiring two imports, see FIXME below for the details) #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -198,11 +201,31 @@ pub struct LocatedImport { /// the original item is the associated constant, but the import has to be a trait that /// defines this constant. pub original_item: ItemInNs, + /// The value of `#[rust_analyzer::completions(...)]`, if existing. + pub complete_in_flyimport: CompleteInFlyimport, } impl LocatedImport { - pub fn new(import_path: ModPath, item_to_import: ItemInNs, original_item: ItemInNs) -> Self { - Self { import_path, item_to_import, original_item } + pub fn new( + import_path: ModPath, + item_to_import: ItemInNs, + original_item: ItemInNs, + complete_in_flyimport: CompleteInFlyimport, + ) -> Self { + Self { import_path, item_to_import, original_item, complete_in_flyimport } + } + + pub fn new_no_completion( + import_path: ModPath, + item_to_import: ItemInNs, + original_item: ItemInNs, + ) -> Self { + Self { + import_path, + item_to_import, + original_item, + complete_in_flyimport: CompleteInFlyimport(true), + } } } @@ -351,12 +374,17 @@ fn path_applicable_imports( // see also an ignored test under FIXME comment in the qualify_path.rs module AssocSearchMode::Exclude, ) - .filter_map(|item| { + .filter_map(|(item, do_not_complete)| { if !scope_filter(item) { return None; } let mod_path = mod_path(item)?; - Some(LocatedImport::new(mod_path, item, item)) + Some(LocatedImport::new( + mod_path, + item, + item, + CompleteInFlyimport(do_not_complete != Complete::IgnoreFlyimport), + )) }) .take(DEFAULT_QUERY_SEARCH_LIMIT) .collect() @@ -371,7 +399,7 @@ fn path_applicable_imports( NameToImport::Exact(first_qsegment.as_str().to_owned(), true), AssocSearchMode::Exclude, ) - .filter_map(|item| { + .filter_map(|(item, do_not_complete)| { // we found imports for `first_qsegment`, now we need to filter these imports by whether // they result in resolving the rest of the path successfully validate_resolvable( @@ -382,6 +410,7 @@ fn path_applicable_imports( &path_candidate.name, item, qualifier_rest, + CompleteInFlyimport(do_not_complete != Complete::IgnoreFlyimport), ) }) .take(DEFAULT_QUERY_SEARCH_LIMIT) @@ -399,6 +428,7 @@ fn validate_resolvable( candidate: &NameToImport, resolved_qualifier: ItemInNs, unresolved_qualifier: &[Name], + complete_in_flyimport: CompleteInFlyimport, ) -> Option { let _p = tracing::info_span!("ImportAssets::import_for_item").entered(); @@ -434,7 +464,14 @@ fn validate_resolvable( false => ControlFlow::Continue(()), }, ) - .map(|item| LocatedImport::new(import_path_candidate, resolved_qualifier, item)); + .map(|item| { + LocatedImport::new( + import_path_candidate, + resolved_qualifier, + item, + complete_in_flyimport, + ) + }); } // FIXME ModuleDef::Trait(_) => return None, @@ -472,6 +509,7 @@ fn validate_resolvable( import_path_candidate.clone(), resolved_qualifier, assoc_to_item(assoc), + complete_in_flyimport, )) }) } @@ -510,15 +548,15 @@ fn trait_applicable_items( let env_traits = trait_candidate.receiver_ty.env_traits(db); let related_traits = inherent_traits.chain(env_traits).collect::>(); - let mut required_assoc_items = FxHashSet::default(); + let mut required_assoc_items = FxHashMap::default(); let mut trait_candidates: FxHashSet<_> = items_locator::items_with_name( db, current_crate, trait_candidate.assoc_item_name.clone(), AssocSearchMode::AssocItemsOnly, ) - .filter_map(|input| item_as_assoc(db, input)) - .filter_map(|assoc| { + .filter_map(|(input, do_not_complete)| Some((item_as_assoc(db, input)?, do_not_complete))) + .filter_map(|(assoc, do_not_complete)| { if !trait_assoc_item && matches!(assoc, AssocItem::Const(_) | AssocItem::TypeAlias(_)) { return None; } @@ -527,7 +565,8 @@ fn trait_applicable_items( if related_traits.contains(&assoc_item_trait) { return None; } - required_assoc_items.insert(assoc); + required_assoc_items + .insert(assoc, CompleteInFlyimport(do_not_complete != Complete::IgnoreFlyimport)); Some(assoc_item_trait.into()) }) .collect(); @@ -599,7 +638,7 @@ fn trait_applicable_items( None, None, |assoc| { - if required_assoc_items.contains(&assoc) { + if let Some(&complete_in_flyimport) = required_assoc_items.get(&assoc) { let located_trait = assoc.container_trait(db).filter(|&it| scope_filter(it))?; let trait_item = ItemInNs::from(ModuleDef::from(located_trait)); let import_path = trait_import_paths @@ -610,6 +649,7 @@ fn trait_applicable_items( import_path, trait_item, assoc_to_item(assoc), + complete_in_flyimport, )); } None::<()> @@ -624,7 +664,7 @@ fn trait_applicable_items( None, |function| { let assoc = function.as_assoc_item(db)?; - if required_assoc_items.contains(&assoc) { + if let Some(&complete_in_flyimport) = required_assoc_items.get(&assoc) { let located_trait = assoc.container_trait(db).filter(|&it| scope_filter(it))?; let trait_item = ItemInNs::from(ModuleDef::from(located_trait)); let import_path = trait_import_paths @@ -635,6 +675,7 @@ fn trait_applicable_items( import_path, trait_item, assoc_to_item(assoc), + complete_in_flyimport, )); } None::<()> diff --git a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs index 7a543d64e27f4..e9385253250ad 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs @@ -5,7 +5,7 @@ use std::ops::ControlFlow; use either::Either; -use hir::{Crate, ItemInNs, Module, import_map}; +use hir::{Complete, Crate, ItemInNs, Module, import_map}; use crate::{ RootDatabase, @@ -25,7 +25,7 @@ pub fn items_with_name( krate: Crate, name: NameToImport, assoc_item_search: AssocSearchMode, -) -> impl Iterator { +) -> impl Iterator { let _p = tracing::info_span!("items_with_name", name = name.text(), assoc_item_search = ?assoc_item_search, crate = ?krate.display_name(db).map(|name| name.to_string())) .entered(); @@ -123,26 +123,29 @@ fn find_items( krate: Crate, local_query: symbol_index::Query, external_query: import_map::Query, -) -> impl Iterator { +) -> impl Iterator { let _p = tracing::info_span!("find_items").entered(); // NOTE: `external_query` includes `assoc_item_search`, so we don't need to // filter on our own. - let external_importables = - krate.query_external_importables(db, external_query).map(|external_importable| { - match external_importable { + let external_importables = krate.query_external_importables(db, external_query).map( + |(external_importable, do_not_complete)| { + let external_importable = match external_importable { Either::Left(module_def) => ItemInNs::from(module_def), Either::Right(macro_def) => ItemInNs::from(macro_def), - } - }); + }; + (external_importable, do_not_complete) + }, + ); // Query the local crate using the symbol index. let mut local_results = Vec::new(); local_query.search(&symbol_index::crate_symbols(db, krate), |local_candidate| { - local_results.push(match local_candidate.def { + let def = match local_candidate.def { hir::ModuleDef::Macro(macro_def) => ItemInNs::Macros(macro_def), def => ItemInNs::from(def), - }); + }; + local_results.push((def, local_candidate.do_not_complete)); ControlFlow::<()>::Continue(()) }); local_results.into_iter().chain(external_importables) diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt index ea50745d67934..8e342ec553c2d 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt @@ -42,6 +42,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "Struct", @@ -75,6 +76,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "mul1", @@ -108,6 +110,7 @@ container_name: None, is_alias: true, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "mul2", @@ -141,6 +144,7 @@ container_name: None, is_alias: true, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "s1", @@ -174,6 +178,7 @@ container_name: None, is_alias: true, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "s1", @@ -207,6 +212,7 @@ container_name: None, is_alias: true, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "s2", @@ -240,6 +246,7 @@ container_name: None, is_alias: true, is_assoc: false, + do_not_complete: Yes, }, ], ), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt index d2d24262f098d..6de25c000e520 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt @@ -40,6 +40,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "CONST", @@ -71,6 +72,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "CONST_WITH_INNER", @@ -102,6 +104,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "Enum", @@ -135,6 +138,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "ItemLikeMacro", @@ -168,6 +172,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "Macro", @@ -201,6 +206,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "STATIC", @@ -232,6 +238,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "Struct", @@ -265,6 +272,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "StructFromMacro", @@ -295,6 +303,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "StructInFn", @@ -330,6 +339,7 @@ ), is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "StructInNamedConst", @@ -365,6 +375,7 @@ ), is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "StructInUnnamedConst", @@ -398,6 +409,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "StructT", @@ -431,6 +443,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "Trait", @@ -462,6 +475,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "Trait", @@ -495,6 +509,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "Union", @@ -528,6 +543,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "a_mod", @@ -563,6 +579,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "b_mod", @@ -598,6 +615,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "define_struct", @@ -631,6 +649,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "generic_impl_fn", @@ -664,6 +683,7 @@ ), is_alias: false, is_assoc: true, + do_not_complete: Yes, }, FileSymbol { name: "impl_fn", @@ -697,6 +717,7 @@ ), is_alias: false, is_assoc: true, + do_not_complete: Yes, }, FileSymbol { name: "macro_rules_macro", @@ -730,6 +751,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "main", @@ -761,6 +783,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "really_define_struct", @@ -794,6 +817,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "trait_fn", @@ -827,6 +851,7 @@ ), is_alias: false, is_assoc: true, + do_not_complete: Yes, }, ], ), @@ -873,6 +898,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, ], ), @@ -917,6 +943,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "IsThisJustATrait", @@ -950,6 +977,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "StructInModB", @@ -983,6 +1011,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "SuperItemLikeMacro", @@ -1016,6 +1045,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, FileSymbol { name: "ThisStruct", @@ -1049,6 +1079,7 @@ container_name: None, is_alias: false, is_assoc: false, + do_not_complete: Yes, }, ], ), diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index cc9b3ef457366..4841f48659156 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -521,4 +521,8 @@ define_symbols! { win64, array, boxed_slice, + completions, + ignore_flyimport, + ignore_flyimport_methods, + ignore_methods, } From 9df5177287184465bd9957c6f7d582eaf16a6b2f Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 26 Mar 2025 11:20:36 +0100 Subject: [PATCH 0333/2248] Convert the `collapsible_if` early lint to a late one --- clippy_lints/src/collapsible_if.rs | 86 ++++++++++++++++-------------- clippy_lints/src/lib.rs | 2 +- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index b100e2408de3d..8728f7f2eb592 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -1,12 +1,10 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::source::{ - HasSession, IntoSpan as _, SpanRangeExt, snippet, snippet_block, snippet_block_with_applicability, -}; -use clippy_utils::span_contains_comment; -use rustc_ast::ast; +use clippy_utils::source::{IntoSpan as _, SpanRangeExt, snippet, snippet_block, snippet_block_with_applicability}; +use rustc_ast::BinOpKind; use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_hir::{Block, Expr, ExprKind, StmtKind}; +use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -89,17 +87,16 @@ impl CollapsibleIf { } } - fn check_collapsible_else_if(cx: &EarlyContext<'_>, then_span: Span, else_: &ast::Expr) { - if let ast::ExprKind::Block(ref block, _) = else_.kind - && !block_starts_with_comment(cx, block) - && let Some(else_) = expr_block(block) - && else_.attrs.is_empty() + fn check_collapsible_else_if(cx: &LateContext<'_>, then_span: Span, else_block: &Block<'_>) { + if !block_starts_with_comment(cx, else_block) + && let Some(else_) = expr_block(else_block) + && cx.tcx.hir_attrs(else_.hir_id).is_empty() && !else_.span.from_expansion() - && let ast::ExprKind::If(..) = else_.kind + && let ExprKind::If(..) = else_.kind { // Prevent "elseif" // Check that the "else" is followed by whitespace - let up_to_else = then_span.between(block.span); + let up_to_else = then_span.between(else_block.span); let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() { !c.is_whitespace() } else { @@ -110,29 +107,28 @@ impl CollapsibleIf { span_lint_and_sugg( cx, COLLAPSIBLE_ELSE_IF, - block.span, + else_block.span, "this `else { if .. }` block can be collapsed", "collapse nested if block", format!( "{}{}", if requires_space { " " } else { "" }, - snippet_block_with_applicability(cx, else_.span, "..", Some(block.span), &mut applicability) + snippet_block_with_applicability(cx, else_.span, "..", Some(else_block.span), &mut applicability) ), applicability, ); } } - fn check_collapsible_if_if(&self, cx: &EarlyContext<'_>, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) { + fn check_collapsible_if_if(&self, cx: &LateContext<'_>, expr: &Expr<'_>, check: &Expr<'_>, then: &Block<'_>) { if let Some(inner) = expr_block(then) - && inner.attrs.is_empty() - && let ast::ExprKind::If(check_inner, _, None) = &inner.kind + && cx.tcx.hir_attrs(inner.hir_id).is_empty() + && let ExprKind::If(check_inner, _, None) = &inner.kind // Prevent triggering on `if c { if let a = b { .. } }`. - && !matches!(check_inner.kind, ast::ExprKind::Let(..)) + && !matches!(check_inner.kind, ExprKind::Let(..)) && let ctxt = expr.span.ctxt() && inner.span.ctxt() == ctxt - && let contains_comment = span_contains_comment(cx.sess().source_map(), check.span.to(check_inner.span)) - && (!contains_comment || self.lint_commented_code) + && (self.lint_commented_code || !block_starts_with_comment(cx, then)) { span_lint_and_then( cx, @@ -168,44 +164,54 @@ impl CollapsibleIf { impl_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]); -impl EarlyLintPass for CollapsibleIf { - fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { - if let ast::ExprKind::If(cond, then, else_) = &expr.kind +impl LateLintPass<'_> for CollapsibleIf { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::If(cond, then, else_) = &expr.kind && !expr.span.from_expansion() { - if let Some(else_) = else_ { + if let Some(else_) = else_ + && let ExprKind::Block(else_, None) = else_.kind + { Self::check_collapsible_else_if(cx, then.span, else_); - } else if !matches!(cond.kind, ast::ExprKind::Let(..)) { + } else if else_.is_none() + && !matches!(cond.kind, ExprKind::Let(..)) + && let ExprKind::Block(then, None) = then.kind + { // Prevent triggering on `if c { if let a = b { .. } }`. - self.check_collapsible_if_if(cx, expr, cond, then); + self.check_collapsible_if_if(cx, expr, cond, block!(then)); } } } } -fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool { +fn block_starts_with_comment(cx: &LateContext<'_>, block: &Block<'_>) -> bool { // We trim all opening braces and whitespaces and then check if the next string is a comment. - let trimmed_block_text = snippet_block(cx, expr.span, "..", None) + let trimmed_block_text = snippet_block(cx, block.span, "..", None) .trim_start_matches(|c: char| c.is_whitespace() || c == '{') .to_owned(); trimmed_block_text.starts_with("//") || trimmed_block_text.starts_with("/*") } -/// If the block contains only one expression, return it. -fn expr_block(block: &ast::Block) -> Option<&ast::Expr> { - if let [stmt] = &*block.stmts - && let ast::StmtKind::Expr(expr) | ast::StmtKind::Semi(expr) = &stmt.kind - { - Some(expr) - } else { - None +/// If `block` is a block with either one expression or a statement containing an expression, +/// return the expression. We don't peel blocks recursively, as extra blocks might be intentional. +fn expr_block<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> { + match block.stmts { + [] => block.expr, + [stmt] => { + if let StmtKind::Semi(expr) = stmt.kind { + Some(expr) + } else { + None + } + }, + _ => None, } } /// If the expression is a `||`, suggest parentheses around it. -fn parens_around(expr: &ast::Expr) -> Vec<(Span, String)> { - if let ast::ExprKind::Binary(op, _, _) = expr.kind - && op.node == ast::BinOpKind::Or +fn parens_around(expr: &Expr<'_>) -> Vec<(Span, String)> { + if let ExprKind::Binary(op, _, _) = expr.peel_drop_temps().kind + && op.node == BinOpKind::Or { vec![ (expr.span.shrink_to_lo(), String::from("(")), diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6f2a4a4c529da..d2d8a1c4ff44f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -771,7 +771,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall)); store.register_early_pass(|| Box::new(unused_unit::UnusedUnit)); store.register_late_pass(|_| Box::new(returns::Return)); - store.register_early_pass(move || Box::new(collapsible_if::CollapsibleIf::new(conf))); + store.register_late_pass(move |_| Box::new(collapsible_if::CollapsibleIf::new(conf))); store.register_late_pass(|_| Box::new(items_after_statements::ItemsAfterStatements)); store.register_early_pass(|| Box::new(precedence::Precedence)); store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals)); From cd701524701bbc3443a007b52edcee6550abb0be Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 26 Mar 2025 20:23:31 +0100 Subject: [PATCH 0334/2248] Make `collapsible_if` recognize the `let_chains` feature Until `if let` chains are stabilized, we do not collapse them together or with other `if` expressions unless the `let_chains` feature is enabled. This is the case for example in Clippy sources. --- clippy_lints/src/collapsible_if.rs | 17 +++-- clippy_lints/src/lib.rs | 2 +- .../collapsible_if_let_chains.fixed | 25 ++++++++ .../collapsible_if_let_chains.rs | 28 ++++++++ .../collapsible_if_let_chains.stderr | 64 +++++++++++++++++++ tests/ui/auxiliary/proc_macros.rs | 12 ++-- tests/ui/collapsible_if_let_chains.fixed | 29 +++++++++ tests/ui/collapsible_if_let_chains.rs | 32 ++++++++++ tests/ui/collapsible_if_let_chains.stderr | 58 +++++++++++++++++ 9 files changed, 254 insertions(+), 13 deletions(-) create mode 100644 tests/ui-toml/collapsible_if/collapsible_if_let_chains.fixed create mode 100644 tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs create mode 100644 tests/ui-toml/collapsible_if/collapsible_if_let_chains.stderr create mode 100644 tests/ui/collapsible_if_let_chains.fixed create mode 100644 tests/ui/collapsible_if_let_chains.rs create mode 100644 tests/ui/collapsible_if_let_chains.stderr diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 8728f7f2eb592..20fae8a6775b9 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -5,6 +5,7 @@ use rustc_ast::BinOpKind; use rustc_errors::Applicability; use rustc_hir::{Block, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -77,12 +78,14 @@ declare_clippy_lint! { } pub struct CollapsibleIf { + let_chains_enabled: bool, lint_commented_code: bool, } impl CollapsibleIf { - pub fn new(conf: &'static Conf) -> Self { + pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { Self { + let_chains_enabled: tcx.features().let_chains(), lint_commented_code: conf.lint_commented_code, } } @@ -124,8 +127,7 @@ impl CollapsibleIf { if let Some(inner) = expr_block(then) && cx.tcx.hir_attrs(inner.hir_id).is_empty() && let ExprKind::If(check_inner, _, None) = &inner.kind - // Prevent triggering on `if c { if let a = b { .. } }`. - && !matches!(check_inner.kind, ExprKind::Let(..)) + && self.eligible_condition(check_inner) && let ctxt = expr.span.ctxt() && inner.span.ctxt() == ctxt && (self.lint_commented_code || !block_starts_with_comment(cx, then)) @@ -160,6 +162,10 @@ impl CollapsibleIf { ); } } + + pub fn eligible_condition(&self, cond: &Expr<'_>) -> bool { + self.let_chains_enabled || !matches!(cond.kind, ExprKind::Let(..)) + } } impl_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]); @@ -174,11 +180,10 @@ impl LateLintPass<'_> for CollapsibleIf { { Self::check_collapsible_else_if(cx, then.span, else_); } else if else_.is_none() - && !matches!(cond.kind, ExprKind::Let(..)) + && self.eligible_condition(cond) && let ExprKind::Block(then, None) = then.kind { - // Prevent triggering on `if c { if let a = b { .. } }`. - self.check_collapsible_if_if(cx, expr, cond, block!(then)); + self.check_collapsible_if_if(cx, expr, cond, then); } } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d2d8a1c4ff44f..ba80e122448d5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -771,7 +771,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall)); store.register_early_pass(|| Box::new(unused_unit::UnusedUnit)); store.register_late_pass(|_| Box::new(returns::Return)); - store.register_late_pass(move |_| Box::new(collapsible_if::CollapsibleIf::new(conf))); + store.register_late_pass(move |tcx| Box::new(collapsible_if::CollapsibleIf::new(tcx, conf))); store.register_late_pass(|_| Box::new(items_after_statements::ItemsAfterStatements)); store.register_early_pass(|| Box::new(precedence::Precedence)); store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals)); diff --git a/tests/ui-toml/collapsible_if/collapsible_if_let_chains.fixed b/tests/ui-toml/collapsible_if/collapsible_if_let_chains.fixed new file mode 100644 index 0000000000000..f12273954c6dd --- /dev/null +++ b/tests/ui-toml/collapsible_if/collapsible_if_let_chains.fixed @@ -0,0 +1,25 @@ +#![feature(let_chains)] +#![warn(clippy::collapsible_if)] + +fn main() { + if let Some(a) = Some(3) + // with comment + && let Some(b) = Some(4) { + let _ = a + b; + } + //~^^^^^^ collapsible_if + + if let Some(a) = Some(3) + // with comment + && a + 1 == 4 { + let _ = a; + } + //~^^^^^^ collapsible_if + + if Some(3) == Some(4).map(|x| x - 1) + // with comment + && let Some(b) = Some(4) { + let _ = b; + } + //~^^^^^^ collapsible_if +} diff --git a/tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs b/tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs new file mode 100644 index 0000000000000..5a984d7a3cbee --- /dev/null +++ b/tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs @@ -0,0 +1,28 @@ +#![feature(let_chains)] +#![warn(clippy::collapsible_if)] + +fn main() { + if let Some(a) = Some(3) { + // with comment + if let Some(b) = Some(4) { + let _ = a + b; + } + } + //~^^^^^^ collapsible_if + + if let Some(a) = Some(3) { + // with comment + if a + 1 == 4 { + let _ = a; + } + } + //~^^^^^^ collapsible_if + + if Some(3) == Some(4).map(|x| x - 1) { + // with comment + if let Some(b) = Some(4) { + let _ = b; + } + } + //~^^^^^^ collapsible_if +} diff --git a/tests/ui-toml/collapsible_if/collapsible_if_let_chains.stderr b/tests/ui-toml/collapsible_if/collapsible_if_let_chains.stderr new file mode 100644 index 0000000000000..c22a65a447301 --- /dev/null +++ b/tests/ui-toml/collapsible_if/collapsible_if_let_chains.stderr @@ -0,0 +1,64 @@ +error: this `if` statement can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs:5:5 + | +LL | / if let Some(a) = Some(3) { +LL | | // with comment +LL | | if let Some(b) = Some(4) { +LL | | let _ = a + b; +LL | | } +LL | | } + | |_____^ + | + = note: `-D clippy::collapsible-if` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::collapsible_if)]` +help: collapse nested if block + | +LL ~ if let Some(a) = Some(3) +LL | // with comment +LL ~ && let Some(b) = Some(4) { +LL | let _ = a + b; +LL ~ } + | + +error: this `if` statement can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs:13:5 + | +LL | / if let Some(a) = Some(3) { +LL | | // with comment +LL | | if a + 1 == 4 { +LL | | let _ = a; +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ if let Some(a) = Some(3) +LL | // with comment +LL ~ && a + 1 == 4 { +LL | let _ = a; +LL ~ } + | + +error: this `if` statement can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs:21:5 + | +LL | / if Some(3) == Some(4).map(|x| x - 1) { +LL | | // with comment +LL | | if let Some(b) = Some(4) { +LL | | let _ = b; +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ if Some(3) == Some(4).map(|x| x - 1) +LL | // with comment +LL ~ && let Some(b) = Some(4) { +LL | let _ = b; +LL ~ } + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/auxiliary/proc_macros.rs b/tests/ui/auxiliary/proc_macros.rs index 1a2a4ec231143..7a4cc4fa9ee8e 100644 --- a/tests/ui/auxiliary/proc_macros.rs +++ b/tests/ui/auxiliary/proc_macros.rs @@ -131,12 +131,12 @@ fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Resul pub fn make_it_big(input: TokenStream) -> TokenStream { let mut expr_repeat = syn::parse_macro_input!(input as syn::ExprRepeat); let len_span = expr_repeat.len.span(); - if let syn::Expr::Lit(expr_lit) = &mut *expr_repeat.len { - if let syn::Lit::Int(lit_int) = &expr_lit.lit { - let orig_val = lit_int.base10_parse::().expect("not a valid length parameter"); - let new_val = orig_val.saturating_mul(10); - expr_lit.lit = syn::parse_quote_spanned!( len_span => #new_val); - } + if let syn::Expr::Lit(expr_lit) = &mut *expr_repeat.len + && let syn::Lit::Int(lit_int) = &expr_lit.lit + { + let orig_val = lit_int.base10_parse::().expect("not a valid length parameter"); + let new_val = orig_val.saturating_mul(10); + expr_lit.lit = syn::parse_quote_spanned!( len_span => #new_val); } quote::quote!(#expr_repeat).into() } diff --git a/tests/ui/collapsible_if_let_chains.fixed b/tests/ui/collapsible_if_let_chains.fixed new file mode 100644 index 0000000000000..3dd9498a4c9f9 --- /dev/null +++ b/tests/ui/collapsible_if_let_chains.fixed @@ -0,0 +1,29 @@ +#![feature(let_chains)] +#![warn(clippy::collapsible_if)] + +fn main() { + if let Some(a) = Some(3) { + // with comment, so do not lint + if let Some(b) = Some(4) { + let _ = a + b; + } + } + + if let Some(a) = Some(3) + && let Some(b) = Some(4) { + let _ = a + b; + } + //~^^^^^ collapsible_if + + if let Some(a) = Some(3) + && a + 1 == 4 { + let _ = a; + } + //~^^^^^ collapsible_if + + if Some(3) == Some(4).map(|x| x - 1) + && let Some(b) = Some(4) { + let _ = b; + } + //~^^^^^ collapsible_if +} diff --git a/tests/ui/collapsible_if_let_chains.rs b/tests/ui/collapsible_if_let_chains.rs new file mode 100644 index 0000000000000..064b9a0be4847 --- /dev/null +++ b/tests/ui/collapsible_if_let_chains.rs @@ -0,0 +1,32 @@ +#![feature(let_chains)] +#![warn(clippy::collapsible_if)] + +fn main() { + if let Some(a) = Some(3) { + // with comment, so do not lint + if let Some(b) = Some(4) { + let _ = a + b; + } + } + + if let Some(a) = Some(3) { + if let Some(b) = Some(4) { + let _ = a + b; + } + } + //~^^^^^ collapsible_if + + if let Some(a) = Some(3) { + if a + 1 == 4 { + let _ = a; + } + } + //~^^^^^ collapsible_if + + if Some(3) == Some(4).map(|x| x - 1) { + if let Some(b) = Some(4) { + let _ = b; + } + } + //~^^^^^ collapsible_if +} diff --git a/tests/ui/collapsible_if_let_chains.stderr b/tests/ui/collapsible_if_let_chains.stderr new file mode 100644 index 0000000000000..64a88114c47a3 --- /dev/null +++ b/tests/ui/collapsible_if_let_chains.stderr @@ -0,0 +1,58 @@ +error: this `if` statement can be collapsed + --> tests/ui/collapsible_if_let_chains.rs:12:5 + | +LL | / if let Some(a) = Some(3) { +LL | | if let Some(b) = Some(4) { +LL | | let _ = a + b; +LL | | } +LL | | } + | |_____^ + | + = note: `-D clippy::collapsible-if` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::collapsible_if)]` +help: collapse nested if block + | +LL ~ if let Some(a) = Some(3) +LL ~ && let Some(b) = Some(4) { +LL | let _ = a + b; +LL ~ } + | + +error: this `if` statement can be collapsed + --> tests/ui/collapsible_if_let_chains.rs:19:5 + | +LL | / if let Some(a) = Some(3) { +LL | | if a + 1 == 4 { +LL | | let _ = a; +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ if let Some(a) = Some(3) +LL ~ && a + 1 == 4 { +LL | let _ = a; +LL ~ } + | + +error: this `if` statement can be collapsed + --> tests/ui/collapsible_if_let_chains.rs:26:5 + | +LL | / if Some(3) == Some(4).map(|x| x - 1) { +LL | | if let Some(b) = Some(4) { +LL | | let _ = b; +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ if Some(3) == Some(4).map(|x| x - 1) +LL ~ && let Some(b) = Some(4) { +LL | let _ = b; +LL ~ } + | + +error: aborting due to 3 previous errors + From 79c69112dc1dd5803af4e2682552c1ad2dde14ca Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 26 Mar 2025 20:38:58 +0100 Subject: [PATCH 0335/2248] Apply `collapsible_if` to Clippy itself Since Clippy uses the `let_chains` feature, there are many occasions to collapse `if` and `if let` statements. --- clippy_dev/src/update_lints.rs | 76 ++--- clippy_dev/src/utils.rs | 8 +- .../src/arbitrary_source_item_ordering.rs | 18 +- .../attrs/blanket_clippy_restriction_lints.rs | 23 +- clippy_lints/src/attrs/deprecated_semver.rs | 8 +- clippy_lints/src/attrs/mod.rs | 41 ++- clippy_lints/src/attrs/useless_attribute.rs | 130 ++++----- clippy_lints/src/await_holding_invalid.rs | 5 +- clippy_lints/src/booleans.rs | 22 +- clippy_lints/src/borrow_deref_ref.rs | 8 +- .../src/casts/cast_possible_truncation.rs | 8 +- clippy_lints/src/casts/cast_ptr_alignment.rs | 19 +- .../src/casts/cast_slice_different_sizes.rs | 65 +++-- clippy_lints/src/casts/unnecessary_cast.rs | 10 +- clippy_lints/src/checked_conversions.rs | 8 +- clippy_lints/src/copies.rs | 8 +- clippy_lints/src/dereference.rs | 105 ++++--- clippy_lints/src/derivable_impls.rs | 24 +- clippy_lints/src/derive.rs | 8 +- clippy_lints/src/doc/markdown.rs | 26 +- clippy_lints/src/doc/mod.rs | 36 ++- clippy_lints/src/drop_forget_ref.rs | 8 +- clippy_lints/src/enum_clike.rs | 8 +- clippy_lints/src/escape.rs | 37 +-- clippy_lints/src/fallible_impl_from.rs | 8 +- clippy_lints/src/floating_point_arithmetic.rs | 144 +++++----- clippy_lints/src/formatting.rs | 41 +-- .../src/functions/too_many_arguments.rs | 18 +- clippy_lints/src/implicit_return.rs | 22 +- clippy_lints/src/indexing_slicing.rs | 40 +-- clippy_lints/src/infinite_iter.rs | 11 +- clippy_lints/src/int_plus_one.rs | 24 +- .../src/invalid_upcast_comparisons.rs | 84 +++--- clippy_lints/src/item_name_repetitions.rs | 95 +++---- clippy_lints/src/len_zero.rs | 18 +- clippy_lints/src/lifetimes.rs | 8 +- clippy_lints/src/literal_representation.rs | 11 +- .../literal_string_with_formatting_args.rs | 9 +- clippy_lints/src/loops/for_kv_map.rs | 74 ++--- clippy_lints/src/loops/manual_memcpy.rs | 123 ++++---- .../src/loops/manual_while_let_some.rs | 16 +- clippy_lints/src/loops/mut_range_bound.rs | 16 +- clippy_lints/src/loops/needless_range_loop.rs | 269 +++++++++--------- clippy_lints/src/loops/never_loop.rs | 8 +- clippy_lints/src/manual_retain.rs | 35 ++- clippy_lints/src/manual_string_new.rs | 15 +- clippy_lints/src/map_unit_fn.rs | 8 +- clippy_lints/src/matches/manual_filter.rs | 20 +- .../src/matches/match_like_matches.rs | 25 +- .../src/matches/match_single_binding.rs | 28 +- .../src/matches/match_str_case_mismatch.rs | 8 +- clippy_lints/src/matches/match_wild_enum.rs | 18 +- .../src/matches/match_wild_err_arm.rs | 11 +- clippy_lints/src/matches/needless_match.rs | 8 +- clippy_lints/src/matches/overlapping_arms.rs | 22 +- .../matches/significant_drop_in_scrutinee.rs | 9 +- clippy_lints/src/matches/wild_in_or_pats.rs | 22 +- .../src/methods/bind_instead_of_map.rs | 8 +- ...se_sensitive_file_extension_comparisons.rs | 10 +- clippy_lints/src/methods/clone_on_copy.rs | 8 +- clippy_lints/src/methods/expect_fun_call.rs | 9 +- clippy_lints/src/methods/is_empty.rs | 16 +- .../src/methods/iterator_step_by_zero.rs | 18 +- .../methods/manual_saturating_arithmetic.rs | 26 +- clippy_lints/src/methods/map_clone.rs | 16 +- clippy_lints/src/methods/mod.rs | 11 +- clippy_lints/src/methods/needless_collect.rs | 26 +- .../src/methods/needless_option_take.rs | 49 ++-- clippy_lints/src/methods/seek_from_current.rs | 29 +- clippy_lints/src/methods/str_splitn.rs | 15 +- clippy_lints/src/methods/suspicious_map.rs | 8 +- .../src/methods/unnecessary_lazy_eval.rs | 94 +++--- .../src/misc_early/builtin_type_shadow.rs | 18 +- .../src/misc_early/redundant_pattern.rs | 30 +- .../misc_early/unneeded_wildcard_pattern.rs | 46 +-- .../src/mismatching_type_param_order.rs | 8 +- clippy_lints/src/missing_const_for_fn.rs | 11 +- clippy_lints/src/missing_fields_in_debug.rs | 7 +- clippy_lints/src/missing_inline.rs | 13 +- .../src/mixed_read_write_in_expression.rs | 16 +- clippy_lints/src/module_style.rs | 32 +-- .../src/multiple_unsafe_ops_per_block.rs | 5 +- clippy_lints/src/mut_key.rs | 8 +- clippy_lints/src/mut_mut.rs | 20 +- clippy_lints/src/mutable_debug_assertion.rs | 11 +- clippy_lints/src/mutex_atomic.rs | 24 +- clippy_lints/src/needless_bool.rs | 8 +- clippy_lints/src/needless_pass_by_ref_mut.rs | 65 ++--- clippy_lints/src/needless_pass_by_value.rs | 71 +++-- clippy_lints/src/needless_update.rs | 21 +- clippy_lints/src/neg_multiply.rs | 16 +- clippy_lints/src/new_without_default.rs | 8 +- clippy_lints/src/no_effect.rs | 31 +- clippy_lints/src/non_zero_suggestions.rs | 7 +- clippy_lints/src/operators/modulo_one.rs | 18 +- .../src/operators/numeric_arithmetic.rs | 16 +- clippy_lints/src/operators/op_ref.rs | 11 +- clippy_lints/src/pass_by_ref_or_value.rs | 32 +-- clippy_lints/src/pathbuf_init_then_push.rs | 19 +- clippy_lints/src/pattern_type_mismatch.rs | 21 +- clippy_lints/src/ptr_offset_with_cast.rs | 24 +- clippy_lints/src/ranges.rs | 32 +-- clippy_lints/src/redundant_clone.rs | 25 +- clippy_lints/src/redundant_slicing.rs | 33 ++- clippy_lints/src/serde_api.rs | 40 +-- clippy_lints/src/shadow.rs | 8 +- .../src/significant_drop_tightening.rs | 8 +- .../src/single_char_lifetime_names.rs | 27 +- .../src/single_component_path_imports.rs | 22 +- clippy_lints/src/strings.rs | 11 +- clippy_lints/src/swap.rs | 11 +- clippy_lints/src/trait_bounds.rs | 23 +- clippy_lints/src/types/mod.rs | 40 +-- clippy_lints/src/unicode.rs | 8 +- clippy_lints/src/unnecessary_wraps.rs | 10 +- clippy_lints/src/unnested_or_patterns.rs | 8 +- clippy_lints/src/unused_io_amount.rs | 17 +- clippy_lints/src/useless_conversion.rs | 56 ++-- .../interning_defined_symbol.rs | 70 ++--- .../src/utils/internal_lints/invalid_paths.rs | 30 +- .../internal_lints/lint_without_lint_pass.rs | 8 +- .../internal_lints/unnecessary_def_path.rs | 8 +- .../unsorted_clippy_utils_paths.rs | 38 ++- clippy_lints/src/zero_sized_map_values.rs | 8 +- clippy_utils/src/diagnostics.rs | 20 +- clippy_utils/src/higher.rs | 11 +- clippy_utils/src/lib.rs | 157 +++++----- clippy_utils/src/source.rs | 18 +- clippy_utils/src/sugg.rs | 5 +- clippy_utils/src/ty/mod.rs | 24 +- clippy_utils/src/usage.rs | 8 +- clippy_utils/src/visitors.rs | 8 +- lintcheck/src/main.rs | 8 +- src/driver.rs | 20 +- tests/compile-test.rs | 14 +- 135 files changed, 1864 insertions(+), 1907 deletions(-) diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index b80ee5aac7e76..0be24f322d2de 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -402,53 +402,53 @@ fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec) -> io } } - if path.exists() { - if let Some(lint) = lints.iter().find(|l| l.name == name) { - if lint.module == name { - // The lint name is the same as the file, we can just delete the entire file - fs::remove_file(path)?; - } else { - // We can't delete the entire file, just remove the declaration - - if let Some(Some("mod.rs")) = path.file_name().map(OsStr::to_str) { - // Remove clippy_lints/src/some_mod/some_lint.rs - let mut lint_mod_path = path.to_path_buf(); - lint_mod_path.set_file_name(name); - lint_mod_path.set_extension("rs"); + if path.exists() + && let Some(lint) = lints.iter().find(|l| l.name == name) + { + if lint.module == name { + // The lint name is the same as the file, we can just delete the entire file + fs::remove_file(path)?; + } else { + // We can't delete the entire file, just remove the declaration - let _ = fs::remove_file(lint_mod_path); - } + if let Some(Some("mod.rs")) = path.file_name().map(OsStr::to_str) { + // Remove clippy_lints/src/some_mod/some_lint.rs + let mut lint_mod_path = path.to_path_buf(); + lint_mod_path.set_file_name(name); + lint_mod_path.set_extension("rs"); - let mut content = - fs::read_to_string(path).unwrap_or_else(|_| panic!("failed to read `{}`", path.to_string_lossy())); + let _ = fs::remove_file(lint_mod_path); + } - eprintln!( - "warn: you will have to manually remove any code related to `{name}` from `{}`", - path.display() - ); + let mut content = + fs::read_to_string(path).unwrap_or_else(|_| panic!("failed to read `{}`", path.to_string_lossy())); - assert!( - content[lint.declaration_range.clone()].contains(&name.to_uppercase()), - "error: `{}` does not contain lint `{}`'s declaration", - path.display(), - lint.name - ); + eprintln!( + "warn: you will have to manually remove any code related to `{name}` from `{}`", + path.display() + ); - // Remove lint declaration (declare_clippy_lint!) - content.replace_range(lint.declaration_range.clone(), ""); + assert!( + content[lint.declaration_range.clone()].contains(&name.to_uppercase()), + "error: `{}` does not contain lint `{}`'s declaration", + path.display(), + lint.name + ); - // Remove the module declaration (mod xyz;) - let mod_decl = format!("\nmod {name};"); - content = content.replacen(&mod_decl, "", 1); + // Remove lint declaration (declare_clippy_lint!) + content.replace_range(lint.declaration_range.clone(), ""); - remove_impl_lint_pass(&lint.name.to_uppercase(), &mut content); - fs::write(path, content).unwrap_or_else(|_| panic!("failed to write to `{}`", path.to_string_lossy())); - } + // Remove the module declaration (mod xyz;) + let mod_decl = format!("\nmod {name};"); + content = content.replacen(&mod_decl, "", 1); - remove_test_assets(name); - remove_lint(name, lints); - return Ok(true); + remove_impl_lint_pass(&lint.name.to_uppercase(), &mut content); + fs::write(path, content).unwrap_or_else(|_| panic!("failed to write to `{}`", path.to_string_lossy())); } + + remove_test_assets(name); + remove_lint(name, lints); + return Ok(true); } Ok(false) diff --git a/clippy_dev/src/utils.rs b/clippy_dev/src/utils.rs index b87fcca13b1ce..206816398f50f 100644 --- a/clippy_dev/src/utils.rs +++ b/clippy_dev/src/utils.rs @@ -30,10 +30,10 @@ pub fn clippy_project_root() -> PathBuf { let current_dir = std::env::current_dir().unwrap(); for path in current_dir.ancestors() { let result = fs::read_to_string(path.join("Cargo.toml")); - if let Err(err) = &result { - if err.kind() == io::ErrorKind::NotFound { - continue; - } + if let Err(err) = &result + && err.kind() == io::ErrorKind::NotFound + { + continue; } let content = result.unwrap(); diff --git a/clippy_lints/src/arbitrary_source_item_ordering.rs b/clippy_lints/src/arbitrary_source_item_ordering.rs index 57cabe437034a..9113c20c795b7 100644 --- a/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -263,10 +263,11 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { continue; } - if let Some(cur_v) = cur_v { - if cur_v.ident.name.as_str() > variant.ident.name.as_str() && cur_v.span != variant.span { - Self::lint_member_name(cx, &variant.ident, &cur_v.ident); - } + if let Some(cur_v) = cur_v + && cur_v.ident.name.as_str() > variant.ident.name.as_str() + && cur_v.span != variant.span + { + Self::lint_member_name(cx, &variant.ident, &cur_v.ident); } cur_v = Some(variant); } @@ -278,10 +279,11 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { continue; } - if let Some(cur_f) = cur_f { - if cur_f.ident.name.as_str() > field.ident.name.as_str() && cur_f.span != field.span { - Self::lint_member_name(cx, &field.ident, &cur_f.ident); - } + if let Some(cur_f) = cur_f + && cur_f.ident.name.as_str() > field.ident.name.as_str() + && cur_f.span != field.span + { + Self::lint_member_name(cx, &field.ident, &cur_f.ident); } cur_f = Some(field); } diff --git a/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs b/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs index fecf316640636..457692ed5dc53 100644 --- a/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs +++ b/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs @@ -8,17 +8,18 @@ use rustc_span::{DUMMY_SP, sym}; pub(super) fn check(cx: &EarlyContext<'_>, name: Symbol, items: &[MetaItemInner]) { for lint in items { - if let Some(lint_name) = extract_clippy_lint(lint) { - if lint_name.as_str() == "restriction" && name != sym::allow { - span_lint_and_help( - cx, - BLANKET_CLIPPY_RESTRICTION_LINTS, - lint.span(), - "`clippy::restriction` is not meant to be enabled as a group", - None, - "enable the restriction lints you need individually", - ); - } + if let Some(lint_name) = extract_clippy_lint(lint) + && lint_name.as_str() == "restriction" + && name != sym::allow + { + span_lint_and_help( + cx, + BLANKET_CLIPPY_RESTRICTION_LINTS, + lint.span(), + "`clippy::restriction` is not meant to be enabled as a group", + None, + "enable the restriction lints you need individually", + ); } } } diff --git a/clippy_lints/src/attrs/deprecated_semver.rs b/clippy_lints/src/attrs/deprecated_semver.rs index d3153ec6613b5..50943b36809d2 100644 --- a/clippy_lints/src/attrs/deprecated_semver.rs +++ b/clippy_lints/src/attrs/deprecated_semver.rs @@ -6,10 +6,10 @@ use rustc_span::Span; use semver::Version; pub(super) fn check(cx: &EarlyContext<'_>, span: Span, lit: &MetaItemLit) { - if let LitKind::Str(is, _) = lit.kind { - if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() { - return; - } + if let LitKind::Str(is, _) = lit.kind + && (is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok()) + { + return; } span_lint( cx, diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 6f8a9a6ecbe3d..f7f168cb26792 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -573,28 +573,27 @@ impl EarlyLintPass for PostExpansionEarlyAttributes { } fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { - if let Some(items) = &attr.meta_item_list() { - if let Some(ident) = attr.ident() { - if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) { - allow_attributes::check(cx, attr); - } - if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) + if let Some(items) = &attr.meta_item_list() + && let Some(ident) = attr.ident() + { + if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) { + allow_attributes::check(cx, attr); + } + if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) { + allow_attributes_without_reason::check(cx, ident.name, items, attr); + } + if is_lint_level(ident.name, attr.id) { + blanket_clippy_restriction_lints::check(cx, ident.name, items); + } + if items.is_empty() || !attr.has_name(sym::deprecated) { + return; + } + for item in items { + if let MetaItemInner::MetaItem(mi) = &item + && let MetaItemKind::NameValue(lit) = &mi.kind + && mi.has_name(sym::since) { - allow_attributes_without_reason::check(cx, ident.name, items, attr); - } - if is_lint_level(ident.name, attr.id) { - blanket_clippy_restriction_lints::check(cx, ident.name, items); - } - if items.is_empty() || !attr.has_name(sym::deprecated) { - return; - } - for item in items { - if let MetaItemInner::MetaItem(mi) = &item - && let MetaItemKind::NameValue(lit) = &mi.kind - && mi.has_name(sym::since) - { - deprecated_semver::check(cx, item.span(), lit); - } + deprecated_semver::check(cx, item.span(), lit); } } } diff --git a/clippy_lints/src/attrs/useless_attribute.rs b/clippy_lints/src/attrs/useless_attribute.rs index e3e081ce08e9f..064b72b930581 100644 --- a/clippy_lints/src/attrs/useless_attribute.rs +++ b/clippy_lints/src/attrs/useless_attribute.rs @@ -14,75 +14,75 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) { if attr.span.in_external_macro(cx.sess().source_map()) { return; } - if let Some(lint_list) = &attr.meta_item_list() { - if attr.ident().is_some_and(|ident| is_lint_level(ident.name, attr.id)) { - for lint in lint_list { - match item.kind { - ItemKind::Use(..) => { - let (namespace @ (Some(sym::clippy) | None), Some(name)) = namespace_and_lint(lint) else { - return; - }; + if let Some(lint_list) = &attr.meta_item_list() + && attr.ident().is_some_and(|ident| is_lint_level(ident.name, attr.id)) + { + for lint in lint_list { + match item.kind { + ItemKind::Use(..) => { + let (namespace @ (Some(sym::clippy) | None), Some(name)) = namespace_and_lint(lint) else { + return; + }; - if namespace.is_none() - && matches!( - name.as_str(), - "ambiguous_glob_reexports" - | "dead_code" - | "deprecated" - | "hidden_glob_reexports" - | "unreachable_pub" - | "unused" - | "unused_braces" - | "unused_import_braces" - | "unused_imports" - ) - { - return; - } + if namespace.is_none() + && matches!( + name.as_str(), + "ambiguous_glob_reexports" + | "dead_code" + | "deprecated" + | "hidden_glob_reexports" + | "unreachable_pub" + | "unused" + | "unused_braces" + | "unused_import_braces" + | "unused_imports" + ) + { + return; + } - if namespace == Some(sym::clippy) - && matches!( - name.as_str(), - "wildcard_imports" - | "enum_glob_use" - | "redundant_pub_crate" - | "macro_use_imports" - | "unsafe_removed_from_name" - | "module_name_repetitions" - | "single_component_path_imports" - | "disallowed_types" - | "unused_trait_names" - ) - { - return; - } - }, - ItemKind::ExternCrate(..) => { - if is_word(lint, sym::unused_imports) && skip_unused_imports { - return; - } - if is_word(lint, sym!(unused_extern_crates)) { - return; - } - }, - _ => {}, - } + if namespace == Some(sym::clippy) + && matches!( + name.as_str(), + "wildcard_imports" + | "enum_glob_use" + | "redundant_pub_crate" + | "macro_use_imports" + | "unsafe_removed_from_name" + | "module_name_repetitions" + | "single_component_path_imports" + | "disallowed_types" + | "unused_trait_names" + ) + { + return; + } + }, + ItemKind::ExternCrate(..) => { + if is_word(lint, sym::unused_imports) && skip_unused_imports { + return; + } + if is_word(lint, sym!(unused_extern_crates)) { + return; + } + }, + _ => {}, } - let line_span = first_line_of_span(cx, attr.span); + } + let line_span = first_line_of_span(cx, attr.span); - if let Some(src) = line_span.get_source_text(cx) { - if src.contains("#[") { - #[expect(clippy::collapsible_span_lint_calls)] - span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| { - diag.span_suggestion( - line_span, - "if you just forgot a `!`, use", - src.replacen("#[", "#![", 1), - Applicability::MaybeIncorrect, - ); - }); - } - } + if let Some(src) = line_span.get_source_text(cx) + && src.contains("#[") + { + #[expect(clippy::collapsible_span_lint_calls)] + span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| { + diag.span_suggestion( + line_span, + "if you just forgot a `!`, use", + src.replacen("#[", "#![", 1), + Applicability::MaybeIncorrect, + ); + }); } } } diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs index 92a0c7f9acbcd..d600aec8c9d65 100644 --- a/clippy_lints/src/await_holding_invalid.rs +++ b/clippy_lints/src/await_holding_invalid.rs @@ -192,10 +192,9 @@ impl<'tcx> LateLintPass<'tcx> for AwaitHolding { def_id, .. }) = expr.kind + && let Some(coroutine_layout) = cx.tcx.mir_coroutine_witnesses(*def_id) { - if let Some(coroutine_layout) = cx.tcx.mir_coroutine_witnesses(*def_id) { - self.check_interior_types(cx, coroutine_layout); - } + self.check_interior_types(cx, coroutine_layout); } } } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 36c1aea263781..249f3b375c0ca 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -242,11 +242,11 @@ struct Hir2Qmm<'a, 'tcx, 'v> { impl<'v> Hir2Qmm<'_, '_, 'v> { fn extract(&mut self, op: BinOpKind, a: &[&'v Expr<'_>], mut v: Vec) -> Result, String> { for a in a { - if let ExprKind::Binary(binop, lhs, rhs) = &a.kind { - if binop.node == op { - v = self.extract(op, &[lhs, rhs], v)?; - continue; - } + if let ExprKind::Binary(binop, lhs, rhs) = &a.kind + && binop.node == op + { + v = self.extract(op, &[lhs, rhs], v)?; + continue; } v.push(self.run(a)?); } @@ -418,12 +418,12 @@ fn simplify_not(cx: &LateContext<'_>, curr_msrv: Msrv, expr: &Expr<'_>) -> Optio let lhs_snippet = lhs.span.get_source_text(cx)?; let rhs_snippet = rhs.span.get_source_text(cx)?; - if !(lhs_snippet.starts_with('(') && lhs_snippet.ends_with(')')) { - if let (ExprKind::Cast(..), BinOpKind::Ge) = (&lhs.kind, binop.node) { - // e.g. `(a as u64) < b`. Without the parens the `<` is - // interpreted as a start of generic arguments for `u64` - return Some(format!("({lhs_snippet}){op}{rhs_snippet}")); - } + if !(lhs_snippet.starts_with('(') && lhs_snippet.ends_with(')')) + && let (ExprKind::Cast(..), BinOpKind::Ge) = (&lhs.kind, binop.node) + { + // e.g. `(a as u64) < b`. Without the parens the `<` is + // interpreted as a start of generic arguments for `u64` + return Some(format!("({lhs_snippet}){op}{rhs_snippet}")); } Some(format!("{lhs_snippet}{op}{rhs_snippet}")) diff --git a/clippy_lints/src/borrow_deref_ref.rs b/clippy_lints/src/borrow_deref_ref.rs index cfe5e424ff750..7cde007a9b66d 100644 --- a/clippy_lints/src/borrow_deref_ref.rs +++ b/clippy_lints/src/borrow_deref_ref.rs @@ -93,10 +93,10 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { // has deref trait -> give 2 help // doesn't have deref trait -> give 1 help - if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait() { - if !implements_trait(cx, *inner_ty, deref_trait_id, &[]) { - return; - } + if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait() + && !implements_trait(cx, *inner_ty, deref_trait_id, &[]) + { + return; } diag.span_suggestion( diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index b28ac8dc971da..8742f5f1a0e0e 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -64,11 +64,11 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::MAX)) }, ExprKind::MethodCall(method, _, [lo, hi], _) => { - if method.ident.as_str() == "clamp" { + if method.ident.as_str() == "clamp" //FIXME: make this a diagnostic item - if let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) { - return lo_bits.max(hi_bits); - } + && let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) + { + return lo_bits.max(hi_bits); } nbits }, diff --git a/clippy_lints/src/casts/cast_ptr_alignment.rs b/clippy_lints/src/casts/cast_ptr_alignment.rs index 57a135abc2e2b..3fca0f8970770 100644 --- a/clippy_lints/src/casts/cast_ptr_alignment.rs +++ b/clippy_lints/src/casts/cast_ptr_alignment.rs @@ -19,16 +19,15 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { cx.typeck_results().expr_ty(expr), ); lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); - } else if let ExprKind::MethodCall(method_path, self_arg, [], _) = &expr.kind { - if method_path.ident.name.as_str() == "cast" - && let Some(generic_args) = method_path.args - && let [GenericArg::Type(cast_to)] = generic_args.args - // There probably is no obvious reason to do this, just to be consistent with `as` cases. - && !is_hir_ty_cfg_dependant(cx, cast_to.as_unambig_ty()) - { - let (cast_from, cast_to) = (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr)); - lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); - } + } else if let ExprKind::MethodCall(method_path, self_arg, [], _) = &expr.kind + && method_path.ident.name.as_str() == "cast" + && let Some(generic_args) = method_path.args + && let [GenericArg::Type(cast_to)] = generic_args.args + // There probably is no obvious reason to do this, just to be consistent with `as` cases. + && !is_hir_ty_cfg_dependant(cx, cast_to.as_unambig_ty()) + { + let (cast_from, cast_to) = (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr)); + lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); } } diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs index c48f253606dcc..a5b295c88b1c7 100644 --- a/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -21,42 +21,41 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: Msrv) start_ty, end_ty, }) = expr_cast_chain_tys(cx, expr) + && let (Ok(from_layout), Ok(to_layout)) = (cx.layout_of(start_ty.ty), cx.layout_of(end_ty.ty)) { - if let (Ok(from_layout), Ok(to_layout)) = (cx.layout_of(start_ty.ty), cx.layout_of(end_ty.ty)) { - let from_size = from_layout.size.bytes(); - let to_size = to_layout.size.bytes(); - if from_size != to_size && from_size != 0 && to_size != 0 && msrv.meets(cx, msrvs::PTR_SLICE_RAW_PARTS) { - span_lint_and_then( - cx, - CAST_SLICE_DIFFERENT_SIZES, - expr.span, - format!( - "casting between raw pointers to `[{}]` (element size {from_size}) and `[{}]` (element size {to_size}) does not adjust the count", - start_ty.ty, end_ty.ty, - ), - |diag| { - let ptr_snippet = source::snippet(cx, left_cast.span, ".."); + let from_size = from_layout.size.bytes(); + let to_size = to_layout.size.bytes(); + if from_size != to_size && from_size != 0 && to_size != 0 && msrv.meets(cx, msrvs::PTR_SLICE_RAW_PARTS) { + span_lint_and_then( + cx, + CAST_SLICE_DIFFERENT_SIZES, + expr.span, + format!( + "casting between raw pointers to `[{}]` (element size {from_size}) and `[{}]` (element size {to_size}) does not adjust the count", + start_ty.ty, end_ty.ty, + ), + |diag| { + let ptr_snippet = source::snippet(cx, left_cast.span, ".."); - let (mutbl_fn_str, mutbl_ptr_str) = match end_ty.mutbl { - Mutability::Mut => ("_mut", "mut"), - Mutability::Not => ("", "const"), - }; - let sugg = format!( - "core::ptr::slice_from_raw_parts{mutbl_fn_str}({ptr_snippet} as *{mutbl_ptr_str} {}, ..)", - // get just the ty from the TypeAndMut so that the printed type isn't something like `mut - // T`, extract just the `T` - end_ty.ty - ); + let (mutbl_fn_str, mutbl_ptr_str) = match end_ty.mutbl { + Mutability::Mut => ("_mut", "mut"), + Mutability::Not => ("", "const"), + }; + let sugg = format!( + "core::ptr::slice_from_raw_parts{mutbl_fn_str}({ptr_snippet} as *{mutbl_ptr_str} {}, ..)", + // get just the ty from the TypeAndMut so that the printed type isn't something like `mut + // T`, extract just the `T` + end_ty.ty + ); - diag.span_suggestion( - expr.span, - format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"), - sugg, - rustc_errors::Applicability::HasPlaceholders, - ); - }, - ); - } + diag.span_suggestion( + expr.span, + format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"), + sugg, + rustc_errors::Applicability::HasPlaceholders, + ); + }, + ); } } } diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index 7885f171461d7..96c5da2cf73ea 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -130,11 +130,11 @@ pub(super) fn check<'tcx>( | LitKind::Float(_, LitFloatType::Suffixed(_)) if cast_from.kind() == cast_to.kind() => { - if let Some(src) = cast_expr.span.get_source_text(cx) { - if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) { - lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to); - return true; - } + if let Some(src) = cast_expr.span.get_source_text(cx) + && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) + { + lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to); + return true; } }, _ => {}, diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index b36c8662289ca..8ada608049c7b 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -253,11 +253,11 @@ fn get_types_from_cast<'a>( match limit.kind { // `from_type::from(_)` ExprKind::Call(path, _) => { - if let ExprKind::Path(ref path) = path.kind { + if let ExprKind::Path(ref path) = path.kind // `to_type` - if let Some(to_type) = get_implementing_type(path, types, func) { - return Some((from_type, to_type)); - } + && let Some(to_type) = get_implementing_type(path, types, func) + { + return Some((from_type, to_type)); } }, // `to_type::MAX` diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index d85005d57ede8..42fbe6438d4ea 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -539,10 +539,10 @@ fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbo .filter(|stmt| !ignore_span.overlaps(stmt.span)) .try_for_each(|stmt| intravisit::walk_stmt(&mut walker, stmt)); - if let Some(expr) = block.expr { - if res.is_continue() { - res = intravisit::walk_expr(&mut walker, expr); - } + if let Some(expr) = block.expr + && res.is_continue() + { + res = intravisit::walk_expr(&mut walker, expr); } res.is_break() diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 849c60b89b97e..7da5a530eaa3d 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -1133,61 +1133,60 @@ fn report<'tcx>( impl<'tcx> Dereferencing<'tcx> { fn check_local_usage(&mut self, cx: &LateContext<'tcx>, e: &Expr<'tcx>, local: HirId) { - if let Some(outer_pat) = self.ref_locals.get_mut(&local) { - if let Some(pat) = outer_pat { - // Check for auto-deref - if !matches!( - cx.typeck_results().expr_adjustments(e), - [ - Adjustment { - kind: Adjust::Deref(_), - .. - }, - Adjustment { - kind: Adjust::Deref(_), - .. - }, + if let Some(outer_pat) = self.ref_locals.get_mut(&local) + && let Some(pat) = outer_pat + // Check for auto-deref + && !matches!( + cx.typeck_results().expr_adjustments(e), + [ + Adjustment { + kind: Adjust::Deref(_), .. - ] - ) { - match get_parent_expr(cx, e) { - // Field accesses are the same no matter the number of references. - Some(Expr { - kind: ExprKind::Field(..), - .. - }) => (), - Some(&Expr { - span, - kind: ExprKind::Unary(UnOp::Deref, _), - .. - }) if !span.from_expansion() => { - // Remove explicit deref. - let snip = snippet_with_context(cx, e.span, span.ctxt(), "..", &mut pat.app).0; - pat.replacements.push((span, snip.into())); - }, - Some(parent) if !parent.span.from_expansion() => { - // Double reference might be needed at this point. - if parent.precedence() == ExprPrecedence::Unambiguous { - // Parentheses would be needed here, don't lint. - *outer_pat = None; - } else { - pat.always_deref = false; - let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0; - pat.replacements.push((e.span, format!("&{snip}"))); - } - }, - _ if !e.span.from_expansion() => { - // Double reference might be needed at this point. - pat.always_deref = false; - let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app); - pat.replacements.push((e.span, format!("&{snip}"))); - }, - // Edge case for macros. The span of the identifier will usually match the context of the - // binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc - // macros - _ => *outer_pat = None, + }, + Adjustment { + kind: Adjust::Deref(_), + .. + }, + .. + ] + ) + { + match get_parent_expr(cx, e) { + // Field accesses are the same no matter the number of references. + Some(Expr { + kind: ExprKind::Field(..), + .. + }) => (), + Some(&Expr { + span, + kind: ExprKind::Unary(UnOp::Deref, _), + .. + }) if !span.from_expansion() => { + // Remove explicit deref. + let snip = snippet_with_context(cx, e.span, span.ctxt(), "..", &mut pat.app).0; + pat.replacements.push((span, snip.into())); + }, + Some(parent) if !parent.span.from_expansion() => { + // Double reference might be needed at this point. + if parent.precedence() == ExprPrecedence::Unambiguous { + // Parentheses would be needed here, don't lint. + *outer_pat = None; + } else { + pat.always_deref = false; + let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0; + pat.replacements.push((e.span, format!("&{snip}"))); } - } + }, + _ if !e.span.from_expansion() => { + // Double reference might be needed at this point. + pat.always_deref = false; + let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app); + pat.replacements.push((e.span, format!("&{snip}"))); + }, + // Edge case for macros. The span of the identifier will usually match the context of the + // binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc + // macros + _ => *outer_pat = None, } } } diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 8d9222e4bf61e..479422f7378ed 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -94,18 +94,18 @@ fn check_struct<'tcx>( ty_args: GenericArgsRef<'_>, typeck_results: &'tcx TypeckResults<'tcx>, ) { - if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind { - if let Some(PathSegment { args, .. }) = p.segments.last() { - let args = args.map(|a| a.args).unwrap_or(&[]); - - // ty_args contains the generic parameters of the type declaration, while args contains the - // arguments used at instantiation time. If both len are not equal, it means that some - // parameters were not provided (which means that the default values were used); in this - // case we will not risk suggesting too broad a rewrite. We won't either if any argument - // is a type or a const. - if ty_args.len() != args.len() || args.iter().any(|arg| !matches!(arg, GenericArg::Lifetime(_))) { - return; - } + if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind + && let Some(PathSegment { args, .. }) = p.segments.last() + { + let args = args.map(|a| a.args).unwrap_or(&[]); + + // ty_args contains the generic parameters of the type declaration, while args contains the + // arguments used at instantiation time. If both len are not equal, it means that some + // parameters were not provided (which means that the default values were used); in this + // case we will not risk suggesting too broad a rewrite. We won't either if any argument + // is a type or a const. + if ty_args.len() != args.len() || args.iter().any(|arg| !matches!(arg, GenericArg::Lifetime(_))) { + return; } } diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 2ae35b4005579..e5ec17d89a115 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -428,10 +428,10 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { } fn visit_expr(&mut self, expr: &'tcx Expr<'_>) -> Self::Result { - if let ExprKind::Block(block, _) = expr.kind { - if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) { - return ControlFlow::Break(()); - } + if let ExprKind::Block(block, _) = expr.kind + && block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) + { + return ControlFlow::Break(()); } walk_expr(self, expr) diff --git a/clippy_lints/src/doc/markdown.rs b/clippy_lints/src/doc/markdown.rs index 8cdaba88e5095..7a1c7c675d2ec 100644 --- a/clippy_lints/src/doc/markdown.rs +++ b/clippy_lints/src/doc/markdown.rs @@ -113,20 +113,20 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b s != "-" && s.contains('-') } - if let Ok(url) = Url::parse(word) { + if let Ok(url) = Url::parse(word) // try to get around the fact that `foo::bar` parses as a valid URL - if !url.cannot_be_a_base() { - span_lint_and_sugg( - cx, - DOC_MARKDOWN, - span, - "you should put bare URLs between `<`/`>` or make a proper Markdown link", - "try", - format!("<{word}>"), - Applicability::MachineApplicable, - ); - return; - } + && !url.cannot_be_a_base() + { + span_lint_and_sugg( + cx, + DOC_MARKDOWN, + span, + "you should put bare URLs between `<`/`>` or make a proper Markdown link", + "try", + format!("<{word}>"), + Applicability::MachineApplicable, + ); + return; } // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343) diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 36fd396cc1df8..d0075d01eeaa4 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -880,19 +880,18 @@ fn check_for_code_clusters<'a, Events: Iterator{}", doc[start..end].replace('`', "")); - diag.span_suggestion_verbose( - span, - "wrap the entire group in `` tags", - sugg, - Applicability::MaybeIncorrect, - ); - diag.help("separate code snippets will be shown with a gap"); - }); - } + span_lint_and_then(cx, DOC_LINK_CODE, span, "code link adjacent to code text", |diag| { + let sugg = format!("{}", doc[start..end].replace('`', "")); + diag.span_suggestion_verbose( + span, + "wrap the entire group in `` tags", + sugg, + Applicability::MaybeIncorrect, + ); + diag.help("separate code snippets will be shown with a gap"); + }); } code_includes_link = false; code_starts_at = None; @@ -1201,16 +1200,15 @@ impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { return; } - if let Some(macro_call) = root_macro_call_first_node(self.cx, expr) { - if is_panic(self.cx, macro_call.def_id) + if let Some(macro_call) = root_macro_call_first_node(self.cx, expr) + && (is_panic(self.cx, macro_call.def_id) || matches!( self.cx.tcx.item_name(macro_call.def_id).as_str(), "assert" | "assert_eq" | "assert_ne" - ) - { - self.is_const = self.cx.tcx.hir_is_inside_const_context(expr.hir_id); - self.panic_span = Some(macro_call.span); - } + )) + { + self.is_const = self.cx.tcx.hir_is_inside_const_context(expr.hir_id); + self.panic_span = Some(macro_call.span); } // check for `unwrap` and `expect` for both `Option` and `Result` diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 617982f4da30f..5c360ce6a5f7e 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -144,10 +144,10 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { // .. // } fn is_single_call_in_arm<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'_>, drop_expr: &'tcx Expr<'_>) -> bool { - if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) { - if let Node::Arm(Arm { body, .. }) = cx.tcx.parent_hir_node(drop_expr.hir_id) { - return body.hir_id == drop_expr.hir_id; - } + if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) + && let Node::Arm(Arm { body, .. }) = cx.tcx.parent_hir_node(drop_expr.hir_id) + { + return body.hir_id == drop_expr.hir_id; } false } diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index f01b5c840d290..ec81294624efa 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -49,10 +49,10 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { .ok() .map(|val| rustc_middle::mir::Const::from_value(val, ty)); if let Some(Constant::Int(val)) = constant.and_then(|c| mir_to_const(cx.tcx, c)) { - if let ty::Adt(adt, _) = ty.kind() { - if adt.is_enum() { - ty = adt.repr().discr_type().to_ty(cx.tcx); - } + if let ty::Adt(adt, _) = ty.kind() + && adt.is_enum() + { + ty = adt.repr().discr_type().to_ty(cx.tcx); } match ty.kind() { ty::Int(IntTy::Isize) => { diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 831d47ac48779..e1f4026ad611d 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -72,10 +72,10 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { _: Span, fn_def_id: LocalDefId, ) { - if let Some(header) = fn_kind.header() { - if header.abi != ExternAbi::Rust { - return; - } + if let Some(header) = fn_kind.header() + && header.abi != ExternAbi::Rust + { + return; } let parent_id = cx @@ -141,22 +141,22 @@ fn is_argument(tcx: TyCtxt<'_>, id: HirId) -> bool { impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> { fn consume(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) { - if cmt.place.projections.is_empty() { - if let PlaceBase::Local(lid) = cmt.place.base { - // FIXME(rust/#120456) - is `swap_remove` correct? - self.set.swap_remove(&lid); - } + if cmt.place.projections.is_empty() + && let PlaceBase::Local(lid) = cmt.place.base + { + // FIXME(rust/#120456) - is `swap_remove` correct? + self.set.swap_remove(&lid); } } fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) { - if cmt.place.projections.is_empty() { - if let PlaceBase::Local(lid) = cmt.place.base { - // FIXME(rust/#120456) - is `swap_remove` correct? - self.set.swap_remove(&lid); - } + if cmt.place.projections.is_empty() + && let PlaceBase::Local(lid) = cmt.place.base + { + // FIXME(rust/#120456) - is `swap_remove` correct? + self.set.swap_remove(&lid); } } @@ -170,10 +170,11 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> { // skip if there is a `self` parameter binding to a type // that contains `Self` (i.e.: `self: Box`), see #4804 - if let Some(trait_self_ty) = self.trait_self_ty { - if self.cx.tcx.hir_name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) { - return; - } + if let Some(trait_self_ty) = self.trait_self_ty + && self.cx.tcx.hir_name(cmt.hir_id) == kw::SelfLower + && cmt.place.ty().contains(trait_self_ty) + { + return; } if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) { diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index f67d38d932b9a..c868b782f43c3 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -75,10 +75,10 @@ fn lint_impl_body(cx: &LateContext<'_>, impl_span: Span, impl_items: &[hir::Impl impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if let Some(macro_call) = root_macro_call_first_node(self.lcx, expr) { - if is_panic(self.lcx, macro_call.def_id) { - self.result.push(expr.span); - } + if let Some(macro_call) = root_macro_call_first_node(self.lcx, expr) + && is_panic(self.lcx, macro_call.def_id) + { + self.result.push(expr.span); } // check for `unwrap` diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 92b607c87d75f..d5f0659f8427f 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -228,24 +228,24 @@ fn get_integer_from_float_constant(value: &Constant<'_>) -> Option { fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { // Check receiver - if let Some(value) = ConstEvalCtxt::new(cx).eval(receiver) { - if let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value { + if let Some(value) = ConstEvalCtxt::new(cx).eval(receiver) + && let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value { Some("exp") } else if F32(2.0) == value || F64(2.0) == value { Some("exp2") } else { None - } { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "exponent for bases 2 and e can be computed more accurately", - "consider using", - format!("{}.{method}()", prepare_receiver_sugg(cx, &args[0])), - Applicability::MachineApplicable, - ); } + { + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "exponent for bases 2 and e can be computed more accurately", + "consider using", + format!("{}.{method}()", prepare_receiver_sugg(cx, &args[0])), + Applicability::MachineApplicable, + ); } // Check argument @@ -289,55 +289,53 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: } fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { - if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) { - if value == Int(2) { - if let Some(parent) = get_parent_expr(cx, expr) { - if let Some(grandparent) = get_parent_expr(cx, parent) { - if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = grandparent.kind - { - if method_name.as_str() == "sqrt" && detect_hypot(cx, receiver).is_some() { - return; - } - } - } + if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) + && value == Int(2) + && let Some(parent) = get_parent_expr(cx, expr) + { + if let Some(grandparent) = get_parent_expr(cx, parent) + && let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = grandparent.kind + && method_name.as_str() == "sqrt" + && detect_hypot(cx, receiver).is_some() + { + return; + } + + if let ExprKind::Binary( + Spanned { + node: op @ (BinOpKind::Add | BinOpKind::Sub), + .. + }, + lhs, + rhs, + ) = parent.kind + { + let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs }; - if let ExprKind::Binary( - Spanned { - node: op @ (BinOpKind::Add | BinOpKind::Sub), - .. - }, - lhs, - rhs, - ) = parent.kind - { - let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs }; - - // Negate expr if original code has subtraction and expr is on the right side - let maybe_neg_sugg = |expr, hir_id| { - let sugg = Sugg::hir(cx, expr, ".."); - if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id { - -sugg - } else { - sugg - } - }; - - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - parent.span, - "multiply and add expressions can be calculated more efficiently and accurately", - "consider using", - format!( - "{}.mul_add({}, {})", - Sugg::hir(cx, receiver, "..").maybe_paren(), - maybe_neg_sugg(receiver, expr.hir_id), - maybe_neg_sugg(other_addend, other_addend.hir_id), - ), - Applicability::MachineApplicable, - ); + // Negate expr if original code has subtraction and expr is on the right side + let maybe_neg_sugg = |expr, hir_id| { + let sugg = Sugg::hir(cx, expr, ".."); + if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id { + -sugg + } else { + sugg } - } + }; + + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + parent.span, + "multiply and add expressions can be calculated more efficiently and accurately", + "consider using", + format!( + "{}.mul_add({}, {})", + Sugg::hir(cx, receiver, "..").maybe_paren(), + maybe_neg_sugg(receiver, expr.hir_id), + maybe_neg_sugg(other_addend, other_addend.hir_id), + ), + Applicability::MachineApplicable, + ); } } } @@ -483,12 +481,12 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) { rhs, ) = &expr.kind { - if let Some(parent) = get_parent_expr(cx, expr) { - if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = parent.kind { - if method_name.as_str() == "sqrt" && detect_hypot(cx, receiver).is_some() { - return; - } - } + if let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = parent.kind + && method_name.as_str() == "sqrt" + && detect_hypot(cx, receiver).is_some() + { + return; } let maybe_neg_sugg = |expr| { @@ -566,15 +564,15 @@ fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// If the two expressions are not negations of each other, then it /// returns None. fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a>) -> Option<(bool, &'a Expr<'a>)> { - if let ExprKind::Unary(UnOp::Neg, expr1_negated) = &expr1.kind { - if eq_expr_value(cx, expr1_negated, expr2) { - return Some((false, expr2)); - } + if let ExprKind::Unary(UnOp::Neg, expr1_negated) = &expr1.kind + && eq_expr_value(cx, expr1_negated, expr2) + { + return Some((false, expr2)); } - if let ExprKind::Unary(UnOp::Neg, expr2_negated) = &expr2.kind { - if eq_expr_value(cx, expr1, expr2_negated) { - return Some((true, expr1)); - } + if let ExprKind::Unary(UnOp::Neg, expr2_negated) = &expr2.kind + && eq_expr_value(cx, expr1, expr2_negated) + { + return Some((true, expr1)); } None } diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index c8fe7ac73cb34..4b482f7b233b8 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -138,27 +138,28 @@ impl EarlyLintPass for Formatting { /// Implementation of the `SUSPICIOUS_ASSIGNMENT_FORMATTING` lint. fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) { - if let ExprKind::Assign(ref lhs, ref rhs, _) = expr.kind { - if !lhs.span.from_expansion() && !rhs.span.from_expansion() { - let eq_span = lhs.span.between(rhs.span); - if let ExprKind::Unary(op, ref sub_rhs) = rhs.kind { - if let Some(eq_snippet) = snippet_opt(cx, eq_span) { - let op = op.as_str(); - let eqop_span = lhs.span.between(sub_rhs.span); - if eq_snippet.ends_with('=') { - span_lint_and_note( - cx, - SUSPICIOUS_ASSIGNMENT_FORMATTING, - eqop_span, - format!( - "this looks like you are trying to use `.. {op}= ..`, but you \ + if let ExprKind::Assign(ref lhs, ref rhs, _) = expr.kind + && !lhs.span.from_expansion() + && !rhs.span.from_expansion() + { + let eq_span = lhs.span.between(rhs.span); + if let ExprKind::Unary(op, ref sub_rhs) = rhs.kind + && let Some(eq_snippet) = snippet_opt(cx, eq_span) + { + let op = op.as_str(); + let eqop_span = lhs.span.between(sub_rhs.span); + if eq_snippet.ends_with('=') { + span_lint_and_note( + cx, + SUSPICIOUS_ASSIGNMENT_FORMATTING, + eqop_span, + format!( + "this looks like you are trying to use `.. {op}= ..`, but you \ really are doing `.. = ({op} ..)`" - ), - None, - format!("to remove this lint, use either `{op}=` or `= {op}`"), - ); - } - } + ), + None, + format!("to remove this lint, use either `{op}=` or `= {op}`"), + ); } } } diff --git a/clippy_lints/src/functions/too_many_arguments.rs b/clippy_lints/src/functions/too_many_arguments.rs index 05dc47f6fe580..48d050aa36aa0 100644 --- a/clippy_lints/src/functions/too_many_arguments.rs +++ b/clippy_lints/src/functions/too_many_arguments.rs @@ -47,16 +47,16 @@ pub(super) fn check_fn( } pub(super) fn check_trait_item(cx: &LateContext<'_>, item: &hir::TraitItem<'_>, too_many_arguments_threshold: u64) { - if let hir::TraitItemKind::Fn(ref sig, _) = item.kind { + if let hir::TraitItemKind::Fn(ref sig, _) = item.kind // don't lint extern functions decls, it's not their fault - if sig.header.abi == ExternAbi::Rust { - check_arg_number( - cx, - sig.decl, - item.span.with_hi(sig.decl.output.span().hi()), - too_many_arguments_threshold, - ); - } + && sig.header.abi == ExternAbi::Rust + { + check_arg_number( + cx, + sig.decl, + item.span.with_hi(sig.decl.output.span().hi()), + too_many_arguments_threshold, + ); } } diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 5f95464e4d494..ee141ddee15b0 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -153,18 +153,18 @@ fn lint_implicit_returns( ExprKind::Loop(block, ..) => { let mut add_return = false; let _: Option = for_each_expr_without_closures(block, |e| { - if let ExprKind::Break(dest, sub_expr) = e.kind { - if dest.target_id.ok() == Some(expr.hir_id) { - if call_site_span.is_none() && e.span.ctxt() == ctxt { - // At this point sub_expr can be `None` in async functions which either diverge, or return - // the unit type. - if let Some(sub_expr) = sub_expr { - lint_break(cx, e.hir_id, e.span, sub_expr.span); - } - } else { - // the break expression is from a macro call, add a return to the loop - add_return = true; + if let ExprKind::Break(dest, sub_expr) = e.kind + && dest.target_id.ok() == Some(expr.hir_id) + { + if call_site_span.is_none() && e.span.ctxt() == ctxt { + // At this point sub_expr can be `None` in async functions which either diverge, or return + // the unit type. + if let Some(sub_expr) = sub_expr { + lint_break(cx, e.hir_id, e.span, sub_expr.span); } + } else { + // the break expression is from a macro call, add a return to the loop + add_return = true; } } ControlFlow::Continue(()) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 33431385c7de3..be801d43a52bb 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -136,28 +136,28 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { let const_range = to_const_range(cx, range, size); - if let (Some(start), _) = const_range { - if start > size { - span_lint( - cx, - OUT_OF_BOUNDS_INDEXING, - range.start.map_or(expr.span, |start| start.span), - "range is out of bounds", - ); - return; - } + if let (Some(start), _) = const_range + && start > size + { + span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + range.start.map_or(expr.span, |start| start.span), + "range is out of bounds", + ); + return; } - if let (_, Some(end)) = const_range { - if end > size { - span_lint( - cx, - OUT_OF_BOUNDS_INDEXING, - range.end.map_or(expr.span, |end| end.span), - "range is out of bounds", - ); - return; - } + if let (_, Some(end)) = const_range + && end > size + { + span_lint( + cx, + OUT_OF_BOUNDS_INDEXING, + range.end.map_or(expr.span, |end| end.span), + "range is out of bounds", + ); + return; } if let (Some(_), Some(_)) = const_range { diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 960b9aa032bea..427a1f8255553 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -156,11 +156,12 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { .and(cap); } } - if method.ident.name.as_str() == "flat_map" && args.len() == 1 { - if let ExprKind::Closure(&Closure { body, .. }) = args[0].kind { - let body = cx.tcx.hir_body(body); - return is_infinite(cx, body.value); - } + if method.ident.name.as_str() == "flat_map" + && args.len() == 1 + && let ExprKind::Closure(&Closure { body, .. }) = args[0].kind + { + let body = cx.tcx.hir_body(body); + return is_infinite(cx, body.value); } Finite }, diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index fc575bff7e63f..67ce57de254d3 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -130,14 +130,14 @@ impl IntPlusOne { BinOpKind::Le => "<", _ => return None, }; - if let Some(snippet) = node.span.get_source_text(cx) { - if let Some(other_side_snippet) = other_side.span.get_source_text(cx) { - let rec = match side { - Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")), - Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")), - }; - return rec; - } + if let Some(snippet) = node.span.get_source_text(cx) + && let Some(other_side_snippet) = other_side.span.get_source_text(cx) + { + let rec = match side { + Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")), + Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")), + }; + return rec; } None } @@ -157,10 +157,10 @@ impl IntPlusOne { impl EarlyLintPass for IntPlusOne { fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) { - if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.kind { - if let Some(rec) = Self::check_binop(cx, kind.node, lhs, rhs) { - Self::emit_warning(cx, item, rec); - } + if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.kind + && let Some(rec) = Self::check_binop(cx, kind.node, lhs, rhs) + { + Self::emit_warning(cx, item, rec); } } } diff --git a/clippy_lints/src/invalid_upcast_comparisons.rs b/clippy_lints/src/invalid_upcast_comparisons.rs index b42664340d1c8..b0ecc5d52ddb8 100644 --- a/clippy_lints/src/invalid_upcast_comparisons.rs +++ b/clippy_lints/src/invalid_upcast_comparisons.rs @@ -91,49 +91,49 @@ fn upcast_comparison_bounds_err<'tcx>( rhs: &'tcx Expr<'_>, invert: bool, ) { - if let Some((lb, ub)) = lhs_bounds { - if let Some(norm_rhs_val) = ConstEvalCtxt::new(cx).eval_full_int(rhs) { - if rel == Rel::Eq || rel == Rel::Ne { - if norm_rhs_val < lb || norm_rhs_val > ub { - err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); - } - } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val < lb - } else { - ub < norm_rhs_val - } - }, - Rel::Le => { - if invert { - norm_rhs_val <= lb - } else { - ub <= norm_rhs_val - } - }, - Rel::Eq | Rel::Ne => unreachable!(), - } { - err_upcast_comparison(cx, span, lhs, true); - } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val >= ub - } else { - lb >= norm_rhs_val - } - }, - Rel::Le => { - if invert { - norm_rhs_val > ub - } else { - lb > norm_rhs_val - } - }, - Rel::Eq | Rel::Ne => unreachable!(), - } { - err_upcast_comparison(cx, span, lhs, false); + if let Some((lb, ub)) = lhs_bounds + && let Some(norm_rhs_val) = ConstEvalCtxt::new(cx).eval_full_int(rhs) + { + if rel == Rel::Eq || rel == Rel::Ne { + if norm_rhs_val < lb || norm_rhs_val > ub { + err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); } + } else if match rel { + Rel::Lt => { + if invert { + norm_rhs_val < lb + } else { + ub < norm_rhs_val + } + }, + Rel::Le => { + if invert { + norm_rhs_val <= lb + } else { + ub <= norm_rhs_val + } + }, + Rel::Eq | Rel::Ne => unreachable!(), + } { + err_upcast_comparison(cx, span, lhs, true); + } else if match rel { + Rel::Lt => { + if invert { + norm_rhs_val >= ub + } else { + lb >= norm_rhs_val + } + }, + Rel::Le => { + if invert { + norm_rhs_val > ub + } else { + lb > norm_rhs_val + } + }, + Rel::Eq | Rel::Ne => unreachable!(), + } { + err_upcast_comparison(cx, span, lhs, false); } } } diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs index 0f800a68cdbf4..b1271a264b548 100644 --- a/clippy_lints/src/item_name_repetitions.rs +++ b/clippy_lints/src/item_name_repetitions.rs @@ -444,57 +444,56 @@ impl LateLintPass<'_> for ItemNameRepetitions { let item_name = ident.name.as_str(); let item_camel = to_camel_case(item_name); - if !item.span.from_expansion() && is_present_in_source(cx, item.span) { - if let [.., (mod_name, mod_camel, mod_owner_id)] = &*self.modules { - // constants don't have surrounding modules - if !mod_camel.is_empty() { - if mod_name == &ident.name - && let ItemKind::Mod(..) = item.kind - && (!self.allow_private_module_inception || cx.tcx.visibility(mod_owner_id.def_id).is_public()) - { - span_lint( - cx, - MODULE_INCEPTION, - item.span, - "module has the same name as its containing module", - ); - } + if !item.span.from_expansion() && is_present_in_source(cx, item.span) + && let [.., (mod_name, mod_camel, mod_owner_id)] = &*self.modules + // constants don't have surrounding modules + && !mod_camel.is_empty() + { + if mod_name == &ident.name + && let ItemKind::Mod(..) = item.kind + && (!self.allow_private_module_inception || cx.tcx.visibility(mod_owner_id.def_id).is_public()) + { + span_lint( + cx, + MODULE_INCEPTION, + item.span, + "module has the same name as its containing module", + ); + } - // The `module_name_repetitions` lint should only trigger if the item has the module in its - // name. Having the same name is accepted. - if cx.tcx.visibility(item.owner_id).is_public() - && cx.tcx.visibility(mod_owner_id.def_id).is_public() - && item_camel.len() > mod_camel.len() - { - let matching = count_match_start(mod_camel, &item_camel); - let rmatching = count_match_end(mod_camel, &item_camel); - let nchars = mod_camel.chars().count(); - - let is_word_beginning = |c: char| c == '_' || c.is_uppercase() || c.is_numeric(); - - if matching.char_count == nchars { - match item_camel.chars().nth(nchars) { - Some(c) if is_word_beginning(c) => span_lint( - cx, - MODULE_NAME_REPETITIONS, - ident.span, - "item name starts with its containing module's name", - ), - _ => (), - } - } - if rmatching.char_count == nchars - && !self.is_allowed_prefix(&item_camel[..item_camel.len() - rmatching.byte_count]) - { - span_lint( - cx, - MODULE_NAME_REPETITIONS, - ident.span, - "item name ends with its containing module's name", - ); - } + // The `module_name_repetitions` lint should only trigger if the item has the module in its + // name. Having the same name is accepted. + if cx.tcx.visibility(item.owner_id).is_public() + && cx.tcx.visibility(mod_owner_id.def_id).is_public() + && item_camel.len() > mod_camel.len() + { + let matching = count_match_start(mod_camel, &item_camel); + let rmatching = count_match_end(mod_camel, &item_camel); + let nchars = mod_camel.chars().count(); + + let is_word_beginning = |c: char| c == '_' || c.is_uppercase() || c.is_numeric(); + + if matching.char_count == nchars { + match item_camel.chars().nth(nchars) { + Some(c) if is_word_beginning(c) => span_lint( + cx, + MODULE_NAME_REPETITIONS, + ident.span, + "item name starts with its containing module's name", + ), + _ => (), } } + if rmatching.char_count == nchars + && !self.is_allowed_prefix(&item_camel[..item_camel.len() - rmatching.byte_count]) + { + span_lint( + cx, + MODULE_NAME_REPETITIONS, + ident.span, + "item name ends with its containing module's name", + ); + } } } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 15c44381debbe..5a86045789a87 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -523,10 +523,10 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_> if let (&ExprKind::MethodCall(method_path, receiver, [], _), ExprKind::Lit(lit)) = (&method.kind, &lit.kind) { // check if we are in an is_empty() method - if let Some(name) = get_item_name(cx, method) { - if name.as_str() == "is_empty" { - return; - } + if let Some(name) = get_item_name(cx, method) + && name.as_str() == "is_empty" + { + return; } check_len(cx, span, method_path.ident.name, receiver, &lit.node, op, compare_to); @@ -588,11 +588,11 @@ fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Ex } fn is_empty_string(expr: &Expr<'_>) -> bool { - if let ExprKind::Lit(lit) = expr.kind { - if let LitKind::Str(lit, _) = lit.node { - let lit = lit.as_str(); - return lit.is_empty(); - } + if let ExprKind::Lit(lit) = expr.kind + && let LitKind::Str(lit, _) = lit.node + { + let lit = lit.as_str(); + return lit.is_empty(); } false } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 3dd2de1fafc72..1769fa53865f0 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -150,10 +150,10 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { } = item.kind { check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, self.msrv); - } else if let ItemKind::Impl(impl_) = item.kind { - if !item.span.from_expansion() { - report_extra_impl_lifetimes(cx, impl_); - } + } else if let ItemKind::Impl(impl_) = item.kind + && !item.span.from_expansion() + { + report_extra_impl_lifetimes(cx, impl_); } } diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 805de23408bf5..7cbfa2d097ae5 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -387,12 +387,11 @@ impl LiteralDigitGrouping { let first = groups.next().expect("At least one group"); - if radix == Radix::Binary || radix == Radix::Octal || radix == Radix::Hexadecimal { - if let Some(second_size) = groups.next() { - if !groups.all(|i| i == second_size) || first > second_size { - return Err(WarningType::UnusualByteGroupings); - } - } + if (radix == Radix::Binary || radix == Radix::Octal || radix == Radix::Hexadecimal) + && let Some(second_size) = groups.next() + && (!groups.all(|i| i == second_size) || first > second_size) + { + return Err(WarningType::UnusualByteGroupings); } if let Some(second) = groups.next() { diff --git a/clippy_lints/src/literal_string_with_formatting_args.rs b/clippy_lints/src/literal_string_with_formatting_args.rs index 975e6833a35f8..244e7c95122e0 100644 --- a/clippy_lints/src/literal_string_with_formatting_args.rs +++ b/clippy_lints/src/literal_string_with_formatting_args.rs @@ -45,15 +45,14 @@ fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, spans: &[(Span, Option(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>) { let pat_span = pat.span; - if let PatKind::Tuple(pat, _) = pat.kind { - if pat.len() == 2 { - let arg_span = arg.span; - let (new_pat_span, kind, ty, mutbl) = match *cx.typeck_results().expr_ty(arg).kind() { - ty::Ref(_, ty, mutbl) => match (&pat[0].kind, &pat[1].kind) { - (key, _) if pat_is_wild(cx, key, body) => (pat[1].span, "value", ty, mutbl), - (_, value) if pat_is_wild(cx, value, body) => (pat[0].span, "key", ty, Mutability::Not), - _ => return, - }, + if let PatKind::Tuple(pat, _) = pat.kind + && pat.len() == 2 + { + let arg_span = arg.span; + let (new_pat_span, kind, ty, mutbl) = match *cx.typeck_results().expr_ty(arg).kind() { + ty::Ref(_, ty, mutbl) => match (&pat[0].kind, &pat[1].kind) { + (key, _) if pat_is_wild(cx, key, body) => (pat[1].span, "value", ty, mutbl), + (_, value) if pat_is_wild(cx, value, body) => (pat[0].span, "key", ty, Mutability::Not), _ => return, - }; - let mutbl = match mutbl { - Mutability::Not => "", - Mutability::Mut => "_mut", - }; - let arg = match arg.kind { - ExprKind::AddrOf(BorrowKind::Ref, _, expr) => expr, - _ => arg, - }; + }, + _ => return, + }; + let mutbl = match mutbl { + Mutability::Not => "", + Mutability::Mut => "_mut", + }; + let arg = match arg.kind { + ExprKind::AddrOf(BorrowKind::Ref, _, expr) => expr, + _ => arg, + }; - if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap) { - span_lint_and_then( - cx, - FOR_KV_MAP, - arg_span, - format!("you seem to want to iterate on a map's {kind}s"), - |diag| { - let map = sugg::Sugg::hir(cx, arg, "map"); - diag.multipart_suggestion( - "use the corresponding method", - vec![ - (pat_span, snippet(cx, new_pat_span, kind).into_owned()), - (arg_span, format!("{}.{kind}s{mutbl}()", map.maybe_paren())), - ], - Applicability::MachineApplicable, - ); - }, - ); - } + if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap) { + span_lint_and_then( + cx, + FOR_KV_MAP, + arg_span, + format!("you seem to want to iterate on a map's {kind}s"), + |diag| { + let map = sugg::Sugg::hir(cx, arg, "map"); + diag.multipart_suggestion( + "use the corresponding method", + vec![ + (pat_span, snippet(cx, new_pat_span, kind).into_owned()), + (arg_span, format!("{}.{kind}s{mutbl}()", map.maybe_paren())), + ], + Applicability::MachineApplicable, + ); + }, + ); } } } diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs index 39af596878178..d9c4b526da99e 100644 --- a/clippy_lints/src/loops/manual_memcpy.rs +++ b/clippy_lints/src/loops/manual_memcpy.rs @@ -28,37 +28,37 @@ pub(super) fn check<'tcx>( end: Some(end), limits, }) = higher::Range::hir(arg) - { // the var must be a single name - if let PatKind::Binding(_, canonical_id, _, _) = pat.kind { - let mut starts = vec![Start { - id: canonical_id, - kind: StartKind::Range, - }]; - - // This is one of few ways to return different iterators - // derived from: https://stackoverflow.com/questions/29760668/conditionally-iterate-over-one-of-several-possible-iterators/52064434#52064434 - let mut iter_a = None; - let mut iter_b = None; - - if let ExprKind::Block(block, _) = body.kind { - if let Some(loop_counters) = get_loop_counters(cx, block, expr) { - starts.extend(loop_counters); - } - iter_a = Some(get_assignments(block, &starts)); - } else { - iter_b = Some(get_assignment(body)); + && let PatKind::Binding(_, canonical_id, _, _) = pat.kind + { + let mut starts = vec![Start { + id: canonical_id, + kind: StartKind::Range, + }]; + + // This is one of few ways to return different iterators + // derived from: https://stackoverflow.com/questions/29760668/conditionally-iterate-over-one-of-several-possible-iterators/52064434#52064434 + let mut iter_a = None; + let mut iter_b = None; + + if let ExprKind::Block(block, _) = body.kind { + if let Some(loop_counters) = get_loop_counters(cx, block, expr) { + starts.extend(loop_counters); } + iter_a = Some(get_assignments(block, &starts)); + } else { + iter_b = Some(get_assignment(body)); + } - let assignments = iter_a.into_iter().flatten().chain(iter_b); + let assignments = iter_a.into_iter().flatten().chain(iter_b); - let big_sugg = assignments - // The only statements in the for loops can be indexed assignments from - // indexed retrievals (except increments of loop counters). - .map(|o| { - o.and_then(|(lhs, rhs)| { - let rhs = fetch_cloned_expr(rhs); - if let ExprKind::Index(base_left, idx_left, _) = lhs.kind + let big_sugg = assignments + // The only statements in the for loops can be indexed assignments from + // indexed retrievals (except increments of loop counters). + .map(|o| { + o.and_then(|(lhs, rhs)| { + let rhs = fetch_cloned_expr(rhs); + if let ExprKind::Index(base_left, idx_left, _) = lhs.kind && let ExprKind::Index(base_right, idx_right, _) = rhs.kind && let Some(ty) = get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_left)) && get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_right)).is_some() @@ -68,42 +68,41 @@ pub(super) fn check<'tcx>( && !local_used_in(cx, canonical_id, base_right) // Source and destination must be different && path_to_local(base_left) != path_to_local(base_right) - { - Some(( - ty, - IndexExpr { - base: base_left, - idx: start_left, - idx_offset: offset_left, - }, - IndexExpr { - base: base_right, - idx: start_right, - idx_offset: offset_right, - }, - )) - } else { - None - } - }) + { + Some(( + ty, + IndexExpr { + base: base_left, + idx: start_left, + idx_offset: offset_left, + }, + IndexExpr { + base: base_right, + idx: start_right, + idx_offset: offset_right, + }, + )) + } else { + None + } }) - .map(|o| o.map(|(ty, dst, src)| build_manual_memcpy_suggestion(cx, start, end, limits, ty, &dst, &src))) - .collect::>>() - .filter(|v| !v.is_empty()) - .map(|v| v.join("\n ")); - - if let Some(big_sugg) = big_sugg { - span_lint_and_sugg( - cx, - MANUAL_MEMCPY, - expr.span, - "it looks like you're manually copying between slices", - "try replacing the loop by", - big_sugg, - Applicability::Unspecified, - ); - return true; - } + }) + .map(|o| o.map(|(ty, dst, src)| build_manual_memcpy_suggestion(cx, start, end, limits, ty, &dst, &src))) + .collect::>>() + .filter(|v| !v.is_empty()) + .map(|v| v.join("\n ")); + + if let Some(big_sugg) = big_sugg { + span_lint_and_sugg( + cx, + MANUAL_MEMCPY, + expr.span, + "it looks like you're manually copying between slices", + "try replacing the loop by", + big_sugg, + Applicability::Unspecified, + ); + return true; } } false diff --git a/clippy_lints/src/loops/manual_while_let_some.rs b/clippy_lints/src/loops/manual_while_let_some.rs index 4473a3343c7c6..9527e258db8ab 100644 --- a/clippy_lints/src/loops/manual_while_let_some.rs +++ b/clippy_lints/src/loops/manual_while_let_some.rs @@ -81,15 +81,15 @@ fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, } fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) { - if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = stmt.kind { - if let ExprKind::MethodCall(.., args, _) | ExprKind::Call(_, args) = expr.kind { - let offending_arg = args - .iter() - .find_map(|arg| is_vec_pop_unwrap(cx, arg, is_empty_recv).then_some(arg.span)); + if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = stmt.kind + && let ExprKind::MethodCall(.., args, _) | ExprKind::Call(_, args) = expr.kind + { + let offending_arg = args + .iter() + .find_map(|arg| is_vec_pop_unwrap(cx, arg, is_empty_recv).then_some(arg.span)); - if let Some(offending_arg) = offending_arg { - report_lint(cx, offending_arg, PopStmt::Anonymous, loop_span, is_empty_recv.span); - } + if let Some(offending_arg) = offending_arg { + report_lint(cx, offending_arg, PopStmt::Anonymous, loop_span, is_empty_recv.span); } } } diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs index 5afcf51167d47..3130a7f0c1a79 100644 --- a/clippy_lints/src/loops/mut_range_bound.rs +++ b/clippy_lints/src/loops/mut_range_bound.rs @@ -82,14 +82,14 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> { fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) { - if bk == ty::BorrowKind::Mutable { - if let PlaceBase::Local(id) = cmt.place.base { - if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) { - self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id)); - } - if Some(id) == self.hir_id_high && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) { - self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id)); - } + if bk == ty::BorrowKind::Mutable + && let PlaceBase::Local(id) = cmt.place.base + { + if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) { + self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id)); + } + if Some(id) == self.hir_id_high && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) { + self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id)); } } } diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs index 0f62183eb33d6..7837b18bcd36c 100644 --- a/clippy_lints/src/loops/needless_range_loop.rs +++ b/clippy_lints/src/loops/needless_range_loop.rs @@ -31,155 +31,154 @@ pub(super) fn check<'tcx>( ref end, limits, }) = higher::Range::hir(arg) - { // the var must be a single name - if let PatKind::Binding(_, canonical_id, ident, _) = pat.kind { - let mut visitor = VarVisitor { - cx, - var: canonical_id, - indexed_mut: FxHashSet::default(), - indexed_indirectly: FxHashMap::default(), - indexed_directly: FxIndexMap::default(), - referenced: FxHashSet::default(), - nonindex: false, - prefer_mutable: false, - }; - walk_expr(&mut visitor, body); - - // linting condition: we only indexed one variable, and indexed it directly - if visitor.indexed_indirectly.is_empty() && visitor.indexed_directly.len() == 1 { - let (indexed, (indexed_extent, indexed_ty)) = visitor - .indexed_directly - .into_iter() - .next() - .expect("already checked that we have exactly 1 element"); + && let PatKind::Binding(_, canonical_id, ident, _) = pat.kind + { + let mut visitor = VarVisitor { + cx, + var: canonical_id, + indexed_mut: FxHashSet::default(), + indexed_indirectly: FxHashMap::default(), + indexed_directly: FxIndexMap::default(), + referenced: FxHashSet::default(), + nonindex: false, + prefer_mutable: false, + }; + walk_expr(&mut visitor, body); - // ensure that the indexed variable was declared before the loop, see #601 - if let Some(indexed_extent) = indexed_extent { - let parent_def_id = cx.tcx.hir_get_parent_item(expr.hir_id); - let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id); - let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id).unwrap(); - if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) { - return; - } - } + // linting condition: we only indexed one variable, and indexed it directly + if visitor.indexed_indirectly.is_empty() && visitor.indexed_directly.len() == 1 { + let (indexed, (indexed_extent, indexed_ty)) = visitor + .indexed_directly + .into_iter() + .next() + .expect("already checked that we have exactly 1 element"); - // don't lint if the container that is indexed does not have .iter() method - let has_iter = has_iter_method(cx, indexed_ty); - if has_iter.is_none() { + // ensure that the indexed variable was declared before the loop, see #601 + if let Some(indexed_extent) = indexed_extent { + let parent_def_id = cx.tcx.hir_get_parent_item(expr.hir_id); + let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id); + let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id).unwrap(); + if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) { return; } + } - // don't lint if the container that is indexed into is also used without - // indexing - if visitor.referenced.contains(&indexed) { - return; - } + // don't lint if the container that is indexed does not have .iter() method + let has_iter = has_iter_method(cx, indexed_ty); + if has_iter.is_none() { + return; + } - let starts_at_zero = is_integer_const(cx, start, 0); + // don't lint if the container that is indexed into is also used without + // indexing + if visitor.referenced.contains(&indexed) { + return; + } - let skip = if starts_at_zero { - String::new() - } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start, cx) { - return; - } else { - format!(".skip({})", snippet(cx, start.span, "..")) - }; + let starts_at_zero = is_integer_const(cx, start, 0); - let mut end_is_start_plus_val = false; + let skip = if starts_at_zero { + String::new() + } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start, cx) { + return; + } else { + format!(".skip({})", snippet(cx, start.span, "..")) + }; - let take = if let Some(end) = *end { - let mut take_expr = end; + let mut end_is_start_plus_val = false; - if let ExprKind::Binary(ref op, left, right) = end.kind { - if op.node == BinOpKind::Add { - let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left); - let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right); + let take = if let Some(end) = *end { + let mut take_expr = end; - if start_equal_left { - take_expr = right; - } else if start_equal_right { - take_expr = left; - } + if let ExprKind::Binary(ref op, left, right) = end.kind + && op.node == BinOpKind::Add + { + let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left); + let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right); - end_is_start_plus_val = start_equal_left | start_equal_right; - } + if start_equal_left { + take_expr = right; + } else if start_equal_right { + take_expr = left; } - if is_len_call(end, indexed) || is_end_eq_array_len(cx, end, limits, indexed_ty) { - String::new() - } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr, cx) { - return; - } else { - match limits { - ast::RangeLimits::Closed => { - let take_expr = sugg::Sugg::hir(cx, take_expr, ""); - format!(".take({})", take_expr + sugg::ONE) - }, - ast::RangeLimits::HalfOpen => { - format!(".take({})", snippet(cx, take_expr.span, "..")) - }, - } - } - } else { - String::new() - }; + end_is_start_plus_val = start_equal_left | start_equal_right; + } - let (ref_mut, method) = if visitor.indexed_mut.contains(&indexed) { - ("mut ", "iter_mut") + if is_len_call(end, indexed) || is_end_eq_array_len(cx, end, limits, indexed_ty) { + String::new() + } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr, cx) { + return; } else { - ("", "iter") - }; + match limits { + ast::RangeLimits::Closed => { + let take_expr = sugg::Sugg::hir(cx, take_expr, ""); + format!(".take({})", take_expr + sugg::ONE) + }, + ast::RangeLimits::HalfOpen => { + format!(".take({})", snippet(cx, take_expr.span, "..")) + }, + } + } + } else { + String::new() + }; - let take_is_empty = take.is_empty(); - let mut method_1 = take; - let mut method_2 = skip; + let (ref_mut, method) = if visitor.indexed_mut.contains(&indexed) { + ("mut ", "iter_mut") + } else { + ("", "iter") + }; - if end_is_start_plus_val { - mem::swap(&mut method_1, &mut method_2); - } + let take_is_empty = take.is_empty(); + let mut method_1 = take; + let mut method_2 = skip; - if visitor.nonindex { - span_lint_and_then( - cx, - NEEDLESS_RANGE_LOOP, - arg.span, - format!("the loop variable `{}` is used to index `{indexed}`", ident.name), - |diag| { - diag.multipart_suggestion( - "consider using an iterator and enumerate()", - vec![ - (pat.span, format!("({}, )", ident.name)), - ( - arg.span, - format!("{indexed}.{method}().enumerate(){method_1}{method_2}"), - ), - ], - Applicability::HasPlaceholders, - ); - }, - ); + if end_is_start_plus_val { + mem::swap(&mut method_1, &mut method_2); + } + + if visitor.nonindex { + span_lint_and_then( + cx, + NEEDLESS_RANGE_LOOP, + arg.span, + format!("the loop variable `{}` is used to index `{indexed}`", ident.name), + |diag| { + diag.multipart_suggestion( + "consider using an iterator and enumerate()", + vec![ + (pat.span, format!("({}, )", ident.name)), + ( + arg.span, + format!("{indexed}.{method}().enumerate(){method_1}{method_2}"), + ), + ], + Applicability::HasPlaceholders, + ); + }, + ); + } else { + let repl = if starts_at_zero && take_is_empty { + format!("&{ref_mut}{indexed}") } else { - let repl = if starts_at_zero && take_is_empty { - format!("&{ref_mut}{indexed}") - } else { - format!("{indexed}.{method}(){method_1}{method_2}") - }; + format!("{indexed}.{method}(){method_1}{method_2}") + }; - span_lint_and_then( - cx, - NEEDLESS_RANGE_LOOP, - arg.span, - format!("the loop variable `{}` is only used to index `{indexed}`", ident.name), - |diag| { - diag.multipart_suggestion( - "consider using an iterator", - vec![(pat.span, "".to_string()), (arg.span, repl)], - Applicability::HasPlaceholders, - ); - }, - ); - } + span_lint_and_then( + cx, + NEEDLESS_RANGE_LOOP, + arg.span, + format!("the loop variable `{}` is only used to index `{indexed}`", ident.name), + |diag| { + diag.multipart_suggestion( + "consider using an iterator", + vec![(pat.span, "".to_string()), (arg.span, repl)], + Applicability::HasPlaceholders, + ); + }, + ); } } } @@ -346,10 +345,10 @@ impl<'tcx> Visitor<'tcx> for VarVisitor<'_, 'tcx> { for expr in args { let ty = self.cx.typeck_results().expr_ty_adjusted(expr); self.prefer_mutable = false; - if let ty::Ref(_, _, mutbl) = *ty.kind() { - if mutbl == Mutability::Mut { - self.prefer_mutable = true; - } + if let ty::Ref(_, _, mutbl) = *ty.kind() + && mutbl == Mutability::Mut + { + self.prefer_mutable = true; } self.visit_expr(expr); } @@ -361,10 +360,10 @@ impl<'tcx> Visitor<'tcx> for VarVisitor<'_, 'tcx> { iter::once(receiver).chain(args.iter()), ) { self.prefer_mutable = false; - if let ty::Ref(_, _, mutbl) = *ty.kind() { - if mutbl == Mutability::Mut { - self.prefer_mutable = true; - } + if let ty::Ref(_, _, mutbl) = *ty.kind() + && mutbl == Mutability::Mut + { + self.prefer_mutable = true; } self.visit_expr(expr); } diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index c3a2a38b5ec25..69c84bc7038ef 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -244,10 +244,10 @@ fn never_loop_expr<'tcx>( }); combine_seq(first, || { // checks if break targets a block instead of a loop - if let ExprKind::Break(Destination { target_id: Ok(t), .. }, _) = expr.kind { - if let Some((_, reachable)) = local_labels.iter_mut().find(|(label, _)| *label == t) { - *reachable = true; - } + if let ExprKind::Break(Destination { target_id: Ok(t), .. }, _) = expr.kind + && let Some((_, reachable)) = local_labels.iter_mut().find(|(label, _)| *label == t) + { + *reachable = true; } NeverLoopResult::Diverging }) diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs index 16dd1ad4e4784..98e8b1f5cf92c 100644 --- a/clippy_lints/src/manual_retain.rs +++ b/clippy_lints/src/manual_retain.rs @@ -92,10 +92,10 @@ fn check_into_iter( && let [filter_params] = filter_body.params { if match_map_type(cx, left_expr) { - if let hir::PatKind::Tuple([key_pat, value_pat], _) = filter_params.pat.kind { - if let Some(sugg) = make_sugg(cx, key_pat, value_pat, left_expr, filter_body) { - make_span_lint_and_sugg(cx, parent_expr_span, sugg); - } + if let hir::PatKind::Tuple([key_pat, value_pat], _) = filter_params.pat.kind + && let Some(sugg) = make_sugg(cx, key_pat, value_pat, left_expr, filter_body) + { + make_span_lint_and_sugg(cx, parent_expr_span, sugg); } // Cannot lint other cases because `retain` requires two parameters } else { @@ -196,22 +196,21 @@ fn check_to_owned( && let filter_body = cx.tcx.hir_body(closure.body) && let [filter_params] = filter_body.params && msrv.meets(cx, msrvs::STRING_RETAIN) + && let hir::PatKind::Ref(pat, _) = filter_params.pat.kind { - if let hir::PatKind::Ref(pat, _) = filter_params.pat.kind { - make_span_lint_and_sugg( - cx, - parent_expr_span, - format!( - "{}.retain(|{}| {})", - snippet(cx, left_expr.span, ".."), - snippet(cx, pat.span, ".."), - snippet(cx, filter_body.value.span, "..") - ), - ); - } - // Be conservative now. Do nothing for the `Binding` case. - // TODO: Ideally, we can rewrite the lambda by stripping one level of reference + make_span_lint_and_sugg( + cx, + parent_expr_span, + format!( + "{}.retain(|{}| {})", + snippet(cx, left_expr.span, ".."), + snippet(cx, pat.span, ".."), + snippet(cx, filter_body.value.span, "..") + ), + ); } + // Be conservative now. Do nothing for the `Binding` case. + // TODO: Ideally, we can rewrite the lambda by stripping one level of reference } fn make_sugg( diff --git a/clippy_lints/src/manual_string_new.rs b/clippy_lints/src/manual_string_new.rs index 5c2a711b5cb23..7ca3b71206671 100644 --- a/clippy_lints/src/manual_string_new.rs +++ b/clippy_lints/src/manual_string_new.rs @@ -113,15 +113,14 @@ fn parse_call(cx: &LateContext<'_>, span: Span, func: &Expr<'_>, arg: &Expr<'_>) && is_expr_kind_empty_str(&arg.kind) { warn_then_suggest(cx, span); - } else if let QPath::Resolved(_, path) = qpath { + } else if let QPath::Resolved(_, path) = qpath // From::from(...) or TryFrom::try_from(...) - if let [path_seg1, path_seg2] = path.segments - && is_expr_kind_empty_str(&arg.kind) - && ((path_seg1.ident.name == sym::From && path_seg2.ident.name == sym::from) - || (path_seg1.ident.name == sym::TryFrom && path_seg2.ident.name == sym::try_from)) - { - warn_then_suggest(cx, span); - } + && let [path_seg1, path_seg2] = path.segments + && is_expr_kind_empty_str(&arg.kind) + && ((path_seg1.ident.name == sym::From && path_seg2.ident.name == sym::from) + || (path_seg1.ident.name == sym::TryFrom && path_seg2.ident.name == sym::try_from)) + { + warn_then_suggest(cx, span); } } } diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 56aead85e7c41..b607f8117eb89 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -101,10 +101,10 @@ fn is_unit_type(ty: Ty<'_>) -> bool { fn is_unit_function(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { let ty = cx.typeck_results().expr_ty(expr); - if let ty::FnDef(id, _) = *ty.kind() { - if let Some(fn_type) = cx.tcx.fn_sig(id).instantiate_identity().no_bound_vars() { - return is_unit_type(fn_type.output()); - } + if let ty::FnDef(id, _) = *ty.kind() + && let Some(fn_type) = cx.tcx.fn_sig(id).instantiate_identity().no_bound_vars() + { + return is_unit_type(fn_type.output()); } false } diff --git a/clippy_lints/src/matches/manual_filter.rs b/clippy_lints/src/matches/manual_filter.rs index 4cc43e427ec61..abf723fa6f4ca 100644 --- a/clippy_lints/src/matches/manual_filter.rs +++ b/clippy_lints/src/matches/manual_filter.rs @@ -41,10 +41,10 @@ fn get_cond_expr<'tcx>( fn peels_blocks_incl_unsafe_opt<'a>(expr: &'a Expr<'a>) -> Option<&'a Expr<'a>> { // we don't want to use `peel_blocks` here because we don't care if the block is unsafe, it's // checked by `contains_unsafe_block` - if let ExprKind::Block(block, None) = expr.kind { - if block.stmts.is_empty() { - return block.expr; - } + if let ExprKind::Block(block, None) = expr.kind + && block.stmts.is_empty() + { + return block.expr; } None } @@ -61,13 +61,13 @@ fn peels_blocks_incl_unsafe<'a>(expr: &'a Expr<'a>) -> &'a Expr<'a> { // } // Returns true if resolves to `Some(x)`, `false` otherwise fn is_some_expr(cx: &LateContext<'_>, target: HirId, ctxt: SyntaxContext, expr: &Expr<'_>) -> bool { - if let Some(inner_expr) = peels_blocks_incl_unsafe_opt(expr) { + if let Some(inner_expr) = peels_blocks_incl_unsafe_opt(expr) // there can be not statements in the block as they would be removed when switching to `.filter` - if let ExprKind::Call(callee, [arg]) = inner_expr.kind { - return ctxt == expr.span.ctxt() - && is_res_lang_ctor(cx, path_res(cx, callee), OptionSome) - && path_to_local_id(arg, target); - } + && let ExprKind::Call(callee, [arg]) = inner_expr.kind + { + return ctxt == expr.span.ctxt() + && is_res_lang_ctor(cx, path_res(cx, callee), OptionSome) + && path_to_local_id(arg, target); } false } diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs index d29d1ea3e96d9..f14b69d91ce4b 100644 --- a/clippy_lints/src/matches/match_like_matches.rs +++ b/clippy_lints/src/matches/match_like_matches.rs @@ -76,17 +76,18 @@ where && first_attrs.is_empty() && iter.all(|arm| find_bool_lit(&arm.2.kind).is_some_and(|b| b == b0) && arm.3.is_none() && arm.0.is_empty()) { - if let Some(last_pat) = last_pat_opt { - if !is_wild(last_pat) { - return false; - } + if let Some(last_pat) = last_pat_opt + && !is_wild(last_pat) + { + return false; } for arm in iter_without_last.clone() { - if let Some(pat) = arm.1 { - if !is_lint_allowed(cx, REDUNDANT_PATTERN_MATCHING, pat.hir_id) && is_some(pat.kind) { - return false; - } + if let Some(pat) = arm.1 + && !is_lint_allowed(cx, REDUNDANT_PATTERN_MATCHING, pat.hir_id) + && is_some(pat.kind) + { + return false; } } @@ -113,10 +114,10 @@ where // strip potential borrows (#6503), but only if the type is a reference let mut ex_new = ex; - if let ExprKind::AddrOf(BorrowKind::Ref, .., ex_inner) = ex.kind { - if let ty::Ref(..) = cx.typeck_results().expr_ty(ex_inner).kind() { - ex_new = ex_inner; - } + if let ExprKind::AddrOf(BorrowKind::Ref, .., ex_inner) = ex.kind + && let ty::Ref(..) = cx.typeck_results().expr_ty(ex_inner).kind() + { + ex_new = ex_inner; } span_lint_and_sugg( cx, diff --git a/clippy_lints/src/matches/match_single_binding.rs b/clippy_lints/src/matches/match_single_binding.rs index 864923b27739d..bca41956f1cad 100644 --- a/clippy_lints/src/matches/match_single_binding.rs +++ b/clippy_lints/src/matches/match_single_binding.rs @@ -178,24 +178,24 @@ fn sugg_with_curlies<'a>( let mut indent = " ".repeat(indent_of(cx, ex.span).unwrap_or(0)); let (mut cbrace_start, mut cbrace_end) = (String::new(), String::new()); - if let Some(parent_expr) = get_parent_expr(cx, match_expr) { - if let ExprKind::Closure { .. } = parent_expr.kind { - cbrace_end = format!("\n{indent}}}"); - // Fix body indent due to the closure - indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0)); - cbrace_start = format!("{{\n{indent}"); - } + if let Some(parent_expr) = get_parent_expr(cx, match_expr) + && let ExprKind::Closure { .. } = parent_expr.kind + { + cbrace_end = format!("\n{indent}}}"); + // Fix body indent due to the closure + indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0)); + cbrace_start = format!("{{\n{indent}"); } // If the parent is already an arm, and the body is another match statement, // we need curly braces around suggestion - if let Node::Arm(arm) = &cx.tcx.parent_hir_node(match_expr.hir_id) { - if let ExprKind::Match(..) = arm.body.kind { - cbrace_end = format!("\n{indent}}}"); - // Fix body indent due to the match - indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0)); - cbrace_start = format!("{{\n{indent}"); - } + if let Node::Arm(arm) = &cx.tcx.parent_hir_node(match_expr.hir_id) + && let ExprKind::Match(..) = arm.body.kind + { + cbrace_end = format!("\n{indent}}}"); + // Fix body indent due to the match + indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0)); + cbrace_start = format!("{{\n{indent}"); } let assignment_str = assignment.map_or_else(String::new, |span| { diff --git a/clippy_lints/src/matches/match_str_case_mismatch.rs b/clippy_lints/src/matches/match_str_case_mismatch.rs index df1b83cbb516a..65b93a095b926 100644 --- a/clippy_lints/src/matches/match_str_case_mismatch.rs +++ b/clippy_lints/src/matches/match_str_case_mismatch.rs @@ -26,10 +26,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>, arm && let ty::Str = ty.kind() { let mut visitor = MatchExprVisitor { cx }; - if let ControlFlow::Break(case_method) = visitor.visit_expr(scrutinee) { - if let Some((bad_case_span, bad_case_sym)) = verify_case(&case_method, arms) { - lint(cx, &case_method, bad_case_span, bad_case_sym.as_str()); - } + if let ControlFlow::Break(case_method) = visitor.visit_expr(scrutinee) + && let Some((bad_case_span, bad_case_sym)) = verify_case(&case_method, arms) + { + lint(cx, &case_method, bad_case_span, bad_case_sym.as_str()); } } } diff --git a/clippy_lints/src/matches/match_wild_enum.rs b/clippy_lints/src/matches/match_wild_enum.rs index 11b588b33554d..24b4a6758004f 100644 --- a/clippy_lints/src/matches/match_wild_enum.rs +++ b/clippy_lints/src/matches/match_wild_enum.rs @@ -80,18 +80,20 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { path }, PatKind::TupleStruct(path, patterns, ..) => { - if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() { - if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p)) { - missing_variants.retain(|e| e.ctor_def_id() != Some(id)); - } + if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() + && arm.guard.is_none() + && patterns.iter().all(|p| !is_refutable(cx, p)) + { + missing_variants.retain(|e| e.ctor_def_id() != Some(id)); } path }, PatKind::Struct(path, patterns, ..) => { - if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() { - if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p.pat)) { - missing_variants.retain(|e| e.def_id != id); - } + if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() + && arm.guard.is_none() + && patterns.iter().all(|p| !is_refutable(cx, p.pat)) + { + missing_variants.retain(|e| e.def_id != id); } path }, diff --git a/clippy_lints/src/matches/match_wild_err_arm.rs b/clippy_lints/src/matches/match_wild_err_arm.rs index d0d2025878e48..8ce8453360f78 100644 --- a/clippy_lints/src/matches/match_wild_err_arm.rs +++ b/clippy_lints/src/matches/match_wild_err_arm.rs @@ -26,11 +26,12 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<' if !matching_wild { // Looking for unused bindings (i.e.: `_e`) for pat in inner { - if let PatKind::Binding(_, id, ident, None) = pat.kind { - if ident.as_str().starts_with('_') && !is_local_used(cx, arm.body, id) { - ident_bind_name = ident.name; - matching_wild = true; - } + if let PatKind::Binding(_, id, ident, None) = pat.kind + && ident.as_str().starts_with('_') + && !is_local_used(cx, arm.body, id) + { + ident_bind_name = ident.name; + matching_wild = true; } } } diff --git a/clippy_lints/src/matches/needless_match.rs b/clippy_lints/src/matches/needless_match.rs index 7e65d586110e5..6c5d7cab2036e 100644 --- a/clippy_lints/src/matches/needless_match.rs +++ b/clippy_lints/src/matches/needless_match.rs @@ -67,10 +67,10 @@ fn check_all_arms(cx: &LateContext<'_>, match_expr: &Expr<'_>, arms: &[Arm<'_>]) for arm in arms { let arm_expr = peel_blocks_with_stmt(arm.body); - if let Some(guard_expr) = &arm.guard { - if guard_expr.can_have_side_effects() { - return false; - } + if let Some(guard_expr) = &arm.guard + && guard_expr.can_have_side_effects() + { + return false; } if let PatKind::Wild = arm.pat.kind { diff --git a/clippy_lints/src/matches/overlapping_arms.rs b/clippy_lints/src/matches/overlapping_arms.rs index 4184f8b9e6e8a..d3136c89178e6 100644 --- a/clippy_lints/src/matches/overlapping_arms.rs +++ b/clippy_lints/src/matches/overlapping_arms.rs @@ -11,17 +11,17 @@ use super::MATCH_OVERLAPPING_ARM; pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) { if arms.len() >= 2 && cx.typeck_results().expr_ty(ex).is_integral() { let ranges = all_ranges(cx, arms, cx.typeck_results().expr_ty(ex)); - if !ranges.is_empty() { - if let Some((start, end)) = overlapping(&ranges) { - span_lint_and_note( - cx, - MATCH_OVERLAPPING_ARM, - start.span, - "some ranges overlap", - Some(end.span), - "overlaps with this", - ); - } + if !ranges.is_empty() + && let Some((start, end)) = overlapping(&ranges) + { + span_lint_and_note( + cx, + MATCH_OVERLAPPING_ARM, + start.span, + "some ranges overlap", + Some(end.span), + "overlaps with this", + ); } } } diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 37bac561a6e06..d7dc7604088f7 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -182,17 +182,16 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> { } fn has_sig_drop_attr_impl(&mut self, ty: Ty<'tcx>) -> bool { - if let Some(adt) = ty.ty_adt_def() { - if get_attr( + if let Some(adt) = ty.ty_adt_def() + && get_attr( self.cx.sess(), self.cx.tcx.get_attrs_unchecked(adt.did()), "has_significant_drop", ) .count() > 0 - { - return true; - } + { + return true; } if !self.seen_types.insert(ty) { diff --git a/clippy_lints/src/matches/wild_in_or_pats.rs b/clippy_lints/src/matches/wild_in_or_pats.rs index b75d1ab9a7aa3..43102d78bfebd 100644 --- a/clippy_lints/src/matches/wild_in_or_pats.rs +++ b/clippy_lints/src/matches/wild_in_or_pats.rs @@ -15,18 +15,18 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arms: &[Arm<'_>]) { return; } for arm in arms { - if let PatKind::Or(fields) = arm.pat.kind { + if let PatKind::Or(fields) = arm.pat.kind // look for multiple fields in this arm that contains at least one Wild pattern - if fields.len() > 1 && fields.iter().any(is_wild) { - span_lint_and_help( - cx, - WILDCARD_IN_OR_PATTERNS, - arm.pat.span, - "wildcard pattern covers any other pattern as it will match anyway", - None, - "consider handling `_` separately", - ); - } + && fields.len() > 1 && fields.iter().any(is_wild) + { + span_lint_and_help( + cx, + WILDCARD_IN_OR_PATTERNS, + arm.pat.span, + "wildcard pattern covers any other pattern as it will match anyway", + None, + "consider handling `_` separately", + ); } } } diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs index 1e9b29f567f41..f8520c23ea503 100644 --- a/clippy_lints/src/methods/bind_instead_of_map.rs +++ b/clippy_lints/src/methods/bind_instead_of_map.rs @@ -192,10 +192,10 @@ impl BindInsteadOfMap { } fn is_variant(&self, cx: &LateContext<'_>, res: Res) -> bool { - if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res { - if let Some(variant_id) = cx.tcx.lang_items().get(self.variant_lang_item) { - return cx.tcx.parent(id) == variant_id; - } + if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res + && let Some(variant_id) = cx.tcx.lang_items().get(self.variant_lang_item) + { + return cx.tcx.parent(id) == variant_id; } false } diff --git a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index 1c745b7376ea4..d07870d4951e0 100644 --- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -19,13 +19,13 @@ pub(super) fn check<'tcx>( arg: &'tcx Expr<'_>, msrv: Msrv, ) { - if let ExprKind::MethodCall(path_segment, ..) = recv.kind { - if matches!( + if let ExprKind::MethodCall(path_segment, ..) = recv.kind + && matches!( path_segment.ident.name.as_str(), "to_lowercase" | "to_uppercase" | "to_ascii_lowercase" | "to_ascii_uppercase" - ) { - return; - } + ) + { + return; } if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs index 1ee27d90d0545..2ecf3eb897988 100644 --- a/clippy_lints/src/methods/clone_on_copy.rs +++ b/clippy_lints/src/methods/clone_on_copy.rs @@ -40,10 +40,10 @@ pub(super) fn check( .map_or_else(|| cx.typeck_results().expr_ty(arg), |a| a.target); let ty = cx.typeck_results().expr_ty(expr); - if let ty::Ref(_, inner, _) = arg_ty.kind() { - if let ty::Ref(..) = inner.kind() { - return; // don't report clone_on_copy - } + if let ty::Ref(_, inner, _) = arg_ty.kind() + && let ty::Ref(..) = inner.kind() + { + return; // don't report clone_on_copy } if is_copy(cx, ty) { diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs index daa6e0e7f940c..f5688e370a478 100644 --- a/clippy_lints/src/methods/expect_fun_call.rs +++ b/clippy_lints/src/methods/expect_fun_call.rs @@ -54,10 +54,11 @@ pub(super) fn check<'tcx>( if is_type_lang_item(cx, arg_ty, hir::LangItem::String) { return false; } - if let ty::Ref(_, ty, ..) = arg_ty.kind() { - if ty.is_str() && can_be_static_str(cx, arg) { - return false; - } + if let ty::Ref(_, ty, ..) = arg_ty.kind() + && ty.is_str() + && can_be_static_str(cx, arg) + { + return false; } true } diff --git a/clippy_lints/src/methods/is_empty.rs b/clippy_lints/src/methods/is_empty.rs index 7c190e123b72e..92dc43f9aa4af 100644 --- a/clippy_lints/src/methods/is_empty.rs +++ b/clippy_lints/src/methods/is_empty.rs @@ -14,15 +14,13 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_ if expr.span.in_external_macro(cx.sess().source_map()) || !receiver.span.eq_ctxt(expr.span) { return; } - if let Some(parent) = get_parent_expr(cx, expr) { - if let Some(parent) = get_parent_expr(cx, parent) { - if is_inside_always_const_context(cx.tcx, expr.hir_id) - && let Some(macro_call) = root_macro_call(parent.span) - && is_assert_macro(cx, macro_call.def_id) - { - return; - } - } + if let Some(parent) = get_parent_expr(cx, expr) + && let Some(parent) = get_parent_expr(cx, parent) + && is_inside_always_const_context(cx.tcx, expr.hir_id) + && let Some(macro_call) = root_macro_call(parent.span) + && is_assert_macro(cx, macro_call.def_id) + { + return; } let init_expr = expr_or_init(cx, receiver); if !receiver.span.eq_ctxt(init_expr.span) { diff --git a/clippy_lints/src/methods/iterator_step_by_zero.rs b/clippy_lints/src/methods/iterator_step_by_zero.rs index 9b358235a40df..90d5d9df55eed 100644 --- a/clippy_lints/src/methods/iterator_step_by_zero.rs +++ b/clippy_lints/src/methods/iterator_step_by_zero.rs @@ -8,14 +8,14 @@ use rustc_span::sym; use super::ITERATOR_STEP_BY_ZERO; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) { - if is_trait_method(cx, expr, sym::Iterator) { - if let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg) { - span_lint( - cx, - ITERATOR_STEP_BY_ZERO, - expr.span, - "`Iterator::step_by(0)` will panic at runtime", - ); - } + if is_trait_method(cx, expr, sym::Iterator) + && let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg) + { + span_lint( + cx, + ITERATOR_STEP_BY_ZERO, + expr.span, + "`Iterator::step_by(0)` will panic at runtime", + ); } } diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs index 13918ed11b87d..18978a1d2bc86 100644 --- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -106,15 +106,15 @@ fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option { }; let check_lit = |expr: &hir::Expr<'_>, check_min: bool| { - if let hir::ExprKind::Lit(lit) = &expr.kind { - if let ast::LitKind::Int(value, _) = lit.node { - if value == maxval { - return Some(MinMax::Max); - } - - if check_min && value == minval { - return Some(MinMax::Min); - } + if let hir::ExprKind::Lit(lit) = &expr.kind + && let ast::LitKind::Int(value, _) = lit.node + { + if value == maxval { + return Some(MinMax::Max); + } + + if check_min && value == minval { + return Some(MinMax::Min); } } @@ -125,10 +125,10 @@ fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option { return r; } - if ty.is_signed() { - if let hir::ExprKind::Unary(hir::UnOp::Neg, val) = &expr.kind { - return check_lit(val, true); - } + if ty.is_signed() + && let hir::ExprKind::Unary(hir::UnOp::Neg, val) = &expr.kind + { + return check_lit(val, true); } None diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index 50b7578085fa2..333a33f7527d6 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -51,19 +51,19 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_ let closure_expr = peel_blocks(closure_body.value); match closure_body.params[0].pat.kind { hir::PatKind::Ref(inner, Mutability::Not) => { - if let hir::PatKind::Binding(hir::BindingMode::NONE, .., name, None) = inner.kind { - if ident_eq(name, closure_expr) { - lint_explicit_closure(cx, e.span, recv.span, true, msrv); - } + if let hir::PatKind::Binding(hir::BindingMode::NONE, .., name, None) = inner.kind + && ident_eq(name, closure_expr) + { + lint_explicit_closure(cx, e.span, recv.span, true, msrv); } }, hir::PatKind::Binding(hir::BindingMode::NONE, .., name, None) => { match closure_expr.kind { hir::ExprKind::Unary(hir::UnOp::Deref, inner) => { - if ident_eq(name, inner) { - if let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind() { - lint_explicit_closure(cx, e.span, recv.span, true, msrv); - } + if ident_eq(name, inner) + && let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind() + { + lint_explicit_closure(cx, e.span, recv.span, true, msrv); } }, hir::ExprKind::MethodCall(method, obj, [], _) => { diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index fad583169b2ea..5b61128b0121c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4667,11 +4667,12 @@ impl_lint_pass!(Methods => [ pub fn method_call<'tcx>( recv: &'tcx Expr<'tcx>, ) -> Option<(&'tcx str, &'tcx Expr<'tcx>, &'tcx [Expr<'tcx>], Span, Span)> { - if let ExprKind::MethodCall(path, receiver, args, call_span) = recv.kind { - if !args.iter().any(|e| e.span.from_expansion()) && !receiver.span.from_expansion() { - let name = path.ident.name.as_str(); - return Some((name, receiver, args, path.ident.span, call_span)); - } + if let ExprKind::MethodCall(path, receiver, args, call_span) = recv.kind + && !args.iter().any(|e| e.span.from_expansion()) + && !receiver.span.from_expansion() + { + let name = path.ident.name.as_str(); + return Some((name, receiver, args, path.ident.span, call_span)); } None } diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 56ff7e2c61b22..4b3fd452954fa 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -377,20 +377,20 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { return; } - if let Some(hir_id) = path_to_local(recv) { - if let Some(index) = self.hir_id_uses_map.remove(&hir_id) { - if self - .illegal_mutable_capture_ids - .intersection(&self.current_mutably_captured_ids) - .next() - .is_none() - { - if let Some(hir_id) = self.current_statement_hir_id { - self.hir_id_uses_map.insert(hir_id, index); - } - } else { - self.uses[index] = None; + if let Some(hir_id) = path_to_local(recv) + && let Some(index) = self.hir_id_uses_map.remove(&hir_id) + { + if self + .illegal_mutable_capture_ids + .intersection(&self.current_mutably_captured_ids) + .next() + .is_none() + { + if let Some(hir_id) = self.current_statement_hir_id { + self.hir_id_uses_map.insert(hir_id, index); } + } else { + self.uses[index] = None; } } } diff --git a/clippy_lints/src/methods/needless_option_take.rs b/clippy_lints/src/methods/needless_option_take.rs index 88b9c69f6f949..cd1b97f3c51b5 100644 --- a/clippy_lints/src/methods/needless_option_take.rs +++ b/clippy_lints/src/methods/needless_option_take.rs @@ -9,26 +9,27 @@ use super::NEEDLESS_OPTION_TAKE; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) { // Checks if expression type is equal to sym::Option and if the expr is not a syntactic place - if !recv.is_syntactic_place_expr() && is_expr_option(cx, recv) { - if let Some(function_name) = source_of_temporary_value(recv) { - span_lint_and_then( - cx, - NEEDLESS_OPTION_TAKE, - expr.span, - "called `Option::take()` on a temporary value", - |diag| { - diag.note(format!( - "`{function_name}` creates a temporary value, so calling take() has no effect" - )); - diag.span_suggestion( - expr.span.with_lo(recv.span.hi()), - "remove", - "", - Applicability::MachineApplicable, - ); - }, - ); - } + if !recv.is_syntactic_place_expr() + && is_expr_option(cx, recv) + && let Some(function_name) = source_of_temporary_value(recv) + { + span_lint_and_then( + cx, + NEEDLESS_OPTION_TAKE, + expr.span, + "called `Option::take()` on a temporary value", + |diag| { + diag.note(format!( + "`{function_name}` creates a temporary value, so calling take() has no effect" + )); + diag.span_suggestion( + expr.span.with_lo(recv.span.hi()), + "remove", + "", + Applicability::MachineApplicable, + ); + }, + ); } } @@ -44,10 +45,10 @@ fn is_expr_option(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { fn source_of_temporary_value<'a>(expr: &'a Expr<'_>) -> Option<&'a str> { match expr.peel_borrows().kind { ExprKind::Call(function, _) => { - if let ExprKind::Path(QPath::Resolved(_, func_path)) = function.kind { - if !func_path.segments.is_empty() { - return Some(func_path.segments[0].ident.name.as_str()); - } + if let ExprKind::Path(QPath::Resolved(_, func_path)) = function.kind + && !func_path.segments.is_empty() + { + return Some(func_path.segments[0].ident.name.as_str()); } if let ExprKind::Path(QPath::TypeRelative(_, func_path_segment)) = function.kind { return Some(func_path_segment.ident.name.as_str()); diff --git a/clippy_lints/src/methods/seek_from_current.rs b/clippy_lints/src/methods/seek_from_current.rs index 28bf2d5aeec5b..96180862fd0dc 100644 --- a/clippy_lints/src/methods/seek_from_current.rs +++ b/clippy_lints/src/methods/seek_from_current.rs @@ -15,21 +15,22 @@ use super::SEEK_FROM_CURRENT; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) { let ty = cx.typeck_results().expr_ty(recv); - if let Some(def_id) = cx.tcx.get_diagnostic_item(sym::IoSeek) { - if implements_trait(cx, ty, def_id, &[]) && arg_is_seek_from_current(cx, arg) { - let mut applicability = Applicability::MachineApplicable; - let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability); + if let Some(def_id) = cx.tcx.get_diagnostic_item(sym::IoSeek) + && implements_trait(cx, ty, def_id, &[]) + && arg_is_seek_from_current(cx, arg) + { + let mut applicability = Applicability::MachineApplicable; + let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability); - span_lint_and_sugg( - cx, - SEEK_FROM_CURRENT, - expr.span, - "using `SeekFrom::Current` to start from current position", - "replace with", - format!("{snip}.stream_position()"), - applicability, - ); - } + span_lint_and_sugg( + cx, + SEEK_FROM_CURRENT, + expr.span, + "using `SeekFrom::Current` to start from current position", + "replace with", + format!("{snip}.stream_position()"), + applicability, + ); } } diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 4ccefb7ec9d77..d183457da25a2 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -238,15 +238,14 @@ fn indirect_usage<'tcx>( unwrap_kind: Some(unwrap_kind), .. } = iter_usage + && parent_id == local_hir_id { - if parent_id == local_hir_id { - return Some(IndirectUsage { - name: ident.name, - span: stmt.span, - init_expr, - unwrap_kind, - }); - } + return Some(IndirectUsage { + name: ident.name, + span: stmt.span, + init_expr, + unwrap_kind, + }); } } diff --git a/clippy_lints/src/methods/suspicious_map.rs b/clippy_lints/src/methods/suspicious_map.rs index 1bd48525f12d8..788014d9bb632 100644 --- a/clippy_lints/src/methods/suspicious_map.rs +++ b/clippy_lints/src/methods/suspicious_map.rs @@ -13,11 +13,11 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, count_recv: &hir::Expr< && let closure_body = cx.tcx.hir_body(closure.body) && !cx.typeck_results().expr_ty(closure_body.value).is_unit() { - if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx) { + if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx) // A variable is used mutably inside of the closure. Suppress the lint. - if !map_mutated_vars.is_empty() { - return; - } + && !map_mutated_vars.is_empty() + { + return; } span_lint_and_help( cx, diff --git a/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/clippy_lints/src/methods/unnecessary_lazy_eval.rs index 9f4080100da20..e3596cf6a60c9 100644 --- a/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -23,56 +23,56 @@ pub(super) fn check<'tcx>( let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); let is_bool = cx.typeck_results().expr_ty(recv).is_bool(); - if is_option || is_result || is_bool { - if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl, .. }) = arg.kind { - let body = cx.tcx.hir_body(body); - let body_expr = &body.value; + if (is_option || is_result || is_bool) + && let hir::ExprKind::Closure(&hir::Closure { body, fn_decl, .. }) = arg.kind + { + let body = cx.tcx.hir_body(body); + let body_expr = &body.value; - if usage::BindingUsageFinder::are_params_used(cx, body) || is_from_proc_macro(cx, expr) { - return false; - } + if usage::BindingUsageFinder::are_params_used(cx, body) || is_from_proc_macro(cx, expr) { + return false; + } - if eager_or_lazy::switch_to_eager_eval(cx, body_expr) { - let msg = if is_option { - "unnecessary closure used to substitute value for `Option::None`" - } else if is_result { - "unnecessary closure used to substitute value for `Result::Err`" - } else { - "unnecessary closure used with `bool::then`" - }; - let applicability = if body - .params - .iter() - // bindings are checked to be unused above - .all(|param| matches!(param.pat.kind, hir::PatKind::Binding(..) | hir::PatKind::Wild)) - && matches!( - fn_decl.output, - FnRetTy::DefaultReturn(_) - | FnRetTy::Return(hir::Ty { - kind: hir::TyKind::Infer(()), - .. - }) - ) { - Applicability::MachineApplicable - } else { - // replacing the lambda may break type inference - Applicability::MaybeIncorrect - }; + if eager_or_lazy::switch_to_eager_eval(cx, body_expr) { + let msg = if is_option { + "unnecessary closure used to substitute value for `Option::None`" + } else if is_result { + "unnecessary closure used to substitute value for `Result::Err`" + } else { + "unnecessary closure used with `bool::then`" + }; + let applicability = if body + .params + .iter() + // bindings are checked to be unused above + .all(|param| matches!(param.pat.kind, hir::PatKind::Binding(..) | hir::PatKind::Wild)) + && matches!( + fn_decl.output, + FnRetTy::DefaultReturn(_) + | FnRetTy::Return(hir::Ty { + kind: hir::TyKind::Infer(()), + .. + }) + ) { + Applicability::MachineApplicable + } else { + // replacing the lambda may break type inference + Applicability::MaybeIncorrect + }; - // This is a duplicate of what's happening in clippy_lints::methods::method_call, - // which isn't ideal, We want to get the method call span, - // but prefer to avoid changing the signature of the function itself. - if let hir::ExprKind::MethodCall(.., span) = expr.kind { - span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| { - diag.span_suggestion_verbose( - span, - format!("use `{simplify_using}` instead"), - format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")), - applicability, - ); - }); - return true; - } + // This is a duplicate of what's happening in clippy_lints::methods::method_call, + // which isn't ideal, We want to get the method call span, + // but prefer to avoid changing the signature of the function itself. + if let hir::ExprKind::MethodCall(.., span) = expr.kind { + span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| { + diag.span_suggestion_verbose( + span, + format!("use `{simplify_using}` instead"), + format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")), + applicability, + ); + }); + return true; } } } diff --git a/clippy_lints/src/misc_early/builtin_type_shadow.rs b/clippy_lints/src/misc_early/builtin_type_shadow.rs index 662f7cd8500cf..9ee1e2f3fd17a 100644 --- a/clippy_lints/src/misc_early/builtin_type_shadow.rs +++ b/clippy_lints/src/misc_early/builtin_type_shadow.rs @@ -6,14 +6,14 @@ use rustc_lint::EarlyContext; use super::BUILTIN_TYPE_SHADOW; pub(super) fn check(cx: &EarlyContext<'_>, param: &GenericParam) { - if let GenericParamKind::Type { .. } = param.kind { - if let Some(prim_ty) = PrimTy::from_name(param.ident.name) { - span_lint( - cx, - BUILTIN_TYPE_SHADOW, - param.ident.span, - format!("this generic shadows the built-in type `{}`", prim_ty.name()), - ); - } + if let GenericParamKind::Type { .. } = param.kind + && let Some(prim_ty) = PrimTy::from_name(param.ident.name) + { + span_lint( + cx, + BUILTIN_TYPE_SHADOW, + param.ident.span, + format!("this generic shadows the built-in type `{}`", prim_ty.name()), + ); } } diff --git a/clippy_lints/src/misc_early/redundant_pattern.rs b/clippy_lints/src/misc_early/redundant_pattern.rs index d5b5b2bf2dd1b..3cb51671aaf18 100644 --- a/clippy_lints/src/misc_early/redundant_pattern.rs +++ b/clippy_lints/src/misc_early/redundant_pattern.rs @@ -6,20 +6,20 @@ use rustc_lint::EarlyContext; use super::REDUNDANT_PATTERN; pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { - if let PatKind::Ident(ann, ident, Some(ref right)) = pat.kind { - if let PatKind::Wild = right.kind { - span_lint_and_sugg( - cx, - REDUNDANT_PATTERN, - pat.span, - format!( - "the `{} @ _` pattern can be written as just `{}`", - ident.name, ident.name, - ), - "try", - format!("{}{}", ann.prefix_str(), ident.name), - Applicability::MachineApplicable, - ); - } + if let PatKind::Ident(ann, ident, Some(ref right)) = pat.kind + && let PatKind::Wild = right.kind + { + span_lint_and_sugg( + cx, + REDUNDANT_PATTERN, + pat.span, + format!( + "the `{} @ _` pattern can be written as just `{}`", + ident.name, ident.name, + ), + "try", + format!("{}{}", ann.prefix_str(), ident.name), + Applicability::MachineApplicable, + ); } } diff --git a/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs b/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs index 00f46629f102c..fffaf40c9d141 100644 --- a/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs +++ b/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs @@ -7,30 +7,30 @@ use rustc_span::Span; use super::UNNEEDED_WILDCARD_PATTERN; pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { - if let PatKind::TupleStruct(_, _, ref patterns) | PatKind::Tuple(ref patterns) = pat.kind { - if let Some(rest_index) = patterns.iter().position(|pat| pat.is_rest()) { - if let Some((left_index, left_pat)) = patterns[..rest_index] - .iter() - .rev() - .take_while(|pat| matches!(pat.kind, PatKind::Wild)) - .enumerate() - .last() - { - span_lint(cx, left_pat.span.until(patterns[rest_index].span), left_index == 0); - } + if let PatKind::TupleStruct(_, _, ref patterns) | PatKind::Tuple(ref patterns) = pat.kind + && let Some(rest_index) = patterns.iter().position(|pat| pat.is_rest()) + { + if let Some((left_index, left_pat)) = patterns[..rest_index] + .iter() + .rev() + .take_while(|pat| matches!(pat.kind, PatKind::Wild)) + .enumerate() + .last() + { + span_lint(cx, left_pat.span.until(patterns[rest_index].span), left_index == 0); + } - if let Some((right_index, right_pat)) = patterns[rest_index + 1..] - .iter() - .take_while(|pat| matches!(pat.kind, PatKind::Wild)) - .enumerate() - .last() - { - span_lint( - cx, - patterns[rest_index].span.shrink_to_hi().to(right_pat.span), - right_index == 0, - ); - } + if let Some((right_index, right_pat)) = patterns[rest_index + 1..] + .iter() + .take_while(|pat| matches!(pat.kind, PatKind::Wild)) + .enumerate() + .last() + { + span_lint( + cx, + patterns[rest_index].span.shrink_to_hi().to(right_pat.span), + right_index == 0, + ); } } } diff --git a/clippy_lints/src/mismatching_type_param_order.rs b/clippy_lints/src/mismatching_type_param_order.rs index d52fe7e7d5b9c..394bc4aef1cc7 100644 --- a/clippy_lints/src/mismatching_type_param_order.rs +++ b/clippy_lints/src/mismatching_type_param_order.rs @@ -111,10 +111,10 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch { // Checks if impl_param_name is the same as one of type_param_names, // and is in a different position fn mismatch_param_name(i: usize, impl_param_name: &String, type_param_names: &FxHashMap<&String, usize>) -> bool { - if let Some(j) = type_param_names.get(impl_param_name) { - if i != *j { - return true; - } + if let Some(j) = type_param_names.get(impl_param_name) + && i != *j + { + return true; } false } diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 38a19dd2999bb..5ac66b4c7e84b 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -139,12 +139,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { // Const fns are not allowed as methods in a trait. { let parent = cx.tcx.hir_get_parent_item(hir_id).def_id; - if parent != CRATE_DEF_ID { - if let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(parent) { - if let hir::ItemKind::Trait(..) = &item.kind { - return; - } - } + if parent != CRATE_DEF_ID + && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(parent) + && let hir::ItemKind::Trait(..) = &item.kind + { + return; } } diff --git a/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs index 28dc242742842..05517a5d869c9 100644 --- a/clippy_lints/src/missing_fields_in_debug.rs +++ b/clippy_lints/src/missing_fields_in_debug.rs @@ -224,11 +224,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { // NB: can't call cx.typeck_results() as we are not in a body && let typeck_results = cx.tcx.typeck_body(*body_id) && should_lint(cx, typeck_results, block) - { // we intentionally only lint structs, see lint description - if let ItemKind::Struct(_, data, _) = &self_item.kind { - check_struct(cx, typeck_results, block, self_ty, item, data); - } + && let ItemKind::Struct(_, data, _) = &self_item.kind + { + check_struct(cx, typeck_results, block, self_ty, item, data); } } } diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index f49e03ea76528..1f613171b46e8 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -160,12 +160,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { AssocItemContainer::Impl => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id), }; - if let Some(trait_def_id) = trait_def_id { - if trait_def_id.is_local() && !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) { - // If a trait is being implemented for an item, and the - // trait is not exported, we don't need #[inline] - return; - } + if let Some(trait_def_id) = trait_def_id + && trait_def_id.is_local() + && !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) + { + // If a trait is being implemented for an item, and the + // trait is not exported, we don't need #[inline] + return; } let attrs = cx.tcx.hir_attrs(impl_item.hir_id()); diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index 274438ac0491e..fd0170604362c 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -135,10 +135,10 @@ impl<'tcx> DivergenceVisitor<'_, 'tcx> { } fn report_diverging_sub_expr(&mut self, e: &Expr<'_>) { - if let Some(macro_call) = root_macro_call_first_node(self.cx, e) { - if self.cx.tcx.item_name(macro_call.def_id).as_str() == "todo" { - return; - } + if let Some(macro_call) = root_macro_call_first_node(self.cx, e) + && self.cx.tcx.item_name(macro_call.def_id).as_str() == "todo" + { + return; } span_lint(self.cx, DIVERGING_SUB_EXPRESSION, e.span, "sub-expression diverges"); } @@ -372,10 +372,10 @@ impl<'tcx> Visitor<'tcx> for ReadVisitor<'_, 'tcx> { /// Returns `true` if `expr` is the LHS of an assignment, like `expr = ...`. fn is_in_assignment_position(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - if let Some(parent) = get_parent_expr(cx, expr) { - if let ExprKind::Assign(lhs, ..) = parent.kind { - return lhs.hir_id == expr.hir_id; - } + if let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::Assign(lhs, ..) = parent.kind + { + return lhs.hir_id == expr.hir_id; } false } diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs index 676d608eb318c..8065a0a359b49 100644 --- a/clippy_lints/src/module_style.rs +++ b/clippy_lints/src/module_style.rs @@ -119,22 +119,22 @@ impl EarlyLintPass for ModStyle { } for folder in &folder_segments { - if !mod_folders.contains(folder) { - if let Some((file, path)) = file_map.get(folder) { - span_lint_and_then( - cx, - SELF_NAMED_MODULE_FILES, - Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None), - format!("`mod.rs` files are required, found `{}`", path.display()), - |diag| { - let mut correct = path.to_path_buf(); - correct.pop(); - correct.push(folder); - correct.push("mod.rs"); - diag.help(format!("move `{}` to `{}`", path.display(), correct.display(),)); - }, - ); - } + if !mod_folders.contains(folder) + && let Some((file, path)) = file_map.get(folder) + { + span_lint_and_then( + cx, + SELF_NAMED_MODULE_FILES, + Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None), + format!("`mod.rs` files are required, found `{}`", path.display()), + |diag| { + let mut correct = path.to_path_buf(); + correct.pop(); + correct.push(folder); + correct.push("mod.rs"); + diag.help(format!("move `{}` to `{}`", path.display(), correct.display(),)); + }, + ); } } } diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 2adc27c0b709a..c6c27e22b90e5 100644 --- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -142,10 +142,9 @@ fn collect_unsafe_exprs<'tcx>( .typeck_results() .type_dependent_def_id(expr.hir_id) .map(|def_id| cx.tcx.fn_sig(def_id)) + && sig.skip_binder().safety().is_unsafe() { - if sig.skip_binder().safety().is_unsafe() { - unsafe_ops.push(("unsafe method call occurs here", expr.span)); - } + unsafe_ops.push(("unsafe method call occurs here", expr.span)); } }, diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs index 7abc5870d00e0..a45031ce22b91 100644 --- a/clippy_lints/src/mut_key.rs +++ b/clippy_lints/src/mut_key.rs @@ -82,10 +82,10 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType<'tcx> { } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) { - if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind { - if trait_ref_of_method(cx, item.owner_id.def_id).is_none() { - self.check_sig(cx, item.owner_id.def_id, sig.decl); - } + if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind + && trait_ref_of_method(cx, item.owner_id.def_id).is_none() + { + self.check_sig(cx, item.owner_id.def_id, sig.decl); } } diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 3c4ba5141dd9b..d98c70e7f5a85 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -77,16 +77,16 @@ impl<'tcx> intravisit::Visitor<'tcx> for MutVisitor<'_, 'tcx> { expr.span, "generally you want to avoid `&mut &mut _` if possible", ); - } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() { - if ty.peel_refs().is_sized(self.cx.tcx, self.cx.typing_env()) { - span_lint_hir( - self.cx, - MUT_MUT, - expr.hir_id, - expr.span, - "this expression mutably borrows a mutable reference. Consider reborrowing", - ); - } + } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() + && ty.peel_refs().is_sized(self.cx.tcx, self.cx.typing_env()) + { + span_lint_hir( + self.cx, + MUT_MUT, + expr.hir_id, + expr.span, + "this expression mutably borrows a mutable reference. Consider reborrowing", + ); } } } diff --git a/clippy_lints/src/mutable_debug_assertion.rs b/clippy_lints/src/mutable_debug_assertion.rs index 3d943bf5b370e..d5bed54f0be2f 100644 --- a/clippy_lints/src/mutable_debug_assertion.rs +++ b/clippy_lints/src/mutable_debug_assertion.rs @@ -97,14 +97,13 @@ impl<'tcx> Visitor<'tcx> for MutArgVisitor<'_, 'tcx> { return; }, ExprKind::Path(_) => { - if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) { - if adj + if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) + && adj .iter() .any(|a| matches!(a.target.kind(), ty::Ref(_, _, Mutability::Mut))) - { - self.found = true; - return; - } + { + self.found = true; + return; } }, // Don't check await desugars diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 49fd29d1dd6dc..fe2157ca533a6 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -91,19 +91,19 @@ declare_lint_pass!(Mutex => [MUTEX_ATOMIC, MUTEX_INTEGER]); impl<'tcx> LateLintPass<'tcx> for Mutex { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let ty = cx.typeck_results().expr_ty(expr); - if let ty::Adt(_, subst) = ty.kind() { - if is_type_diagnostic_item(cx, ty, sym::Mutex) { - let mutex_param = subst.type_at(0); - if let Some(atomic_name) = get_atomic_name(mutex_param) { - let msg = format!( - "consider using an `{atomic_name}` instead of a `Mutex` here; if you just want the locking \ + if let ty::Adt(_, subst) = ty.kind() + && is_type_diagnostic_item(cx, ty, sym::Mutex) + { + let mutex_param = subst.type_at(0); + if let Some(atomic_name) = get_atomic_name(mutex_param) { + let msg = format!( + "consider using an `{atomic_name}` instead of a `Mutex` here; if you just want the locking \ behavior and not the internal type, consider using `Mutex<()>`" - ); - match *mutex_param.kind() { - ty::Uint(t) if t != UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, msg), - ty::Int(t) if t != IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, msg), - _ => span_lint(cx, MUTEX_ATOMIC, expr.span, msg), - } + ); + match *mutex_param.kind() { + ty::Uint(t) if t != UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, msg), + ty::Int(t) if t != IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, msg), + _ => span_lint(cx, MUTEX_ATOMIC, expr.span, msg), } } } diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 0e648c5cb2bc5..f768e11a4a2bb 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -426,10 +426,10 @@ fn fetch_bool_block(expr: &Expr<'_>) -> Option { } fn fetch_bool_expr(expr: &Expr<'_>) -> Option { - if let ExprKind::Lit(lit_ptr) = peel_blocks(expr).kind { - if let LitKind::Bool(value) = lit_ptr.node { - return Some(value); - } + if let ExprKind::Lit(lit_ptr) = peel_blocks(expr).kind + && let LitKind::Bool(value) = lit_ptr.node + { + return Some(value); } None } diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index 576bb27b254c9..3a520c5a7bdd4 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -86,11 +86,11 @@ fn should_skip<'tcx>( return false; } - if let PatKind::Binding(.., name, _) = arg.pat.kind { + if let PatKind::Binding(.., name, _) = arg.pat.kind // If it's a potentially unused variable, we don't check it. - if name.name == kw::Underscore || name.as_str().starts_with('_') { - return true; - } + && (name.name == kw::Underscore || name.as_str().starts_with('_')) + { + return true; } // All spans generated from a proc-macro invocation are the same... @@ -164,13 +164,13 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { }; // Exclude non-inherent impls - if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) { - if matches!( + if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) + && matches!( item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) - ) { - return; - } + ) + { + return; } let fn_sig = cx.tcx.fn_sig(fn_def_id).instantiate_identity(); @@ -353,10 +353,10 @@ impl MutablyUsedVariablesCtxt<'_> { for (parent, node) in self.tcx.hir_parent_iter(item) { if let Some(fn_sig) = self.tcx.hir_fn_sig_by_hir_id(parent) { return fn_sig.header.is_unsafe(); - } else if let Node::Block(block) = node { - if matches!(block.rules, BlockCheckMode::UnsafeBlock(_)) { - return true; - } + } else if let Node::Block(block) = node + && matches!(block.rules, BlockCheckMode::UnsafeBlock(_)) + { + return true; } } false @@ -426,10 +426,10 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> { // upon! self.add_mutably_used_var(*vid); } - } else if borrow == ty::BorrowKind::Immutable { + } else if borrow == ty::BorrowKind::Immutable // If there is an `async block`, it'll contain a call to a closure which we need to // go into to ensure all "mutate" checks are found. - if let Node::Expr(Expr { + && let Node::Expr(Expr { kind: ExprKind::Call( _, @@ -442,9 +442,8 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> { ), .. }) = self.tcx.hir_node(cmt.hir_id) - { - self.async_closures.insert(*def_id); - } + { + self.async_closures.insert(*def_id); } } @@ -460,10 +459,9 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> { }), .. } = &cmt.place + && !projections.is_empty() { - if !projections.is_empty() { - self.add_mutably_used_var(*vid); - } + self.add_mutably_used_var(*vid); } } @@ -477,10 +475,9 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> { }), .. } = &cmt.place + && self.is_in_unsafe_block(id) { - if self.is_in_unsafe_block(id) { - self.add_mutably_used_var(*vid); - } + self.add_mutably_used_var(*vid); } self.prev_bind = None; } @@ -499,15 +496,14 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> { }), .. } = &cmt.place + && let FakeReadCause::ForLet(Some(inner)) = cause { - if let FakeReadCause::ForLet(Some(inner)) = cause { - // Seems like we are inside an async function. We need to store the closure `DefId` - // to go through it afterwards. - self.async_closures.insert(inner); - self.add_alias(cmt.hir_id, *vid); - self.prev_move_to_closure.insert(*vid); - self.prev_bind = None; - } + // Seems like we are inside an async function. We need to store the closure `DefId` + // to go through it afterwards. + self.async_closures.insert(inner); + self.add_alias(cmt.hir_id, *vid); + self.prev_move_to_closure.insert(*vid); + self.prev_bind = None; } } @@ -522,10 +518,9 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> { }), .. } = &cmt.place + && self.is_in_unsafe_block(id) { - if self.is_in_unsafe_block(id) { - self.add_mutably_used_var(*vid); - } + self.add_mutably_used_var(*vid); } } } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 55ca875edcee6..0c5c624c378ef 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -98,13 +98,13 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } // Exclude non-inherent impls - if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) { - if matches!( + if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) + && matches!( item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) - ) { - return; - } + ) + { + return; } // Allow `Borrow` or functions to be taken by value @@ -197,20 +197,18 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { { // Dereference suggestion let sugg = |diag: &mut Diag<'_, ()>| { - if let ty::Adt(def, ..) = ty.kind() { - if let Some(span) = cx.tcx.hir().span_if_local(def.did()) { - if type_allowed_to_implement_copy( - cx.tcx, - cx.param_env, - ty, - traits::ObligationCause::dummy_with_span(span), - rustc_hir::Safety::Safe, - ) - .is_ok() - { - diag.span_help(span, "or consider marking this type as `Copy`"); - } - } + if let ty::Adt(def, ..) = ty.kind() + && let Some(span) = cx.tcx.hir().span_if_local(def.did()) + && type_allowed_to_implement_copy( + cx.tcx, + cx.param_env, + ty, + traits::ObligationCause::dummy_with_span(span), + rustc_hir::Safety::Safe, + ) + .is_ok() + { + diag.span_help(span, "or consider marking this type as `Copy`"); } if is_type_diagnostic_item(cx, ty, sym::Vec) @@ -254,29 +252,28 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { return; } - if is_type_lang_item(cx, ty, LangItem::String) { - if let Some(clone_spans) = + if is_type_lang_item(cx, ty, LangItem::String) + && let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) - { + { + diag.span_suggestion( + input.span, + "consider changing the type to", + "&str", + Applicability::Unspecified, + ); + + for (span, suggestion) in clone_spans { diag.span_suggestion( - input.span, - "consider changing the type to", - "&str", + span, + span.get_source_text(cx) + .map_or("change the call to".to_owned(), |src| format!("change `{src}` to")), + suggestion, Applicability::Unspecified, ); - - for (span, suggestion) in clone_spans { - diag.span_suggestion( - span, - span.get_source_text(cx) - .map_or("change the call to".to_owned(), |src| format!("change `{src}` to")), - suggestion, - Applicability::Unspecified, - ); - } - - return; } + + return; } diag.span_suggestion_verbose( diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 0cba72bd2c6a9..4a86c3720ca24 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -53,17 +53,16 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessUpdate { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Struct(_, fields, StructTailExpr::Base(base)) = expr.kind { let ty = cx.typeck_results().expr_ty(expr); - if let ty::Adt(def, _) = ty.kind() { - if fields.len() == def.non_enum_variant().fields.len() - && !def.variant(0_usize.into()).is_field_list_non_exhaustive() - { - span_lint( - cx, - NEEDLESS_UPDATE, - base.span, - "struct update has no effect, all the fields in the struct have already been specified", - ); - } + if let ty::Adt(def, _) = ty.kind() + && fields.len() == def.non_enum_variant().fields.len() + && !def.variant(0_usize.into()).is_field_list_non_exhaustive() + { + span_lint( + cx, + NEEDLESS_UPDATE, + base.span, + "struct update has no effect, all the fields in the struct have already been specified", + ); } } } diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 86eb833becc20..07924e67765bc 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -35,14 +35,14 @@ declare_lint_pass!(NegMultiply => [NEG_MULTIPLY]); impl<'tcx> LateLintPass<'tcx> for NegMultiply { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::Binary(ref op, left, right) = e.kind { - if BinOpKind::Mul == op.node { - match (&left.kind, &right.kind) { - (&ExprKind::Unary(..), &ExprKind::Unary(..)) => {}, - (&ExprKind::Unary(UnOp::Neg, lit), _) => check_mul(cx, e.span, lit, right), - (_, &ExprKind::Unary(UnOp::Neg, lit)) => check_mul(cx, e.span, lit, left), - _ => {}, - } + if let ExprKind::Binary(ref op, left, right) = e.kind + && BinOpKind::Mul == op.node + { + match (&left.kind, &right.kind) { + (&ExprKind::Unary(..), &ExprKind::Unary(..)) => {}, + (&ExprKind::Unary(UnOp::Neg, lit), _) => check_mul(cx, e.span, lit, right), + (_, &ExprKind::Unary(UnOp::Neg, lit)) => check_mul(cx, e.span, lit, left), + _ => {}, } } } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index f0ee613791fb9..c4e5498d5ee62 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -99,10 +99,10 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { let mut impls = HirIdSet::default(); cx.tcx.for_each_impl(default_trait_id, |d| { let ty = cx.tcx.type_of(d).instantiate_identity(); - if let Some(ty_def) = ty.ty_adt_def() { - if let Some(local_def_id) = ty_def.did().as_local() { - impls.insert(cx.tcx.local_def_id_to_hir_id(local_def_id)); - } + if let Some(ty_def) = ty.ty_adt_def() + && let Some(local_def_id) = ty_def.did().as_local() + { + impls.insert(cx.tcx.local_def_id_to_hir_id(local_def_id)); } }); self.impling_types = Some(impls); diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 7187a8f2c11a1..7ab7976d5697a 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -182,23 +182,22 @@ impl NoEffect { ); return true; } - } else if let StmtKind::Let(local) = stmt.kind { - if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id) - && !matches!(local.source, LocalSource::AsyncFn) - && let Some(init) = local.init - && local.els.is_none() - && !local.pat.span.from_expansion() - && has_no_effect(cx, init) - && let PatKind::Binding(_, hir_id, ident, _) = local.pat.kind - && ident.name.to_ident_string().starts_with('_') - && !in_automatically_derived(cx.tcx, local.hir_id) - { - if let Some(l) = self.local_bindings.last_mut() { - l.push(hir_id); - self.underscore_bindings.insert(hir_id, ident.span); - } - return true; + } else if let StmtKind::Let(local) = stmt.kind + && !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id) + && !matches!(local.source, LocalSource::AsyncFn) + && let Some(init) = local.init + && local.els.is_none() + && !local.pat.span.from_expansion() + && has_no_effect(cx, init) + && let PatKind::Binding(_, hir_id, ident, _) = local.pat.kind + && ident.name.to_ident_string().starts_with('_') + && !in_automatically_derived(cx.tcx, local.hir_id) + { + if let Some(l) = self.local_bindings.last_mut() { + l.push(hir_id); + self.underscore_bindings.insert(hir_id, ident.span); } + return true; } false } diff --git a/clippy_lints/src/non_zero_suggestions.rs b/clippy_lints/src/non_zero_suggestions.rs index 16c4391c0fbea..635f5678e2a65 100644 --- a/clippy_lints/src/non_zero_suggestions.rs +++ b/clippy_lints/src/non_zero_suggestions.rs @@ -82,11 +82,10 @@ fn check_non_zero_conversion(cx: &LateContext<'_>, expr: &Expr<'_>, applicabilit if let ty::Adt(adt_def, _) = receiver_ty.kind() && adt_def.is_struct() && cx.tcx.get_diagnostic_name(adt_def.did()) == Some(sym::NonZero) + && let Some(target_non_zero_type) = get_target_non_zero_type(target_ty) { - if let Some(target_non_zero_type) = get_target_non_zero_type(target_ty) { - let arg_snippet = get_arg_snippet(cx, arg, rcv_path); - suggest_non_zero_conversion(cx, expr, fn_name, target_non_zero_type, &arg_snippet, applicability); - } + let arg_snippet = get_arg_snippet(cx, arg, rcv_path); + suggest_non_zero_conversion(cx, expr, fn_name, target_non_zero_type, &arg_snippet, applicability); } } } diff --git a/clippy_lints/src/operators/modulo_one.rs b/clippy_lints/src/operators/modulo_one.rs index fc5565e821edd..2e6a071eb1848 100644 --- a/clippy_lints/src/operators/modulo_one.rs +++ b/clippy_lints/src/operators/modulo_one.rs @@ -12,15 +12,15 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, op: BinOpKind, right: span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); } - if let ty::Int(ity) = cx.typeck_results().expr_ty(right).kind() { - if is_integer_const(cx, right, unsext(cx.tcx, -1, *ity)) { - span_lint( - cx, - MODULO_ONE, - expr.span, - "any number modulo -1 will panic/overflow or result in 0", - ); - } + if let ty::Int(ity) = cx.typeck_results().expr_ty(right).kind() + && is_integer_const(cx, right, unsext(cx.tcx, -1, *ity)) + { + span_lint( + cx, + MODULO_ONE, + expr.span, + "any number modulo -1 will panic/overflow or result in 0", + ); } } } diff --git a/clippy_lints/src/operators/numeric_arithmetic.rs b/clippy_lints/src/operators/numeric_arithmetic.rs index c261fd9bd9cb0..d0aa5740713c0 100644 --- a/clippy_lints/src/operators/numeric_arithmetic.rs +++ b/clippy_lints/src/operators/numeric_arithmetic.rs @@ -75,10 +75,10 @@ impl Context { hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const { .. } => { let body_span = cx.tcx.hir().span_with_body(body_owner); - if let Some(span) = self.const_span { - if span.contains(body_span) { - return; - } + if let Some(span) = self.const_span + && span.contains(body_span) + { + return; } self.const_span = Some(body_span); }, @@ -90,10 +90,10 @@ impl Context { let body_owner = cx.tcx.hir_body_owner(body.id()); let body_span = cx.tcx.hir().span_with_body(body_owner); - if let Some(span) = self.const_span { - if span.contains(body_span) { - return; - } + if let Some(span) = self.const_span + && span.contains(body_span) + { + return; } self.const_span = None; } diff --git a/clippy_lints/src/operators/op_ref.rs b/clippy_lints/src/operators/op_ref.rs index 6bbc76cbb2a13..0faa7b9e64665 100644 --- a/clippy_lints/src/operators/op_ref.rs +++ b/clippy_lints/src/operators/op_ref.rs @@ -47,12 +47,11 @@ pub(crate) fn check<'tcx>( let rty = cx.typeck_results().expr_ty(r); let lcpy = is_copy(cx, lty); let rcpy = is_copy(cx, rty); - if let Some((self_ty, other_ty)) = in_impl(cx, e, trait_id) { - if (are_equal(cx, rty, self_ty) && are_equal(cx, lty, other_ty)) - || (are_equal(cx, rty, other_ty) && are_equal(cx, lty, self_ty)) - { - return; // Don't lint - } + if let Some((self_ty, other_ty)) = in_impl(cx, e, trait_id) + && ((are_equal(cx, rty, self_ty) && are_equal(cx, lty, other_ty)) + || (are_equal(cx, rty, other_ty) && are_equal(cx, lty, self_ty))) + { + return; // Don't lint } // either operator autorefs or both args are copyable if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty.into()]) { diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 0a8e288564875..5d30b66def2c8 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -178,19 +178,18 @@ impl PassByRefOrValue { && size <= self.ref_min_size && let hir::TyKind::Ref(_, MutTy { ty: decl_ty, .. }) = input.kind { - if let Some(typeck) = cx.maybe_typeck_results() { + if let Some(typeck) = cx.maybe_typeck_results() // Don't lint if a raw pointer is created. // TODO: Limit the check only to raw pointers to the argument (or part of the argument) // which escape the current function. - if typeck.node_types().items().any(|(_, &ty)| ty.is_raw_ptr()) + && (typeck.node_types().items().any(|(_, &ty)| ty.is_raw_ptr()) || typeck .adjustments() .items() .flat_map(|(_, a)| a) - .any(|a| matches!(a.kind, Adjust::Pointer(PointerCoercion::UnsafeFnPointer))) - { - continue; - } + .any(|a| matches!(a.kind, Adjust::Pointer(PointerCoercion::UnsafeFnPointer)))) + { + continue; } let value_type = if fn_body.and_then(|body| body.params.get(index)).is_some_and(is_self) { "self".into() @@ -282,12 +281,11 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue { } let attrs = cx.tcx.hir_attrs(hir_id); for a in attrs { - if let Some(meta_items) = a.meta_item_list() { - if a.has_name(sym::proc_macro_derive) - || (a.has_name(sym::inline) && attr::list_contains_name(&meta_items, sym::always)) - { - return; - } + if let Some(meta_items) = a.meta_item_list() + && (a.has_name(sym::proc_macro_derive) + || (a.has_name(sym::inline) && attr::list_contains_name(&meta_items, sym::always))) + { + return; } } }, @@ -296,13 +294,13 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue { } // Exclude non-inherent impls - if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) { - if matches!( + if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) + && matches!( item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) - ) { - return; - } + ) + { + return; } self.check_poly_fn(cx, def_id, decl, Some(span)); diff --git a/clippy_lints/src/pathbuf_init_then_push.rs b/clippy_lints/src/pathbuf_init_then_push.rs index b653b459b04c8..35caac855cf61 100644 --- a/clippy_lints/src/pathbuf_init_then_push.rs +++ b/clippy_lints/src/pathbuf_init_then_push.rs @@ -173,16 +173,15 @@ impl<'tcx> LateLintPass<'tcx> for PathbufThenPush<'tcx> { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { - if let Some(mut searcher) = self.searcher.take() { - if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind - && let ExprKind::MethodCall(name, self_arg, [arg_expr], _) = expr.kind - && path_to_local_id(self_arg, searcher.local_id) - && name.ident.as_str() == "push" - { - searcher.err_span = searcher.err_span.to(stmt.span); - searcher.arg = Some(*arg_expr); - searcher.display_err(cx); - } + if let Some(mut searcher) = self.searcher.take() + && let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind + && let ExprKind::MethodCall(name, self_arg, [arg_expr], _) = expr.kind + && path_to_local_id(self_arg, searcher.local_id) + && name.ident.as_str() == "push" + { + searcher.err_span = searcher.err_span.to(stmt.span); + searcher.arg = Some(*arg_expr); + searcher.display_err(cx); } } diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs index 8f1a1ee76c6a6..4c5b8a315d020 100644 --- a/clippy_lints/src/pattern_type_mismatch.rs +++ b/clippy_lints/src/pattern_type_mismatch.rs @@ -177,17 +177,16 @@ fn find_first_mismatch(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<(Span, Mut PatKind::Or([p, ..]) => p, _ => p, }; - if let Some(adjustments) = cx.typeck_results().pat_adjustments().get(adjust_pat.hir_id) { - if let [first, ..] = **adjustments { - if let ty::Ref(.., mutability) = *first.kind() { - let level = if p.hir_id == pat.hir_id { - Level::Top - } else { - Level::Lower - }; - result = Some((p.span, mutability, level)); - } - } + if let Some(adjustments) = cx.typeck_results().pat_adjustments().get(adjust_pat.hir_id) + && let [first, ..] = **adjustments + && let ty::Ref(.., mutability) = *first.kind() + { + let level = if p.hir_id == pat.hir_id { + Level::Top + } else { + Level::Lower + }; + result = Some((p.span, mutability, level)); } result.is_none() }); diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 68ae575c9063f..7f74a2fff9f20 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -77,10 +77,10 @@ impl<'tcx> LateLintPass<'tcx> for PtrOffsetWithCast { // If the given expression is a cast from a usize, return the lhs of the cast fn expr_as_cast_from_usize<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { - if let ExprKind::Cast(cast_lhs_expr, _) = expr.kind { - if is_expr_ty_usize(cx, cast_lhs_expr) { - return Some(cast_lhs_expr); - } + if let ExprKind::Cast(cast_lhs_expr, _) = expr.kind + && is_expr_ty_usize(cx, cast_lhs_expr) + { + return Some(cast_lhs_expr); } None } @@ -91,14 +91,14 @@ fn expr_as_ptr_offset_call<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> { - if let ExprKind::MethodCall(path_segment, arg_0, [arg_1], _) = &expr.kind { - if is_expr_ty_raw_ptr(cx, arg_0) { - if path_segment.ident.name == sym::offset { - return Some((arg_0, arg_1, Method::Offset)); - } - if path_segment.ident.name.as_str() == "wrapping_offset" { - return Some((arg_0, arg_1, Method::WrappingOffset)); - } + if let ExprKind::MethodCall(path_segment, arg_0, [arg_1], _) = &expr.kind + && is_expr_ty_raw_ptr(cx, arg_0) + { + if path_segment.ident.name == sym::offset { + return Some((arg_0, arg_1, Method::Offset)); + } + if path_segment.ident.name.as_str() == "wrapping_offset" { + return Some((arg_0, arg_1, Method::WrappingOffset)); } } None diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 83c36d71a9c7f..d292ed86ea4c6 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -179,10 +179,10 @@ impl_lint_pass!(Ranges => [ impl<'tcx> LateLintPass<'tcx> for Ranges { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Binary(ref op, l, r) = expr.kind { - if self.msrv.meets(cx, msrvs::RANGE_CONTAINS) { - check_possible_range_contains(cx, op.node, l, r, expr, expr.span); - } + if let ExprKind::Binary(ref op, l, r) = expr.kind + && self.msrv.meets(cx, msrvs::RANGE_CONTAINS) + { + check_possible_range_contains(cx, op.node, l, r, expr, expr.span); } check_exclusive_range_plus_one(cx, expr); @@ -327,18 +327,18 @@ fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) -> inc: inclusive, }); } - } else if let Some(id) = path_to_local(r) { - if let Some(c) = ConstEvalCtxt::new(cx).eval(l) { - return Some(RangeBounds { - val: c, - expr: l, - id, - name_span: r.span, - val_span: l.span, - ord: ordering.reverse(), - inc: inclusive, - }); - } + } else if let Some(id) = path_to_local(r) + && let Some(c) = ConstEvalCtxt::new(cx).eval(l) + { + return Some(RangeBounds { + val: c, + expr: l, + id, + name_span: r.span, + val_span: l.span, + ord: ordering.reverse(), + inc: inclusive, + }); } } None diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index cfa622aea582f..c9c1a095937b0 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -109,10 +109,10 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { continue; } - if let ty::Adt(def, _) = arg_ty.kind() { - if def.is_manually_drop() { - continue; - } + if let ty::Adt(def, _) = arg_ty.kind() + && def.is_manually_drop() + { + continue; } // `{ arg = &cloned; clone(move arg); }` or `{ arg = &cloned; to_path_buf(arg); }` @@ -191,11 +191,11 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { if clone_usage.cloned_used && clone_usage.clone_consumed_or_mutated { // cloned value is used, and the clone is modified or moved continue; - } else if let Some(loc) = clone_usage.cloned_consume_or_mutate_loc { + } else if let Some(loc) = clone_usage.cloned_consume_or_mutate_loc // cloned value is mutated, and the clone is alive. - if possible_borrower.local_is_alive_at(ret_local, loc) { - continue; - } + && possible_borrower.local_is_alive_at(ret_local, loc) + { + continue; } clone_usage }; @@ -216,14 +216,13 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { let call_snip = &snip[dot + 1..]; // Machine applicable when `call_snip` looks like `foobar()` - if let Some(call_snip) = call_snip.strip_suffix("()").map(str::trim) { - if call_snip + if let Some(call_snip) = call_snip.strip_suffix("()").map(str::trim) + && call_snip .as_bytes() .iter() .all(|b| b.is_ascii_alphabetic() || *b == b'_') - { - app = Applicability::MachineApplicable; - } + { + app = Applicability::MachineApplicable; } span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |diag| { diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs index 7038b19d27596..1117dea703c2a 100644 --- a/clippy_lints/src/redundant_slicing.rs +++ b/clippy_lints/src/redundant_slicing.rs @@ -135,25 +135,24 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { }; diag.span_suggestion(expr.span, help_msg, sugg, app); }); - } else if let Some(target_id) = cx.tcx.lang_items().deref_target() { - if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions( + } else if let Some(target_id) = cx.tcx.lang_items().deref_target() + && let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions( cx.typing_env(), Ty::new_projection_from_args(cx.tcx, target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])), - ) { - if deref_ty == expr_ty { - let (lint, msg) = DEREF_BY_SLICING_LINT; - span_lint_and_then(cx, lint, expr.span, msg, |diag| { - let mut app = Applicability::MachineApplicable; - let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; - let sugg = if needs_parens_for_prefix { - format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count)) - } else { - format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count)) - }; - diag.span_suggestion(expr.span, "dereference the original value instead", sugg, app); - }); - } - } + ) + && deref_ty == expr_ty + { + let (lint, msg) = DEREF_BY_SLICING_LINT; + span_lint_and_then(cx, lint, expr.span, msg, |diag| { + let mut app = Applicability::MachineApplicable; + let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; + let sugg = if needs_parens_for_prefix { + format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count)) + } else { + format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count)) + }; + diag.span_suggestion(expr.span, "dereference the original value instead", sugg, app); + }); } } } diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index 6a0dfde2d9c9c..a8c6518b592ba 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -32,28 +32,28 @@ impl<'tcx> LateLintPass<'tcx> for SerdeApi { }) = item.kind { let did = trait_ref.path.res.def_id(); - if let Some(visit_did) = get_trait_def_id(cx.tcx, &paths::SERDE_DE_VISITOR) { - if did == visit_did { - let mut seen_str = None; - let mut seen_string = None; - for item in *items { - match item.ident.as_str() { - "visit_str" => seen_str = Some(item.span), - "visit_string" => seen_string = Some(item.span), - _ => {}, - } - } - if let Some(span) = seen_string { - if seen_str.is_none() { - span_lint( - cx, - SERDE_API_MISUSE, - span, - "you should not implement `visit_string` without also implementing `visit_str`", - ); - } + if let Some(visit_did) = get_trait_def_id(cx.tcx, &paths::SERDE_DE_VISITOR) + && did == visit_did + { + let mut seen_str = None; + let mut seen_string = None; + for item in *items { + match item.ident.as_str() { + "visit_str" => seen_str = Some(item.span), + "visit_string" => seen_string = Some(item.span), + _ => {}, } } + if let Some(span) = seen_string + && seen_str.is_none() + { + span_lint( + cx, + SERDE_API_MISUSE, + span, + "you should not implement `visit_string` without also implementing `visit_str`", + ); + } } } } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 3795c7483da4d..8194552c53f95 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -167,10 +167,10 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { fn is_shadow(cx: &LateContext<'_>, owner: LocalDefId, first: ItemLocalId, second: ItemLocalId) -> bool { let scope_tree = cx.tcx.region_scope_tree(owner.to_def_id()); - if let Some(first_scope) = scope_tree.var_scope(first) { - if let Some(second_scope) = scope_tree.var_scope(second) { - return scope_tree.is_subscope_of(second_scope, first_scope); - } + if let Some(first_scope) = scope_tree.var_scope(first) + && let Some(second_scope) = scope_tree.var_scope(second) + { + return scope_tree.is_subscope_of(second_scope, first_scope); } false diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index e9db7c9d031a9..c705609c8405e 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -181,10 +181,10 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> { } } for generic_arg in *b { - if let GenericArgKind::Type(ty) = generic_arg.unpack() { - if self.has_sig_drop_attr(ty) { - return true; - } + if let GenericArgKind::Type(ty) = generic_arg.unpack() + && self.has_sig_drop_attr(ty) + { + return true; } } false diff --git a/clippy_lints/src/single_char_lifetime_names.rs b/clippy_lints/src/single_char_lifetime_names.rs index 50a6ee316c8a6..8c34da0d14a4d 100644 --- a/clippy_lints/src/single_char_lifetime_names.rs +++ b/clippy_lints/src/single_char_lifetime_names.rs @@ -45,19 +45,20 @@ impl EarlyLintPass for SingleCharLifetimeNames { return; } - if let GenericParamKind::Lifetime = param.kind { - if !param.is_placeholder && param.ident.as_str().len() <= 2 { - #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] - span_lint_and_then( - ctx, - SINGLE_CHAR_LIFETIME_NAMES, - param.ident.span, - "single-character lifetime names are likely uninformative", - |diag| { - diag.help("use a more informative name"); - }, - ); - } + if let GenericParamKind::Lifetime = param.kind + && !param.is_placeholder + && param.ident.as_str().len() <= 2 + { + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( + ctx, + SINGLE_CHAR_LIFETIME_NAMES, + param.ident.span, + "single-character lifetime names are likely uninformative", + |diag| { + diag.help("use a more informative name"); + }, + ); } } } diff --git a/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs index fa08245350429..82f2f30676868 100644 --- a/clippy_lints/src/single_component_path_imports.rs +++ b/clippy_lints/src/single_component_path_imports.rs @@ -204,17 +204,17 @@ impl SingleComponentPathImports { if let UseTreeKind::Nested { items, .. } = &use_tree.kind { for tree in items { let segments = &tree.0.prefix.segments; - if segments.len() == 1 { - if let UseTreeKind::Simple(None) = tree.0.kind { - let name = segments[0].ident.name; - if !macros.contains(&name) { - single_use_usages.push(SingleUse { - name, - span: tree.0.span, - item_id: item.id, - can_suggest: false, - }); - } + if segments.len() == 1 + && let UseTreeKind::Simple(None) = tree.0.kind + { + let name = segments[0].ident.name; + if !macros.contains(&name) { + single_use_usages.push(SingleUse { + name, + span: tree.0.span, + item_id: item.id, + can_suggest: false, + }); } } } diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 27c548bed9f64..dd819510f84ca 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -162,13 +162,12 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd { if is_string(cx, left) { if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) { let parent = get_parent_expr(cx, e); - if let Some(p) = parent { - if let ExprKind::Assign(target, _, _) = p.kind { + if let Some(p) = parent + && let ExprKind::Assign(target, _, _) = p.kind // avoid duplicate matches - if SpanlessEq::new(cx).eq_expr(target, left) { - return; - } - } + && SpanlessEq::new(cx).eq_expr(target, left) + { + return; } } span_lint( diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index d1486c2c246e1..caab4e66a70c8 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -269,12 +269,11 @@ fn parse<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(ExprOrIdent<'hir>, &'a Expr< if let ExprKind::Assign(lhs, rhs, _) = expr.kind { return Some((ExprOrIdent::Expr(lhs), rhs)); } - } else if let StmtKind::Let(expr) = stmt.kind { - if let Some(rhs) = expr.init { - if let PatKind::Binding(_, _, ident_l, _) = expr.pat.kind { - return Some((ExprOrIdent::Ident(ident_l), rhs)); - } - } + } else if let StmtKind::Let(expr) = stmt.kind + && let Some(rhs) = expr.init + && let PatKind::Binding(_, _, ident_l, _) = expr.pat.kind + { + return Some((ExprOrIdent::Ident(ident_l), rhs)); } None } diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index fa36c9a21f65e..8aac3a5910294 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -151,20 +151,19 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { .iter() .filter_map(get_trait_info_from_bound) .for_each(|(trait_item_res, trait_item_segments, span)| { - if let Some(self_segments) = self_bounds_map.get(&trait_item_res) { - if SpanlessEq::new(cx) + if let Some(self_segments) = self_bounds_map.get(&trait_item_res) + && SpanlessEq::new(cx) .paths_by_resolution() .eq_path_segments(self_segments, trait_item_segments) - { - span_lint_and_help( - cx, - TRAIT_DUPLICATION_IN_BOUNDS, - span, - "this trait bound is already specified in trait declaration", - None, - "consider removing this trait bound", - ); - } + { + span_lint_and_help( + cx, + TRAIT_DUPLICATION_IN_BOUNDS, + span, + "this trait bound is already specified in trait declaration", + None, + "consider removing this trait bound", + ); } }); } diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index b6f4c4d7f0a41..3147058b4cda0 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -591,26 +591,26 @@ impl Types { TyKind::Path(ref qpath) if !context.in_body => { let hir_id = hir_ty.hir_id; let res = cx.qpath_res(qpath, hir_id); - if let Some(def_id) = res.opt_def_id() { - if self.is_type_change_allowed(context) { - // All lints that are being checked in this block are guarded by - // the `avoid_breaking_exported_api` configuration. When adding a - // new lint, please also add the name to the configuration documentation - // in `clippy_config::conf` - - let mut triggered = false; - triggered |= box_collection::check(cx, hir_ty, qpath, def_id); - triggered |= redundant_allocation::check(cx, hir_ty, qpath, def_id); - triggered |= rc_buffer::check(cx, hir_ty, qpath, def_id); - triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold); - triggered |= option_option::check(cx, hir_ty, qpath, def_id); - triggered |= linked_list::check(cx, hir_ty, def_id); - triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id); - triggered |= owned_cow::check(cx, qpath, def_id); - - if triggered { - return; - } + if let Some(def_id) = res.opt_def_id() + && self.is_type_change_allowed(context) + { + // All lints that are being checked in this block are guarded by + // the `avoid_breaking_exported_api` configuration. When adding a + // new lint, please also add the name to the configuration documentation + // in `clippy_config::conf` + + let mut triggered = false; + triggered |= box_collection::check(cx, hir_ty, qpath, def_id); + triggered |= redundant_allocation::check(cx, hir_ty, qpath, def_id); + triggered |= rc_buffer::check(cx, hir_ty, qpath, def_id); + triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold); + triggered |= option_option::check(cx, hir_ty, qpath, def_id); + triggered |= linked_list::check(cx, hir_ty, def_id); + triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id); + triggered |= owned_cow::check(cx, qpath, def_id); + + if triggered { + return; } } match *qpath { diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index e1fc644e4ceeb..79571b0409d21 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -76,10 +76,10 @@ declare_lint_pass!(Unicode => [INVISIBLE_CHARACTERS, NON_ASCII_LITERAL, UNICODE_ impl LateLintPass<'_> for Unicode { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { - if let ExprKind::Lit(lit) = expr.kind { - if let LitKind::Str(_, _) | LitKind::Char(_) = lit.node { - check_str(cx, lit.span, expr.hir_id); - } + if let ExprKind::Lit(lit) = expr.kind + && let LitKind::Str(_, _) | LitKind::Char(_) = lit.node + { + check_str(cx, lit.span, expr.hir_id); } } } diff --git a/clippy_lints/src/unnecessary_wraps.rs b/clippy_lints/src/unnecessary_wraps.rs index 937e35dea96d9..bcd05cceca9c3 100644 --- a/clippy_lints/src/unnecessary_wraps.rs +++ b/clippy_lints/src/unnecessary_wraps.rs @@ -93,13 +93,13 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { // Abort if the method is implementing a trait or of it a trait method. let hir_id = cx.tcx.local_def_id_to_hir_id(def_id); - if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) { - if matches!( + if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) + && matches!( item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) - ) { - return; - } + ) + { + return; } // Get the wrapper and inner types, if can't, abort. diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index f43715d6752e3..535dec7fa977b 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -69,10 +69,10 @@ impl EarlyLintPass for UnnestedOrPatterns { } fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { - if self.msrv.meets(msrvs::OR_PATTERNS) { - if let ast::ExprKind::Let(pat, _, _, _) = &e.kind { - lint_unnested_or_patterns(cx, pat); - } + if self.msrv.meets(msrvs::OR_PATTERNS) + && let ast::ExprKind::Let(pat, _, _, _) = &e.kind + { + lint_unnested_or_patterns(cx, pat); } } diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 0687fc319af68..2d88c490b1abe 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -265,15 +265,14 @@ fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { /// If `expr` is an (e).await, return the inner expression "e" that's being /// waited on. Otherwise return None. fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { - if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind { - if let ExprKind::Call(func, [arg_0]) = expr.kind { - if matches!( - func.kind, - ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..)) - ) { - return arg_0; - } - } + if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind + && let ExprKind::Call(func, [arg_0]) = expr.kind + && matches!( + func.kind, + ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..)) + ) + { + return arg_0; } expr } diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 972c1adbd40ae..3a9c997a579d1 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -92,36 +92,36 @@ fn into_iter_bound<'tcx>( let mut into_iter_span = None; for (pred, span) in cx.tcx.explicit_predicates_of(fn_did).predicates { - if let ty::ClauseKind::Trait(tr) = pred.kind().skip_binder() { - if tr.self_ty().is_param(param_index) { - if tr.def_id() == into_iter_did { - into_iter_span = Some(*span); - } else { - let tr = cx.tcx.erase_regions(tr); - if tr.has_escaping_bound_vars() { - return None; - } - - // Substitute generics in the predicate and replace the IntoIterator type parameter with the - // `.into_iter()` receiver to see if the bound also holds for that type. - let args = cx.tcx.mk_args_from_iter(node_args.iter().enumerate().map(|(i, arg)| { - if i == param_index as usize { - GenericArg::from(into_iter_receiver) - } else { - arg - } - })); + if let ty::ClauseKind::Trait(tr) = pred.kind().skip_binder() + && tr.self_ty().is_param(param_index) + { + if tr.def_id() == into_iter_did { + into_iter_span = Some(*span); + } else { + let tr = cx.tcx.erase_regions(tr); + if tr.has_escaping_bound_vars() { + return None; + } - let predicate = EarlyBinder::bind(tr).instantiate(cx.tcx, args); - let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); - if !cx - .tcx - .infer_ctxt() - .build(cx.typing_mode()) - .predicate_must_hold_modulo_regions(&obligation) - { - return None; + // Substitute generics in the predicate and replace the IntoIterator type parameter with the + // `.into_iter()` receiver to see if the bound also holds for that type. + let args = cx.tcx.mk_args_from_iter(node_args.iter().enumerate().map(|(i, arg)| { + if i == param_index as usize { + GenericArg::from(into_iter_receiver) + } else { + arg } + })); + + let predicate = EarlyBinder::bind(tr).instantiate(cx.tcx, args); + let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); + if !cx + .tcx + .infer_ctxt() + .build(cx.typing_mode()) + .predicate_must_hold_modulo_regions(&obligation) + { + return None; } } } diff --git a/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs index e454427adde1b..044894f827932 100644 --- a/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs +++ b/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs @@ -107,48 +107,48 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol { Applicability::MachineApplicable, ); } - if let ExprKind::Binary(op, left, right) = expr.kind { - if matches!(op.node, BinOpKind::Eq | BinOpKind::Ne) { - let data = [ - (left, self.symbol_str_expr(left, cx)), - (right, self.symbol_str_expr(right, cx)), - ]; - match data { - // both operands are a symbol string - [(_, Some(left)), (_, Some(right))] => { + if let ExprKind::Binary(op, left, right) = expr.kind + && matches!(op.node, BinOpKind::Eq | BinOpKind::Ne) + { + let data = [ + (left, self.symbol_str_expr(left, cx)), + (right, self.symbol_str_expr(right, cx)), + ]; + match data { + // both operands are a symbol string + [(_, Some(left)), (_, Some(right))] => { + span_lint_and_sugg( + cx, + UNNECESSARY_SYMBOL_STR, + expr.span, + "unnecessary `Symbol` to string conversion", + "try", + format!( + "{} {} {}", + left.as_symbol_snippet(cx), + op.node.as_str(), + right.as_symbol_snippet(cx), + ), + Applicability::MachineApplicable, + ); + }, + // one of the operands is a symbol string + [(expr, Some(symbol)), _] | [_, (expr, Some(symbol))] => { + // creating an owned string for comparison + if matches!(symbol, SymbolStrExpr::Expr { is_to_owned: true, .. }) { span_lint_and_sugg( cx, UNNECESSARY_SYMBOL_STR, expr.span, - "unnecessary `Symbol` to string conversion", + "unnecessary string allocation", "try", - format!( - "{} {} {}", - left.as_symbol_snippet(cx), - op.node.as_str(), - right.as_symbol_snippet(cx), - ), + format!("{}.as_str()", symbol.as_symbol_snippet(cx)), Applicability::MachineApplicable, ); - }, - // one of the operands is a symbol string - [(expr, Some(symbol)), _] | [_, (expr, Some(symbol))] => { - // creating an owned string for comparison - if matches!(symbol, SymbolStrExpr::Expr { is_to_owned: true, .. }) { - span_lint_and_sugg( - cx, - UNNECESSARY_SYMBOL_STR, - expr.span, - "unnecessary string allocation", - "try", - format!("{}.as_str()", symbol.as_symbol_snippet(cx)), - Applicability::MachineApplicable, - ); - } - }, - // nothing found - [(_, None), (_, None)] => {}, - } + } + }, + // nothing found + [(_, None), (_, None)] => {}, } } } diff --git a/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/clippy_lints/src/utils/internal_lints/invalid_paths.rs index 252ac5e676822..5e1872ad97521 100644 --- a/clippy_lints/src/utils/internal_lints/invalid_paths.rs +++ b/clippy_lints/src/utils/internal_lints/invalid_paths.rs @@ -80,22 +80,22 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool { .copied(); for item_def_id in lang_items.iter().map(|(_, def_id)| def_id).chain(incoherent_impls) { let lang_item_path = cx.get_def_path(item_def_id); - if path_syms.starts_with(&lang_item_path) { - if let [item] = &path_syms[lang_item_path.len()..] { - if matches!( - cx.tcx.def_kind(item_def_id), - DefKind::Mod | DefKind::Enum | DefKind::Trait - ) { - for child in cx.tcx.module_children(item_def_id) { - if child.ident.name == *item { - return true; - } + if path_syms.starts_with(&lang_item_path) + && let [item] = &path_syms[lang_item_path.len()..] + { + if matches!( + cx.tcx.def_kind(item_def_id), + DefKind::Mod | DefKind::Enum | DefKind::Trait + ) { + for child in cx.tcx.module_children(item_def_id) { + if child.ident.name == *item { + return true; } - } else { - for child in cx.tcx.associated_item_def_ids(item_def_id) { - if cx.tcx.item_name(*child) == *item { - return true; - } + } + } else { + for child in cx.tcx.associated_item_def_ids(item_def_id) { + if cx.tcx.item_name(*child) == *item { + return true; } } } diff --git a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index 94a2e598522b2..bee05e52ed26a 100644 --- a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -205,12 +205,10 @@ pub(super) fn is_lint_ref_type(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { mutbl: Mutability::Not, }, ) = ty.kind + && let TyKind::Path(ref path) = inner.kind + && let Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, inner.hir_id) { - if let TyKind::Path(ref path) = inner.kind { - if let Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, inner.hir_id) { - return match_def_path(cx, def_id, &paths::LINT); - } - } + return match_def_path(cx, def_id, &paths::LINT); } false diff --git a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs index 76b0a52621be4..3790805df35ac 100644 --- a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs +++ b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs @@ -281,10 +281,10 @@ fn path_from_array(exprs: &[Expr<'_>]) -> Option> { exprs .iter() .map(|expr| { - if let ExprKind::Lit(lit) = &expr.kind { - if let LitKind::Str(sym, _) = lit.node { - return Some((*sym.as_str()).to_owned()); - } + if let ExprKind::Lit(lit) = &expr.kind + && let LitKind::Str(sym, _) = lit.node + { + return Some((*sym.as_str()).to_owned()); } None diff --git a/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs b/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs index a5c4bf474f7aa..d4c0df1700d39 100644 --- a/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs +++ b/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs @@ -21,28 +21,26 @@ declare_lint_pass!(UnsortedClippyUtilsPaths => [UNSORTED_CLIPPY_UTILS_PATHS]); impl EarlyLintPass for UnsortedClippyUtilsPaths { fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { - if let Some(utils) = krate.items.iter().find(|item| item.ident.name.as_str() == "utils") { - if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = utils.kind { - if let Some(paths) = items.iter().find(|item| item.ident.name.as_str() == "paths") { - if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = paths.kind { - let mut last_name: Option<&str> = None; - for item in items { - let name = item.ident.as_str(); - if let Some(last_name) = last_name { - if *last_name > *name { - span_lint( - cx, - UNSORTED_CLIPPY_UTILS_PATHS, - item.span, - "this constant should be before the previous constant due to lexical \ + if let Some(utils) = krate.items.iter().find(|item| item.ident.name.as_str() == "utils") + && let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = utils.kind + && let Some(paths) = items.iter().find(|item| item.ident.name.as_str() == "paths") + && let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = paths.kind + { + let mut last_name: Option<&str> = None; + for item in items { + let name = item.ident.as_str(); + if let Some(last_name) = last_name + && *last_name > *name + { + span_lint( + cx, + UNSORTED_CLIPPY_UTILS_PATHS, + item.span, + "this constant should be before the previous constant due to lexical \ ordering", - ); - } - } - last_name = Some(name); - } - } + ); } + last_name = Some(name); } } } diff --git a/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs index f6948be7f67aa..a97643e0eaca5 100644 --- a/clippy_lints/src/zero_sized_map_values.rs +++ b/clippy_lints/src/zero_sized_map_values.rs @@ -74,10 +74,10 @@ impl LateLintPass<'_> for ZeroSizedMapValues { fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool { let parent_id = cx.tcx.hir_get_parent_item(hir_id); let second_parent_id = cx.tcx.hir_get_parent_item(parent_id.into()).def_id; - if let Node::Item(item) = cx.tcx.hir_node_by_def_id(second_parent_id) { - if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind { - return true; - } + if let Node::Item(item) = cx.tcx.hir_node_by_def_id(second_parent_id) + && let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind + { + return true; } false } diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs index 292792408c642..cd2098a89891d 100644 --- a/clippy_utils/src/diagnostics.rs +++ b/clippy_utils/src/diagnostics.rs @@ -17,16 +17,16 @@ use rustc_span::Span; use std::env; fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) { - if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { - if let Some(lint) = lint.name_lower().strip_prefix("clippy::") { - diag.help(format!( - "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{lint}", - &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| { - // extract just major + minor version and ignore patch versions - format!("rust-{}", n.rsplit_once('.').unwrap().1) - }) - )); - } + if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() + && let Some(lint) = lint.name_lower().strip_prefix("clippy::") + { + diag.help(format!( + "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{lint}", + &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| { + // extract just major + minor version and ignore patch versions + format!("rust-{}", n.rsplit_once('.').unwrap().1) + }) + )); } } diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs index 852378d50e8b4..d4e66ebd8e1fb 100644 --- a/clippy_utils/src/higher.rs +++ b/clippy_utils/src/higher.rs @@ -118,18 +118,17 @@ impl<'hir> IfLet<'hir> { ) = expr.kind { let mut iter = cx.tcx.hir_parent_iter(expr.hir_id); - if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next() { - if let Some(( + if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next() + && let Some(( _, Node::Expr(Expr { kind: ExprKind::Loop(_, _, LoopSource::While, _), .. }), )) = iter.next() - { - // while loop desugar - return None; - } + { + // while loop desugar + return None; } return Some(Self { let_pat, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 5f39af811cd99..e8ec42e0662bd 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -367,10 +367,10 @@ pub fn is_inherent_method_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// Checks if a method is defined in an impl of a diagnostic item pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool { - if let Some(impl_did) = cx.tcx.impl_of_method(def_id) { - if let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() { - return cx.tcx.is_diagnostic_item(diag_item, adt.did()); - } + if let Some(impl_did) = cx.tcx.impl_of_method(def_id) + && let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() + { + return cx.tcx.is_diagnostic_item(diag_item, adt.did()); } false } @@ -457,10 +457,10 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool { QPath::Resolved(_, path) => match_path(path, segments), QPath::TypeRelative(ty, segment) => match ty.kind { TyKind::Path(ref inner_path) => { - if let [prefix @ .., end] = segments { - if match_qpath(inner_path, prefix) { - return segment.ident.name.as_str() == *end; - } + if let [prefix @ .., end] = segments + && match_qpath(inner_path, prefix) + { + return segment.ident.name.as_str() == *end; } false }, @@ -523,10 +523,10 @@ pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool { /// If the expression is a path to a local, returns the canonical `HirId` of the local. pub fn path_to_local(expr: &Expr<'_>) -> Option { - if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind { - if let Res::Local(id) = path.res { - return Some(id); - } + if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind + && let Res::Local(id) = path.res + { + return Some(id); } None } @@ -893,16 +893,14 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath< sym::BinaryHeap, ]; - if let QPath::TypeRelative(_, method) = path { - if method.ident.name == sym::new { - if let Some(impl_did) = cx.tcx.impl_of_method(def_id) { - if let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() { - return std_types_symbols.iter().any(|&symbol| { - cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string() - }); - } - } - } + if let QPath::TypeRelative(_, method) = path + && method.ident.name == sym::new + && let Some(impl_did) = cx.tcx.impl_of_method(def_id) + && let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() + { + return std_types_symbols.iter().any(|&symbol| { + cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string() + }); } false } @@ -1204,12 +1202,10 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind { .adjustments() .get(child_id) .map_or(&[][..], |x| &**x) - { - if let rustc_ty::RawPtr(_, mutability) | rustc_ty::Ref(_, _, mutability) = + && let rustc_ty::RawPtr(_, mutability) | rustc_ty::Ref(_, _, mutability) = *adjust.last().map_or(target, |a| a.target).kind() - { - return CaptureKind::Ref(mutability); - } + { + return CaptureKind::Ref(mutability); } match parent { @@ -1737,10 +1733,10 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool /// Checks whether the given expression is a constant literal of the given value. pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool { // FIXME: use constant folding - if let ExprKind::Lit(spanned) = expr.kind { - if let LitKind::Int(v, _) = spanned.node { - return v == value; - } + if let ExprKind::Lit(spanned) = expr.kind + && let LitKind::Int(v, _) = spanned.node + { + return v == value; } false } @@ -1777,10 +1773,10 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option { let data = span.ctxt().outer_expn_data(); let new_span = data.call_site; - if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind { - if mac_name.as_str() == name { - return Some(new_span); - } + if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind + && mac_name.as_str() == name + { + return Some(new_span); } span = new_span; @@ -1806,10 +1802,10 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option { let data = span.ctxt().outer_expn_data(); let new_span = data.call_site; - if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind { - if mac_name.as_str() == name { - return Some(new_span); - } + if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind + && mac_name.as_str() == name + { + return Some(new_span); } } @@ -1830,15 +1826,15 @@ pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_def_id: OwnerId, nth: usize) -> /// Checks if an expression is constructing a tuple-like enum variant or struct pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - if let ExprKind::Call(fun, _) = expr.kind { - if let ExprKind::Path(ref qp) = fun.kind { - let res = cx.qpath_res(qp, fun.hir_id); - return match res { - Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true, - Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id), - _ => false, - }; - } + if let ExprKind::Call(fun, _) = expr.kind + && let ExprKind::Path(ref qp) = fun.kind + { + let res = cx.qpath_res(qp, fun.hir_id); + return match res { + Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true, + Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id), + _ => false, + }; } false } @@ -1911,10 +1907,10 @@ pub fn is_self(slf: &Param<'_>) -> bool { } pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool { - if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind { - if let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path.res { - return true; - } + if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind + && let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path.res + { + return true; } false } @@ -2119,10 +2115,10 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, } // final `else {..}` - if !blocks.is_empty() { - if let ExprKind::Block(block, _) = expr.kind { - blocks.push(block); - } + if !blocks.is_empty() + && let ExprKind::Block(block, _) = expr.kind + { + blocks.push(block); } (conds, blocks) @@ -2139,8 +2135,8 @@ pub fn is_async_fn(kind: FnKind<'_>) -> bool { /// Peels away all the compiler generated code surrounding the body of an async function, pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> { - if let ExprKind::Closure(&Closure { body, .. }) = body.value.kind { - if let ExprKind::Block( + if let ExprKind::Closure(&Closure { body, .. }) = body.value.kind + && let ExprKind::Block( Block { stmts: [], expr: @@ -2152,9 +2148,8 @@ pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'t }, _, ) = tcx.hir_body(body).value.kind - { - return Some(expr); - } + { + return Some(expr); } None } @@ -2628,10 +2623,10 @@ pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir> } pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { - if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind { - if let Res::Def(_, def_id) = path.res { - return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr); - } + if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind + && let Res::Def(_, def_id) = path.res + { + return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr); } false } @@ -2650,18 +2645,16 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym if matches!(tcx.def_kind(id.owner_id), DefKind::Const) && let item = tcx.hir_item(id) && let ItemKind::Const(ident, ty, _generics, _body) = item.kind - { - if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind { + && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind // We could also check for the type name `test::TestDescAndFn` - if let Res::Def(DefKind::Struct, _) = path.res { - let has_test_marker = tcx - .hir_attrs(item.hir_id()) - .iter() - .any(|a| a.has_name(sym::rustc_test_marker)); - if has_test_marker { - names.push(ident.name); - } - } + && let Res::Def(DefKind::Struct, _) = path.res + { + let has_test_marker = tcx + .hir_attrs(item.hir_id()) + .iter() + .any(|a| a.has_name(sym::rustc_test_marker)); + if has_test_marker { + names.push(ident.name); } } } @@ -2682,12 +2675,12 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool { // Since you can nest functions we need to collect all until we leave // function scope .any(|(_id, node)| { - if let Node::Item(item) = node { - if let ItemKind::Fn { ident, .. } = item.kind { - // Note that we have sorted the item names in the visitor, - // so the binary_search gets the same as `contains`, but faster. - return names.binary_search(&ident.name).is_ok(); - } + if let Node::Item(item) = node + && let ItemKind::Fn { ident, .. } = item.kind + { + // Note that we have sorted the item names in the visitor, + // so the binary_search gets the same as `contains`, but faster. + return names.binary_search(&ident.name).is_ok(); } false }) diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs index 80066e9702d34..56e81dbd59ee7 100644 --- a/clippy_utils/src/source.rs +++ b/clippy_utils/src/source.rs @@ -384,10 +384,10 @@ pub fn snippet_indent(sess: &impl HasSession, span: Span) -> Option { // For some reason these attributes don't have any expansion info on them, so // we have to check it this way until there is a better way. pub fn is_present_in_source(sess: &impl HasSession, span: Span) -> bool { - if let Some(snippet) = snippet_opt(sess, span) { - if snippet.is_empty() { - return false; - } + if let Some(snippet) = snippet_opt(sess, span) + && snippet.is_empty() + { + return false; } true } @@ -408,11 +408,11 @@ pub fn position_before_rarrow(s: &str) -> Option { let mut rpos = rpos; let chars: Vec = s.chars().collect(); while rpos > 1 { - if let Some(c) = chars.get(rpos - 1) { - if c.is_whitespace() { - rpos -= 1; - continue; - } + if let Some(c) = chars.get(rpos - 1) + && c.is_whitespace() + { + rpos -= 1; + continue; } break; } diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 1b35d86146d06..f1d1936f9fbd2 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -947,11 +947,10 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { // some items do not need explicit deref, such as array accesses, // so we mark them as already processed // i.e.: don't suggest `*sub[1..4].len()` for `|sub| sub[1..4].len() == 3` - if let ty::Ref(_, inner, _) = cmt.place.ty_before_projection(i).kind() { - if matches!(inner.kind(), ty::Ref(_, innermost, _) if innermost.is_array()) { + if let ty::Ref(_, inner, _) = cmt.place.ty_before_projection(i).kind() + && matches!(inner.kind(), ty::Ref(_, innermost, _) if innermost.is_array()) { projections_handled = true; } - } }, } }); diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 99650d0292faf..a72414f2aff5a 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -128,10 +128,10 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' // For `impl Trait`, it will register a predicate of `::Assoc = U`, // so we check the term for `U`. ty::ClauseKind::Projection(projection_predicate) => { - if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() { - if contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) { - return true; - } + if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() + && contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) + { + return true; } }, _ => (), @@ -337,20 +337,20 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { ty::Tuple(args) => args.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => { for (predicate, _) in cx.tcx.explicit_item_self_bounds(def_id).skip_binder() { - if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() { - if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { - return true; - } + if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() + && cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) + { + return true; } } false }, ty::Dynamic(binder, _, _) => { for predicate in *binder { - if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { - if cx.tcx.has_attr(trait_ref.def_id, sym::must_use) { - return true; - } + if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() + && cx.tcx.has_attr(trait_ref.def_id, sym::must_use) + { + return true; } } false diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs index a079fd940c009..1b049b6d12c4c 100644 --- a/clippy_utils/src/usage.rs +++ b/clippy_utils/src/usage.rs @@ -126,10 +126,10 @@ impl<'tcx> Visitor<'tcx> for BindingUsageFinder<'_, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; fn visit_path(&mut self, path: &hir::Path<'tcx>, _: HirId) -> Self::Result { - if let Res::Local(id) = path.res { - if self.binding_ids.contains(&id) { - return ControlFlow::Break(()); - } + if let Res::Local(id) = path.res + && self.binding_ids.contains(&id) + { + return ControlFlow::Break(()); } ControlFlow::Continue(()) diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 63dd00f2de0fb..fc6e30a980476 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -297,10 +297,10 @@ where /// Checks if the given resolved path is used in the given body. pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool { for_each_expr(cx, cx.tcx.hir_body(body).value, |e| { - if let ExprKind::Path(p) = &e.kind { - if cx.qpath_res(p, e.hir_id) == res { - return ControlFlow::Break(()); - } + if let ExprKind::Path(p) = &e.kind + && cx.qpath_res(p, e.hir_id) == res + { + return ControlFlow::Break(()); } ControlFlow::Continue(()) }) diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs index c8b4a2c9e2073..fe488ef89da1f 100644 --- a/lintcheck/src/main.rs +++ b/lintcheck/src/main.rs @@ -467,10 +467,10 @@ fn get_perf_data_filename(source_path: &Path) -> String { .for_each(|path| { let file_name = path.file_name(); let file_name = file_name.as_os_str().to_str().unwrap().split('.').next_back().unwrap(); - if let Ok(parsed_file_name) = file_name.parse::() { - if parsed_file_name >= max_number { - max_number = parsed_file_name + 1; - } + if let Ok(parsed_file_name) = file_name.parse::() + && parsed_file_name >= max_number + { + max_number = parsed_file_name + 1; } }); return format!("perf.data.{max_number}"); diff --git a/src/driver.rs b/src/driver.rs index e4092bcd10564..c6b3c06baa419 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -207,12 +207,12 @@ pub fn main() { // Beside checking for existence of `--sysroot` on the command line, we need to // check for the arg files that are prefixed with @ as well to be consistent with rustc for arg in args.iter() { - if let Some(arg_file_path) = arg.strip_prefix('@') { - if let Ok(arg_file) = read_to_string(arg_file_path) { - let split_arg_file: Vec = arg_file.lines().map(ToString::to_string).collect(); - if has_arg(&split_arg_file, "--sysroot") { - return true; - } + if let Some(arg_file_path) = arg.strip_prefix('@') + && let Ok(arg_file) = read_to_string(arg_file_path) + { + let split_arg_file: Vec = arg_file.lines().map(ToString::to_string).collect(); + if has_arg(&split_arg_file, "--sysroot") { + return true; } } } @@ -221,10 +221,10 @@ pub fn main() { let sys_root_env = std::env::var("SYSROOT").ok(); let pass_sysroot_env_if_given = |args: &mut Vec, sys_root_env| { - if let Some(sys_root) = sys_root_env { - if !has_sysroot_arg(args) { - args.extend(vec!["--sysroot".into(), sys_root]); - } + if let Some(sys_root) = sys_root_env + && !has_sysroot_arg(args) + { + args.extend(vec!["--sysroot".into(), sys_root]); } }; diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 956a05288f358..a9ba382daf279 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -86,13 +86,13 @@ fn extern_flags() -> Vec { let name = name.strip_prefix("lib").unwrap_or(name); Some((name, path_str)) }; - if let Some((name, path)) = parse_name_path() { - if TEST_DEPENDENCIES.contains(&name) { - // A dependency may be listed twice if it is available in sysroot, - // and the sysroot dependencies are listed first. As of the writing, - // this only seems to apply to if_chain. - crates.insert(name, path); - } + if let Some((name, path)) = parse_name_path() + && TEST_DEPENDENCIES.contains(&name) + { + // A dependency may be listed twice if it is available in sysroot, + // and the sysroot dependencies are listed first. As of the writing, + // this only seems to apply to if_chain. + crates.insert(name, path); } } let not_found: Vec<&str> = TEST_DEPENDENCIES 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 0336/2248] 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 781949d68b7393d35e02e7acca6a7d523af1cef8 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 27 Mar 2025 21:27:15 +0100 Subject: [PATCH 0337/2248] Use char::is_whitespace directly in str::trim* --- library/core/src/str/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 5cc08f8a71afb..4de5ce89b1338 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2115,7 +2115,7 @@ impl str { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "str_trim"] pub fn trim(&self) -> &str { - self.trim_matches(|c: char| c.is_whitespace()) + self.trim_matches(char::is_whitespace) } /// Returns a string slice with leading whitespace removed. @@ -2154,7 +2154,7 @@ impl str { #[stable(feature = "trim_direction", since = "1.30.0")] #[rustc_diagnostic_item = "str_trim_start"] pub fn trim_start(&self) -> &str { - self.trim_start_matches(|c: char| c.is_whitespace()) + self.trim_start_matches(char::is_whitespace) } /// Returns a string slice with trailing whitespace removed. @@ -2193,7 +2193,7 @@ impl str { #[stable(feature = "trim_direction", since = "1.30.0")] #[rustc_diagnostic_item = "str_trim_end"] pub fn trim_end(&self) -> &str { - self.trim_end_matches(|c: char| c.is_whitespace()) + self.trim_end_matches(char::is_whitespace) } /// Returns a string slice with leading whitespace removed. From 65624d9ea5c2aee3f3c7729f3b8d72c0920df6e6 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 26 Mar 2025 20:32:14 -0500 Subject: [PATCH 0338/2248] 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 01820a9efe3d7d09d858483f15fcd38b8cf2cab9 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 27 Mar 2025 20:44:03 +0100 Subject: [PATCH 0339/2248] Do not make incomplete or invalid suggestions The `unnecessary_filter_map` and `unnecessary_find_map` lints were making partial suggestions, proposing to replace the whole expression by only the method name, or a subexpression which contained explicit placeholders. Since even `MaybeIncorrect` suggestions must generate code that compiles, this changes those lints to recommandation lints with no code suggestion. --- .../src/methods/unnecessary_filter_map.rs | 26 +++++---- tests/ui/unnecessary_filter_map.rs | 7 +-- tests/ui/unnecessary_filter_map.stderr | 53 +++++++------------ tests/ui/unnecessary_find_map.rs | 1 - tests/ui/unnecessary_find_map.stderr | 30 +++++------ 5 files changed, 48 insertions(+), 69 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index ca42a9ac04e0b..f920f306bc1ed 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -1,11 +1,10 @@ use super::utils::clone_or_copy_needed; -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::is_copy; use clippy_utils::usage::mutated_variables; use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id}; use core::ops::ControlFlow; -use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_lint::LateContext; @@ -45,30 +44,32 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a && is_res_lang_ctor(cx, path_res(cx, expr), OptionSome) && let hir::ExprKind::Path(_) = args[0].kind { - span_lint_and_sugg( + span_lint( cx, UNNECESSARY_FILTER_MAP, expr.span, - format!("{name} is unnecessary"), - "try removing the filter_map", - String::new(), - Applicability::MaybeIncorrect, + String::from("this call to `.filter_map(..)` is unnecessary"), ); + return; + } + if name == "filter_map" { + "map(..)" + } else { + "map(..).next()" } - if name == "filter_map" { "map" } else { "map(..).next()" } } else if !found_mapping && !mutates_arg && (!clone_or_copy_needed || is_copy(cx, in_ty)) { match cx.typeck_results().expr_ty(body.value).kind() { ty::Adt(adt, subst) if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) && in_ty == subst.type_at(0) => { - if name == "filter_map" { "filter" } else { "find" } + if name == "filter_map" { "filter(..)" } else { "find(..)" } }, _ => return, } } else { return; }; - span_lint_and_sugg( + span_lint( cx, if name == "filter_map" { UNNECESSARY_FILTER_MAP @@ -76,10 +77,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a UNNECESSARY_FIND_MAP }, expr.span, - format!("this `.{name}` can be written more simply"), - "try instead", - sugg.to_string(), - Applicability::MaybeIncorrect, + format!("this `.{name}(..)` can be written more simply using `.{sugg}`"), ); } } diff --git a/tests/ui/unnecessary_filter_map.rs b/tests/ui/unnecessary_filter_map.rs index c4f1b6bc7e3d7..85582c399ce5f 100644 --- a/tests/ui/unnecessary_filter_map.rs +++ b/tests/ui/unnecessary_filter_map.rs @@ -1,5 +1,4 @@ -//@no-rustfix -#![allow(dead_code)] +#![allow(clippy::redundant_closure)] fn main() { let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); @@ -27,9 +26,7 @@ fn main() { let _ = (0..4).filter_map(Some); let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); - //~^ redundant_closure - //~| unnecessary_filter_map - //~| unnecessary_filter_map + //~^ unnecessary_filter_map } fn filter_map_none_changes_item_type() -> impl Iterator { diff --git a/tests/ui/unnecessary_filter_map.stderr b/tests/ui/unnecessary_filter_map.stderr index 6683444b72730..a879633e10f2a 100644 --- a/tests/ui/unnecessary_filter_map.stderr +++ b/tests/ui/unnecessary_filter_map.stderr @@ -1,14 +1,14 @@ -error: this `.filter_map` can be written more simply - --> tests/ui/unnecessary_filter_map.rs:5:13 +error: this `.filter_map(..)` can be written more simply using `.filter(..)` + --> tests/ui/unnecessary_filter_map.rs:4:13 | LL | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `filter` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_filter_map)]` -error: this `.filter_map` can be written more simply - --> tests/ui/unnecessary_filter_map.rs:8:13 +error: this `.filter_map(..)` can be written more simply using `.filter(..)` + --> tests/ui/unnecessary_filter_map.rs:7:13 | LL | let _ = (0..4).filter_map(|x| { | _____________^ @@ -18,10 +18,10 @@ LL | | if x > 1 { ... | LL | | None LL | | }); - | |______^ help: try instead: `filter` + | |______^ -error: this `.filter_map` can be written more simply - --> tests/ui/unnecessary_filter_map.rs:16:13 +error: this `.filter_map(..)` can be written more simply using `.filter(..)` + --> tests/ui/unnecessary_filter_map.rs:15:13 | LL | let _ = (0..4).filter_map(|x| match x { | _____________^ @@ -29,40 +29,25 @@ LL | | LL | | 0 | 1 => None, LL | | _ => Some(x), LL | | }); - | |______^ help: try instead: `filter` + | |______^ -error: this `.filter_map` can be written more simply - --> tests/ui/unnecessary_filter_map.rs:22:13 +error: this `.filter_map(..)` can be written more simply using `.map(..)` + --> tests/ui/unnecessary_filter_map.rs:21:13 | LL | let _ = (0..4).filter_map(|x| Some(x + 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: redundant closure - --> tests/ui/unnecessary_filter_map.rs:29:57 +error: this call to `.filter_map(..)` is unnecessary + --> tests/ui/unnecessary_filter_map.rs:28:61 | LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); - | ^^^^^^^^^^^ help: replace the closure with the function itself: `Some` - | - = note: `-D clippy::redundant-closure` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]` - -error: filter_map is unnecessary - --> tests/ui/unnecessary_filter_map.rs:29:61 - | -LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); - | ^^^^ help: try removing the filter_map - -error: this `.filter_map` can be written more simply - --> tests/ui/unnecessary_filter_map.rs:29:13 - | -LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map` + | ^^^^ -error: this `.filter_map` can be written more simply - --> tests/ui/unnecessary_filter_map.rs:169:14 +error: this `.filter_map(..)` can be written more simply using `.filter(..)` + --> tests/ui/unnecessary_filter_map.rs:166:14 | LL | let _x = std::iter::once(1).filter_map(|n| (n > 1).then_some(n)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `filter` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/unnecessary_find_map.rs b/tests/ui/unnecessary_find_map.rs index 8c8a3799f0216..33ba7074d623b 100644 --- a/tests/ui/unnecessary_find_map.rs +++ b/tests/ui/unnecessary_find_map.rs @@ -1,4 +1,3 @@ -//@no-rustfix #![allow(dead_code)] fn main() { diff --git a/tests/ui/unnecessary_find_map.stderr b/tests/ui/unnecessary_find_map.stderr index 94e320773a6fe..3754a3d99538e 100644 --- a/tests/ui/unnecessary_find_map.stderr +++ b/tests/ui/unnecessary_find_map.stderr @@ -1,14 +1,14 @@ -error: this `.find_map` can be written more simply - --> tests/ui/unnecessary_find_map.rs:5:13 +error: this `.find_map(..)` can be written more simply using `.find(..)` + --> tests/ui/unnecessary_find_map.rs:4:13 | LL | let _ = (0..4).find_map(|x| if x > 1 { Some(x) } else { None }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `find` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-find-map` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_find_map)]` -error: this `.find_map` can be written more simply - --> tests/ui/unnecessary_find_map.rs:8:13 +error: this `.find_map(..)` can be written more simply using `.find(..)` + --> tests/ui/unnecessary_find_map.rs:7:13 | LL | let _ = (0..4).find_map(|x| { | _____________^ @@ -18,10 +18,10 @@ LL | | if x > 1 { ... | LL | | None LL | | }); - | |______^ help: try instead: `find` + | |______^ -error: this `.find_map` can be written more simply - --> tests/ui/unnecessary_find_map.rs:16:13 +error: this `.find_map(..)` can be written more simply using `.find(..)` + --> tests/ui/unnecessary_find_map.rs:15:13 | LL | let _ = (0..4).find_map(|x| match x { | _____________^ @@ -29,19 +29,19 @@ LL | | LL | | 0 | 1 => None, LL | | _ => Some(x), LL | | }); - | |______^ help: try instead: `find` + | |______^ -error: this `.find_map` can be written more simply - --> tests/ui/unnecessary_find_map.rs:22:13 +error: this `.find_map(..)` can be written more simply using `.map(..).next()` + --> tests/ui/unnecessary_find_map.rs:21:13 | LL | let _ = (0..4).find_map(|x| Some(x + 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map(..).next()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: this `.find_map` can be written more simply - --> tests/ui/unnecessary_find_map.rs:34:14 +error: this `.find_map(..)` can be written more simply using `.find(..)` + --> tests/ui/unnecessary_find_map.rs:33:14 | LL | let _x = std::iter::once(1).find_map(|n| (n > 1).then_some(n)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `find` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors From 9f089e080c47bc282aa98f1e8c72ff44076afbb9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 09:33:02 +1100 Subject: [PATCH 0340/2248] Add `{ast,hir,thir}::PatKind::Missing` variants. "Missing" patterns are possible in bare fn types (`fn f(u32)`) and similar places. Currently these are represented in the AST with `ast::PatKind::Ident` with no `by_ref`, no `mut`, an empty ident, and no sub-pattern. This flows through to `{hir,thir}::PatKind::Binding` for HIR and THIR. This is a bit nasty. It's very non-obvious, and easy to forget to check for the exceptional empty identifier case. This commit adds a new variant, `PatKind::Missing`, to do it properly. The process I followed: - Add a `Missing` variant to `{ast,hir,thir}::PatKind`. - Chang `parse_param_general` to produce `ast::PatKind::Missing` instead of `ast::PatKind::Missing`. - Look through `kw::Empty` occurrences to find functions where an existing empty ident check needs replacing with a `PatKind::Missing` check: `print_param`, `check_trait_item`, `is_named_param`. - Add a `PatKind::Missing => unreachable!(),` arm to every exhaustive match identified by the compiler. - Find which arms are actually reachable by running the test suite, changing them to something appropriate, usually by looking at what would happen to a `PatKind::Ident`/`PatKind::Binding` with no ref, no `mut`, an empty ident, and no subpattern. Quite a few of the `unreachable!()` arms were never reached. This makes sense because `PatKind::Missing` can't happen in every pattern, only in places like bare fn tys and trait fn decls. I also tried an alternative approach: modifying `ast::Param::pat` to hold an `Option>` instead of a `P`, but that quickly turned into a very large and painful change. Adding `PatKind::Missing` is much easier. --- compiler/rustc_ast/src/ast.rs | 8 +++++- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 3 ++- compiler/rustc_ast_lowering/src/pat.rs | 1 + .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 11 +++----- compiler/rustc_hir/src/hir.rs | 6 ++++- compiler/rustc_hir/src/intravisit.rs | 2 +- .../rustc_hir_analysis/src/check/region.rs | 1 + compiler/rustc_hir_pretty/src/lib.rs | 1 + compiler/rustc_hir_typeck/src/expr.rs | 3 ++- .../rustc_hir_typeck/src/expr_use_visitor.rs | 2 ++ compiler/rustc_hir_typeck/src/pat.rs | 11 +++++--- compiler/rustc_lint/src/builtin.rs | 26 +++++++++---------- compiler/rustc_lint/src/unused.rs | 3 ++- compiler/rustc_middle/src/thir.rs | 3 +++ compiler/rustc_middle/src/thir/visit.rs | 3 ++- .../src/builder/matches/match_pair.rs | 2 +- .../src/builder/matches/mod.rs | 1 + .../rustc_mir_build/src/check_unsafety.rs | 1 + .../rustc_mir_build/src/thir/pattern/mod.rs | 2 ++ compiler/rustc_mir_build/src/thir/print.rs | 1 + compiler/rustc_parse/src/parser/item.rs | 4 +-- compiler/rustc_passes/src/input_stats.rs | 2 ++ compiler/rustc_pattern_analysis/src/rustc.rs | 2 +- src/librustdoc/clean/utils.rs | 1 + .../clippy_lints/src/equatable_if_let.rs | 1 + .../src/matches/match_same_arms.rs | 1 + .../clippy_lints/src/matches/single_match.rs | 1 + .../clippy_lints/src/unnested_or_patterns.rs | 1 + .../clippy/clippy_lints/src/utils/author.rs | 1 + .../clippy/clippy_utils/src/ast_utils/mod.rs | 1 + .../clippy/clippy_utils/src/hir_utils.rs | 1 + src/tools/clippy/clippy_utils/src/lib.rs | 1 + src/tools/rustfmt/src/items.rs | 6 +---- src/tools/rustfmt/src/patterns.rs | 2 ++ tests/ui/macros/stringify.rs | 2 ++ tests/ui/unpretty/expanded-exhaustive.rs | 5 ++++ tests/ui/unpretty/expanded-exhaustive.stdout | 3 +++ 40 files changed, 86 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 064f05ef1f3ef..944ae65ffc679 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -563,6 +563,7 @@ impl Pat { /// This is intended for use by diagnostics. pub fn to_ty(&self) -> Option> { let kind = match &self.kind { + PatKind::Missing => unreachable!(), // In a type expression `_` is an inference variable. PatKind::Wild => TyKind::Infer, // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`. @@ -625,7 +626,8 @@ impl Pat { | PatKind::Guard(s, _) => s.walk(it), // These patterns do not contain subpatterns, skip. - PatKind::Wild + PatKind::Missing + | PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Expr(_) @@ -676,6 +678,7 @@ impl Pat { /// Return a name suitable for diagnostics. pub fn descr(&self) -> Option { match &self.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => Some("_".to_string()), PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")), PatKind::Ref(pat, mutbl) => pat.descr().map(|d| format!("&{}{d}", mutbl.prefix_str())), @@ -769,6 +772,9 @@ pub enum RangeSyntax { // Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`. #[derive(Clone, Encodable, Decodable, Debug)] pub enum PatKind { + /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`. + Missing, + /// Represents a wildcard pattern (`_`). Wild, diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 274fe312f7fad..8c6ddf2a69c9a 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1572,7 +1572,7 @@ pub fn walk_pat(vis: &mut T, pat: &mut P) { vis.visit_id(id); match kind { PatKind::Err(_guar) => {} - PatKind::Wild | PatKind::Rest | PatKind::Never => {} + PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Ident(_binding_mode, ident, sub) => { vis.visit_ident(ident); visit_opt(sub, |sub| vis.visit_pat(sub)); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 2716601ca4f9d..3d78f65f634bf 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -727,7 +727,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res try_visit!(visitor.visit_pat(subpattern)); try_visit!(visitor.visit_expr(guard_condition)); } - PatKind::Wild | PatKind::Rest | PatKind::Never => {} + PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Err(_guar) => {} PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { walk_list!(visitor, visit_pat, elems); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ced9064fd9f41..4041e5d092aa8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1495,6 +1495,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option] { self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { + PatKind::Missing => None, PatKind::Ident(_, ident, _) => { if ident.name != kw::Empty { Some(self.lower_ident(ident)) @@ -1506,7 +1507,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { _ => { self.dcx().span_delayed_bug( param.pat.span, - "non-ident/wild param pat must trigger an error", + "non-missing/ident/wild param pat must trigger an error", ); None } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 07cc64a1358ee..f94d788a9b0e6 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -26,6 +26,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let pat_hir_id = self.lower_node_id(pattern.id); let node = loop { match &pattern.kind { + PatKind::Missing => break hir::PatKind::Missing, PatKind::Wild => break hir::PatKind::Wild, PatKind::Never => break hir::PatKind::Never, PatKind::Ident(binding_mode, ident, sub) => { diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a1487ca74be87..ab6d4644f7e94 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -239,7 +239,7 @@ impl<'a> AstValidator<'a> { fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option, bool)) { for Param { pat, .. } in &decl.inputs { match pat.kind { - PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {} + PatKind::Missing | PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {} PatKind::Ident(BindingMode::MUT, ident, None) => { report_err(pat.span, Some(ident), true) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cdb1817944987..f9e17fb0539d8 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1622,9 +1622,9 @@ impl<'a> State<'a> { fn print_pat(&mut self, pat: &ast::Pat) { self.maybe_print_comment(pat.span.lo()); self.ann.pre(self, AnnNode::Pat(pat)); - /* Pat isn't normalized, but the beauty of it - is that it doesn't matter */ + /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match &pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => self.word("_"), PatKind::Never => self.word("!"), PatKind::Ident(BindingMode(by_ref, mutbl), ident, sub) => { @@ -1946,12 +1946,7 @@ impl<'a> State<'a> { if let Some(eself) = input.to_self() { self.print_explicit_self(&eself); } else { - let invalid = if let PatKind::Ident(_, ident, _) = input.pat.kind { - ident.name == kw::Empty - } else { - false - }; - if !invalid { + if !matches!(input.pat.kind, PatKind::Missing) { self.print_pat(&input.pat); self.word(":"); self.space(); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 751c379b21a64..08e37accb8a30 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1516,6 +1516,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { + Missing => unreachable!(), Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => true, Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it), Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), @@ -1543,7 +1544,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { - Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {} + Missing | Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {} Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it), Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), @@ -1681,6 +1682,9 @@ pub enum TyPatKind<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum PatKind<'hir> { + /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`. + Missing, + /// Represents a wildcard pattern (i.e., `_`). Wild, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 506358341b501..ea3f396761b16 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -744,7 +744,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V: visit_opt!(visitor, visit_pat_expr, lower_bound); visit_opt!(visitor, visit_pat_expr, upper_bound); } - PatKind::Never | PatKind::Wild | PatKind::Err(_) => (), + PatKind::Missing | PatKind::Never | PatKind::Wild | PatKind::Err(_) => (), PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => { walk_list!(visitor, visit_pat, prepatterns); visit_opt!(visitor, visit_pat, slice_pattern); diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 255f5fee52a80..d63fef8c0ef26 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -701,6 +701,7 @@ fn resolve_local<'tcx>( PatKind::Ref(_, _) | PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..) + | PatKind::Missing | PatKind::Wild | PatKind::Never | PatKind::Expr(_) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ddaca89ccf82d..a4961fc2c8506 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1875,6 +1875,7 @@ impl<'a> State<'a> { // Pat isn't normalized, but the beauty of it // is that it doesn't matter match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => self.word("_"), PatKind::Never => self.word("!"), PatKind::Binding(BindingMode(by_ref, mutbl), _, ident, sub) => { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a75f6f4caac91..0ed03a03c1b48 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -482,7 +482,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // All of these constitute a read, or match on something that isn't `!`, // which would require a `NeverToAny` coercion. - hir::PatKind::Binding(_, _, _, _) + hir::PatKind::Missing + | hir::PatKind::Binding(_, _, _, _) | hir::PatKind::Struct(_, _, _) | hir::PatKind::TupleStruct(_, _, _) | hir::PatKind::Tuple(_, _) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index c71a5ea8b9761..d50f235ad4d10 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -611,6 +611,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx for pat in pats { self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| { match &pat.kind { + PatKind::Missing => unreachable!(), PatKind::Binding(.., opt_sub_pat) => { // If the opt_sub_pat is None, then the binding does not count as // a wildcard for the purpose of borrowing discr. @@ -1884,6 +1885,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx | PatKind::Expr(..) | PatKind::Range(..) | PatKind::Never + | PatKind::Missing | PatKind::Wild | PatKind::Err(_) => { // always ok diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index f1f956779c94f..0d4ecbc867b73 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -341,7 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let ty = match pat.kind { - PatKind::Wild | PatKind::Err(_) => expected, + PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected, // We allow any type here; we ensure that the type is uninhabited during match checking. PatKind::Never => expected, PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { @@ -505,9 +505,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, // Ref patterns are complicated, we handle them in `check_pat_ref`. - PatKind::Ref(..) => AdjustMode::Pass, + PatKind::Ref(..) + // No need to do anything on a missing pattern. + | PatKind::Missing // A `_` pattern works with any expected type, so there's no need to do anything. - PatKind::Wild + | PatKind::Wild // A malformed pattern doesn't have an expected type, so let's just accept any type. | PatKind::Err(_) // Bindings also work with whatever the expected type is, @@ -1037,7 +1039,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::Tuple(..) | PatKind::Slice(..) => "binding", - PatKind::Wild + PatKind::Missing + | PatKind::Wild | PatKind::Never | PatKind::Binding(..) | PatKind::Box(..) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 9dccd4a0552c3..0b5cdf99de5aa 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -778,21 +778,19 @@ impl EarlyLintPass for AnonymousParameters { } if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind { for arg in sig.decl.inputs.iter() { - if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind { - if ident.name == kw::Empty { - let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span); + if let ast::PatKind::Missing = arg.pat.kind { + let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span); - let (ty_snip, appl) = if let Ok(ref snip) = ty_snip { - (snip.as_str(), Applicability::MachineApplicable) - } else { - ("", Applicability::HasPlaceholders) - }; - cx.emit_span_lint( - ANONYMOUS_PARAMETERS, - arg.pat.span, - BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip }, - ); - } + let (ty_snip, appl) = if let Ok(ref snip) = ty_snip { + (snip.as_str(), Applicability::MachineApplicable) + } else { + ("", Applicability::HasPlaceholders) + }; + cx.emit_span_lint( + ANONYMOUS_PARAMETERS, + arg.pat.span, + BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip }, + ); } } } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 7b43aac90c741..806bca78f7875 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1201,7 +1201,8 @@ impl EarlyLintPass for UnusedParens { // Do not lint on `(..)` as that will result in the other arms being useless. Paren(_) // The other cases do not contain sub-patterns. - | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {}, + | Missing | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None) + | Path(..) | Err(_) => {}, // These are list-like patterns; parens can always be removed. TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { self.check_unused_parens_pat(cx, p, false, false, keep_space); diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 6783bbf8bf42f..413717e45ebfa 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -747,6 +747,9 @@ pub struct Ascription<'tcx> { #[derive(Clone, Debug, HashStable, TypeVisitable)] pub enum PatKind<'tcx> { + /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`. + Missing, + /// A wildcard pattern: `_`. Wild, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 7d62ab7970d01..f3da2a5cc8e4e 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -250,7 +250,8 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>( mut callback: impl FnMut(&'a Pat<'tcx>), ) { match &pat.kind { - PatKind::Wild + PatKind::Missing + | PatKind::Wild | PatKind::Binding { subpattern: None, .. } | PatKind::Constant { value: _ } | PatKind::Range(_) diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 29d400a957b47..11672163b658f 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -118,7 +118,7 @@ impl<'tcx> MatchPairTree<'tcx> { let place = place_builder.try_to_place(cx); let mut subpairs = Vec::new(); let test_case = match pattern.kind { - PatKind::Wild | PatKind::Error(_) => None, + PatKind::Missing | PatKind::Wild | PatKind::Error(_) => None, PatKind::Or { ref pats } => Some(TestCase::Or { pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(), diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 3acf2a6a2a61a..977d4f3e931b5 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -920,6 +920,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Constant { .. } | PatKind::Range { .. } + | PatKind::Missing | PatKind::Wild | PatKind::Never | PatKind::Error(_) => {} diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 7f2e7d5ca8385..9572dfc52dac8 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -313,6 +313,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &'a Pat<'tcx>) { if self.in_union_destructure { match pat.kind { + PatKind::Missing => unreachable!(), // binding to a variable allows getting stuff out of variable PatKind::Binding { .. } // match is conditional on having this value diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 4bfeab44bf4b9..f36a895849a14 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -290,6 +290,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let mut span = pat.span; let kind = match pat.kind { + hir::PatKind::Missing => PatKind::Missing, + hir::PatKind::Wild => PatKind::Wild, hir::PatKind::Never => PatKind::Never, diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 16cef0ec3acbc..ac71bb845a886 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -664,6 +664,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, "kind: PatKind {", depth_lvl); match pat_kind { + PatKind::Missing => unreachable!(), PatKind::Wild => { print_indented!(self, "Wild", depth_lvl + 1); } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index aad1857837554..0f5d8d9fbedd4 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2941,9 +2941,7 @@ impl<'a> Parser<'a> { } match ty { Ok(ty) => { - let ident = Ident::new(kw::Empty, this.prev_token.span); - let bm = BindingMode::NONE; - let pat = this.mk_pat_ident(ty.span, bm, ident); + let pat = this.mk_pat(ty.span, PatKind::Missing); (pat, ty) } // If this is a C-variadic argument and we hit an error, return the error. diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 1278e98afcf61..7181544817225 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -295,6 +295,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { record_variants!( (self, p, p.kind, Some(p.hir_id), hir, Pat, PatKind), [ + Missing, Wild, Binding, Struct, @@ -597,6 +598,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { record_variants!( (self, p, p.kind, None, ast, Pat, PatKind), [ + Missing, Wild, Ident, Struct, diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index a25a80cd45f74..e815273405244 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -457,7 +457,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { PatKind::AscribeUserType { subpattern, .. } | PatKind::ExpandedConstant { subpattern, .. } => return self.lower_pat(subpattern), PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat), - PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { + PatKind::Missing | PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; fields = vec![]; arity = 0; diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index f81db58950cbd..afcca81a485ff 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -304,6 +304,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { Symbol::intern(&match &p.kind { // FIXME(never_patterns): does this make sense? + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Err(_) | PatKind::Never diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index cd9ab2764ac48..3afb687040f45 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -45,6 +45,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { pats.iter().all(unary_pattern) } match &pat.kind { + PatKind::Missing => unreachable!(), PatKind::Slice(_, _, _) | PatKind::Range(_, _, _) | PatKind::Binding(..) diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 250f17fa9025a..a21597ffb93d7 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -253,6 +253,7 @@ fn iter_matching_struct_fields<'a>( impl<'a> NormalizedPat<'a> { fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self { match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Binding(.., None) => Self::Wild, PatKind::Binding(.., Some(pat)) | PatKind::Box(pat) diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 56fbd626eefc4..836c46240ce7b 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -406,6 +406,7 @@ impl<'a> PatState<'a> { pats.iter().map(|p| p.pat), ), + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Binding(_, _, _, None) | PatKind::Expr(_) diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index f43715d6752e3..8966e6851ac2f 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -224,6 +224,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us // We're trying to find whatever kind (~"constructor") we found in `alternatives[start..]`. let changed = match &mut focus_kind { + Missing => unreachable!(), // These pattern forms are "leafs" and do not have sub-patterns. // Therefore they are not some form of constructor `C`, // with which a pattern `C(p_0)` may be formed, diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 4309cd2c9abdf..b7dcd2ffb0eea 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -676,6 +676,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } match pat.value.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => kind!("Wild"), PatKind::Never => kind!("Never"), PatKind::Binding(ann, _, name, sub) => { 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..ed99f966d2b76 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -33,6 +33,7 @@ pub fn eq_id(l: Ident, r: Ident) -> bool { pub fn eq_pat(l: &Pat, r: &Pat) -> bool { use PatKind::*; match (&l.kind, &r.kind) { + (Missing, _) | (_, Missing) => unreachable!(), (Paren(l), _) => eq_pat(l, r), (_, Paren(r)) => eq_pat(l, r), (Wild, Wild) | (Rest, Rest) => true, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 9938e64d24264..b813cd361ed8c 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1124,6 +1124,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_pat(&mut self, pat: &Pat<'_>) { std::mem::discriminant(&pat.kind).hash(&mut self.s); match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Binding(BindingMode(by_ref, mutability), _, _, pat) => { std::mem::discriminant(&by_ref).hash(&mut self.s); std::mem::discriminant(&mutability).hash(&mut self.s); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 1307ff79bc5dd..bdcbe1437d0e2 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1857,6 +1857,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { } match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable. PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)), PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat), diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 3fb3284e3d7fd..81ff6327a4fc0 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -2433,11 +2433,7 @@ pub(crate) fn span_hi_for_param(context: &RewriteContext<'_>, param: &ast::Param } pub(crate) fn is_named_param(param: &ast::Param) -> bool { - if let ast::PatKind::Ident(_, ident, _) = param.pat.kind { - ident.name != symbol::kw::Empty - } else { - true - } + !matches!(param.pat.kind, ast::PatKind::Missing) } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index bafed41e39f42..8ec3de286dcb7 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -42,6 +42,7 @@ pub(crate) fn is_short_pattern( fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool { match &pat.kind { + ast::PatKind::Missing => unreachable!(), ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Err(_) => { true } @@ -100,6 +101,7 @@ impl Rewrite for Pat { fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { match self.kind { + PatKind::Missing => unreachable!(), PatKind::Or(ref pats) => { let pat_strs = pats .iter() diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index 40033f546d30b..3490d3efc5992 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -515,6 +515,8 @@ fn test_meta() { #[test] fn test_pat() { + // PatKind::Missing: untestable in isolation. + // PatKind::Wild c1!(pat, [ _ ], "_"); diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 31af323ecdab5..4d1f12e349001 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -574,6 +574,11 @@ mod items { } mod patterns { + /// PatKind::Missing + fn pat_missing() { + let _: fn(u32, T, &str); + } + /// PatKind::Wild fn pat_wild() { let _; diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 19ae66f7a07aa..d8da941a34077 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -361,6 +361,7 @@ mod expressions { + { builtin # offset_of(T, field) }; @@ -517,6 +518,8 @@ mod items { } } mod patterns { + /// PatKind::Missing + fn pat_missing() { let _: fn(u32, T, &str); } /// PatKind::Wild fn pat_wild() { let _; } /// PatKind::Ident From 32f330158ef0151427f5d9f2617eb7998c4d4567 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 09:33:02 +1100 Subject: [PATCH 0341/2248] Add `{ast,hir,thir}::PatKind::Missing` variants. "Missing" patterns are possible in bare fn types (`fn f(u32)`) and similar places. Currently these are represented in the AST with `ast::PatKind::Ident` with no `by_ref`, no `mut`, an empty ident, and no sub-pattern. This flows through to `{hir,thir}::PatKind::Binding` for HIR and THIR. This is a bit nasty. It's very non-obvious, and easy to forget to check for the exceptional empty identifier case. This commit adds a new variant, `PatKind::Missing`, to do it properly. The process I followed: - Add a `Missing` variant to `{ast,hir,thir}::PatKind`. - Chang `parse_param_general` to produce `ast::PatKind::Missing` instead of `ast::PatKind::Missing`. - Look through `kw::Empty` occurrences to find functions where an existing empty ident check needs replacing with a `PatKind::Missing` check: `print_param`, `check_trait_item`, `is_named_param`. - Add a `PatKind::Missing => unreachable!(),` arm to every exhaustive match identified by the compiler. - Find which arms are actually reachable by running the test suite, changing them to something appropriate, usually by looking at what would happen to a `PatKind::Ident`/`PatKind::Binding` with no ref, no `mut`, an empty ident, and no subpattern. Quite a few of the `unreachable!()` arms were never reached. This makes sense because `PatKind::Missing` can't happen in every pattern, only in places like bare fn tys and trait fn decls. I also tried an alternative approach: modifying `ast::Param::pat` to hold an `Option>` instead of a `P`, but that quickly turned into a very large and painful change. Adding `PatKind::Missing` is much easier. --- clippy_lints/src/equatable_if_let.rs | 1 + clippy_lints/src/matches/match_same_arms.rs | 1 + clippy_lints/src/matches/single_match.rs | 1 + clippy_lints/src/unnested_or_patterns.rs | 1 + clippy_lints/src/utils/author.rs | 1 + clippy_utils/src/ast_utils/mod.rs | 1 + clippy_utils/src/hir_utils.rs | 1 + clippy_utils/src/lib.rs | 1 + 8 files changed, 8 insertions(+) diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs index cd9ab2764ac48..3afb687040f45 100644 --- a/clippy_lints/src/equatable_if_let.rs +++ b/clippy_lints/src/equatable_if_let.rs @@ -45,6 +45,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { pats.iter().all(unary_pattern) } match &pat.kind { + PatKind::Missing => unreachable!(), PatKind::Slice(_, _, _) | PatKind::Range(_, _, _) | PatKind::Binding(..) diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs index 250f17fa9025a..a21597ffb93d7 100644 --- a/clippy_lints/src/matches/match_same_arms.rs +++ b/clippy_lints/src/matches/match_same_arms.rs @@ -253,6 +253,7 @@ fn iter_matching_struct_fields<'a>( impl<'a> NormalizedPat<'a> { fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self { match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Binding(.., None) => Self::Wild, PatKind::Binding(.., Some(pat)) | PatKind::Box(pat) diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index 56fbd626eefc4..836c46240ce7b 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -406,6 +406,7 @@ impl<'a> PatState<'a> { pats.iter().map(|p| p.pat), ), + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Binding(_, _, _, None) | PatKind::Expr(_) diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index f43715d6752e3..8966e6851ac2f 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -224,6 +224,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us // We're trying to find whatever kind (~"constructor") we found in `alternatives[start..]`. let changed = match &mut focus_kind { + Missing => unreachable!(), // These pattern forms are "leafs" and do not have sub-patterns. // Therefore they are not some form of constructor `C`, // with which a pattern `C(p_0)` may be formed, diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 4309cd2c9abdf..b7dcd2ffb0eea 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -676,6 +676,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } match pat.value.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => kind!("Wild"), PatKind::Never => kind!("Never"), PatKind::Binding(ann, _, name, sub) => { diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index 6023ae9cc7b16..ed99f966d2b76 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -33,6 +33,7 @@ pub fn eq_id(l: Ident, r: Ident) -> bool { pub fn eq_pat(l: &Pat, r: &Pat) -> bool { use PatKind::*; match (&l.kind, &r.kind) { + (Missing, _) | (_, Missing) => unreachable!(), (Paren(l), _) => eq_pat(l, r), (_, Paren(r)) => eq_pat(l, r), (Wild, Wild) | (Rest, Rest) => true, diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 9938e64d24264..b813cd361ed8c 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -1124,6 +1124,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_pat(&mut self, pat: &Pat<'_>) { std::mem::discriminant(&pat.kind).hash(&mut self.s); match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Binding(BindingMode(by_ref, mutability), _, _, pat) => { std::mem::discriminant(&by_ref).hash(&mut self.s); std::mem::discriminant(&mutability).hash(&mut self.s); diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 1307ff79bc5dd..bdcbe1437d0e2 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1857,6 +1857,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { } match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable. PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)), PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat), From 909f4492475988ba5e1b84efadacb16eb7d7ff0e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 17:00:27 +1100 Subject: [PATCH 0342/2248] Remove `kw::Extra` checks that are no longer necessary. Thanks to the introduction of `PatKind::Missing`. --- compiler/rustc_ast_lowering/src/lib.rs | 8 +------- compiler/rustc_passes/src/liveness.rs | 5 +---- compiler/rustc_resolve/src/late.rs | 13 ++++--------- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4041e5d092aa8..a3e0f96031613 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1496,13 +1496,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option] { self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { PatKind::Missing => None, - PatKind::Ident(_, ident, _) => { - if ident.name != kw::Empty { - Some(self.lower_ident(ident)) - } else { - None - } - } + PatKind::Ident(_, ident, _) => Some(self.lower_ident(ident)), PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))), _ => { self.dcx().span_delayed_bug( diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index ed70d9ee91f5a..07e3b28bcf658 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -96,7 +96,7 @@ use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt}; use rustc_session::lint; -use rustc_span::{BytePos, Span, Symbol, kw, sym}; +use rustc_span::{BytePos, Span, Symbol, sym}; use tracing::{debug, instrument}; use self::LiveNodeKind::*; @@ -1481,9 +1481,6 @@ impl<'tcx> Liveness<'_, 'tcx> { fn should_warn(&self, var: Variable) -> Option { let name = self.ir.variable_name(var); - if name == kw::Empty { - return None; - } let name = name.as_str(); if name.as_bytes()[0] == b'_' { return None; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 533e216ddb291..117d2ccdde380 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3999,22 +3999,17 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.report_error(ident.span, error(ident)); } - // Record as bound if it's valid: - let ident_valid = ident.name != kw::Empty; - if ident_valid { - bindings.last_mut().unwrap().1.insert(ident); - } + // Record as bound. + bindings.last_mut().unwrap().1.insert(ident); if already_bound_or { // `Variant1(a) | Variant2(a)`, ok // Reuse definition from the first `a`. self.innermost_rib_bindings(ValueNS)[&ident] } else { + // A completely fresh binding is added to the set. let res = Res::Local(pat_id); - if ident_valid { - // A completely fresh binding add to the set if it's valid. - self.innermost_rib_bindings(ValueNS).insert(ident, res); - } + self.innermost_rib_bindings(ValueNS).insert(ident, res); res } } From d4870874158d70e3f6863412ea729dd70d1baf7b Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 27 Mar 2025 17:24:21 -0500 Subject: [PATCH 0343/2248] 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 41b04653f3d2fd9cd6451a586354257d661385e2 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Sun, 23 Mar 2025 19:45:27 -0700 Subject: [PATCH 0344/2248] Trusty: Implement write_vectored for stdio Currently, `write` for stdout and stderr on Trusty is implemented with the semantics of `write_all`. Instead, call the underlying syscall only once in `write` and use the default implementation of `write_all` like other platforms. Also, implement `write_vectored` by adding support for `IoSlice`. Refactor stdin to reuse the unsupported type like #136769. --- library/std/src/sys/io/io_slice/iovec.rs | 2 +- library/std/src/sys/io/mod.rs | 2 +- library/std/src/sys/stdio/trusty.rs | 83 ++++++++++++++---------- 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/library/std/src/sys/io/io_slice/iovec.rs b/library/std/src/sys/io/io_slice/iovec.rs index 072191315f7c5..df56358969a39 100644 --- a/library/std/src/sys/io/io_slice/iovec.rs +++ b/library/std/src/sys/io/io_slice/iovec.rs @@ -1,6 +1,6 @@ #[cfg(target_os = "hermit")] use hermit_abi::iovec; -#[cfg(target_family = "unix")] +#[cfg(any(target_family = "unix", target_os = "trusty"))] use libc::iovec; use crate::ffi::c_void; diff --git a/library/std/src/sys/io/mod.rs b/library/std/src/sys/io/mod.rs index e00b479109f39..4d0365d42fd9b 100644 --- a/library/std/src/sys/io/mod.rs +++ b/library/std/src/sys/io/mod.rs @@ -2,7 +2,7 @@ mod io_slice { cfg_if::cfg_if! { - if #[cfg(any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3"))] { + if #[cfg(any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3", target_os = "trusty"))] { mod iovec; pub use iovec::*; } else if #[cfg(target_os = "windows")] { diff --git a/library/std/src/sys/stdio/trusty.rs b/library/std/src/sys/stdio/trusty.rs index d393e95394d1a..e05461aa44a73 100644 --- a/library/std/src/sys/stdio/trusty.rs +++ b/library/std/src/sys/stdio/trusty.rs @@ -1,21 +1,14 @@ -use crate::io; +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; -pub struct Stdin; +use crate::cmp; +use crate::io::{self, IoSlice}; + +pub type Stdin = unsupported_stdio::Stdin; pub struct Stdout; pub struct Stderr; -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result { - Ok(0) - } -} - impl Stdout { pub const fn new() -> Stdout { Stdout @@ -24,7 +17,16 @@ impl Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { - _write(libc::STDOUT_FILENO, buf) + write(libc::STDOUT_FILENO, buf) + } + + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + write_vectored(libc::STDOUT_FILENO, bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + true } fn flush(&mut self) -> io::Result<()> { @@ -40,7 +42,16 @@ impl Stderr { impl io::Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { - _write(libc::STDERR_FILENO, buf) + write(libc::STDERR_FILENO, buf) + } + + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + write_vectored(libc::STDERR_FILENO, bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + true } fn flush(&mut self) -> io::Result<()> { @@ -48,7 +59,7 @@ impl io::Write for Stderr { } } -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(_err: &io::Error) -> bool { true @@ -58,24 +69,24 @@ pub fn panic_output() -> Option { Some(Stderr) } -fn _write(fd: i32, message: &[u8]) -> io::Result { - let mut iov = libc::iovec { iov_base: message.as_ptr() as *mut _, iov_len: message.len() }; - loop { - // SAFETY: syscall, safe arguments. - let ret = unsafe { libc::writev(fd, &iov, 1) }; - if ret < 0 { - return Err(io::Error::last_os_error()); - } - let ret = ret as usize; - if ret > iov.iov_len { - return Err(io::Error::last_os_error()); - } - if ret == iov.iov_len { - return Ok(message.len()); - } - // SAFETY: ret has been checked to be less than the length of - // the buffer - iov.iov_base = unsafe { iov.iov_base.add(ret) }; - iov.iov_len -= ret; +fn write(fd: i32, buf: &[u8]) -> io::Result { + let iov = libc::iovec { iov_base: buf.as_ptr() as *mut _, iov_len: buf.len() }; + // SAFETY: syscall, safe arguments. + let ret = unsafe { libc::writev(fd, &iov, 1) }; + // This check includes ret < 0, since the length is at most isize::MAX. + if ret as usize > iov.iov_len { + return Err(io::Error::last_os_error()); + } + Ok(ret as usize) +} + +fn write_vectored(fd: i32, bufs: &[IoSlice<'_>]) -> io::Result { + let iov = bufs.as_ptr() as *const libc::iovec; + let len = cmp::min(bufs.len(), libc::c_int::MAX as usize) as libc::c_int; + // SAFETY: syscall, safe arguments. + let ret = unsafe { libc::writev(fd, iov, len) }; + if ret < 0 { + return Err(io::Error::last_os_error()); } + Ok(ret as usize) } From 0340a865b9e7a3aa17a69555f0cc22ba3ad92c73 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 15 Feb 2025 09:19:17 -0800 Subject: [PATCH 0345/2248] Add test for doctest runtool --- .../doctest/auxiliary/doctest-runtool.rs | 21 +++++++++++++++++++ tests/rustdoc/doctest/doctest-runtool.rs | 14 +++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/rustdoc/doctest/auxiliary/doctest-runtool.rs create mode 100644 tests/rustdoc/doctest/doctest-runtool.rs diff --git a/tests/rustdoc/doctest/auxiliary/doctest-runtool.rs b/tests/rustdoc/doctest/auxiliary/doctest-runtool.rs new file mode 100644 index 0000000000000..a21ae0664fe63 --- /dev/null +++ b/tests/rustdoc/doctest/auxiliary/doctest-runtool.rs @@ -0,0 +1,21 @@ +// For some reason on Windows, the PATH to the libstd dylib doesn't seem to +// carry over to running the runtool. +//@ no-prefer-dynamic + +use std::path::Path; +use std::process::Command; + +fn main() { + let args: Vec<_> = std::env::args().collect(); + eprintln!("{args:#?}"); + assert_eq!(args.len(), 4); + assert_eq!(args[1], "arg1"); + assert_eq!(args[2], "arg2 with space"); + let path = Path::new(&args[3]); + let output = Command::new(path).output().unwrap(); + // Should fail without env var. + assert!(!output.status.success()); + let output = Command::new(path).env("DOCTEST_RUNTOOL_CHECK", "xyz").output().unwrap(); + // Should pass with env var. + assert!(output.status.success()); +} diff --git a/tests/rustdoc/doctest/doctest-runtool.rs b/tests/rustdoc/doctest/doctest-runtool.rs new file mode 100644 index 0000000000000..f54dc06fb203a --- /dev/null +++ b/tests/rustdoc/doctest/doctest-runtool.rs @@ -0,0 +1,14 @@ +// Tests that the --runtool argument works. + +//@ ignore-cross-compile +//@ aux-bin: doctest-runtool.rs +//@ compile-flags: --test +//@ compile-flags: --runtool=auxiliary/bin/doctest-runtool +//@ compile-flags: --runtool-arg=arg1 --runtool-arg +//@ compile-flags: 'arg2 with space' +//@ compile-flags: -Zunstable-options + +/// ``` +/// assert_eq!(std::env::var("DOCTEST_RUNTOOL_CHECK"), Ok("xyz".to_string())); +/// ``` +pub fn main() {} From ec25e3300b930b9d2873fe589ed3cbfa55db3ffe Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 15 Feb 2025 10:50:47 -0800 Subject: [PATCH 0346/2248] Rename `--runtool` and `--runtool-arg` This renames `--runtool` and `--runtool-arg` to `--test-runtool` and `--test-runtool-arg` to maintain consistency with other `--test-*` arguments. --- src/doc/rustdoc/src/unstable-features.md | 6 +++--- src/librustdoc/config.rs | 16 ++++++++-------- src/librustdoc/doctest.rs | 4 ++-- src/librustdoc/lib.rs | 4 ++-- src/tools/miri/cargo-miri/src/main.rs | 2 +- src/tools/miri/cargo-miri/src/phases.rs | 10 +++++----- tests/run-make/doctests-runtool/rmake.rs | 6 +++--- .../rustdoc-default-output/output-default.stdout | 4 ++-- tests/rustdoc/doctest/doctest-runtool.rs | 6 +++--- 9 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index d4ff69a99338b..144f1c61b34b1 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -666,21 +666,21 @@ struct Foo; In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will override `ignore`. -## `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it +## `--test-runtool`, `--test-runtool-arg`: program to run tests with; args to pass to it * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) Using these options looks like this: ```bash -$ rustdoc src/lib.rs -Z unstable-options --runtool runner --runtool-arg --do-thing --runtool-arg --do-other-thing +$ rustdoc src/lib.rs -Z unstable-options --test-runtool runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing ``` These options can be used to run the doctest under a program, and also pass arguments to that program. For example, if you want to run your doctests under valgrind you might run ```bash -$ rustdoc src/lib.rs -Z unstable-options --runtool valgrind +$ rustdoc src/lib.rs -Z unstable-options --test-runtool valgrind ``` Another use case would be to run a test inside an emulator, or through a Virtual Machine. diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 23a2bcd9011ee..0eb620c01d9b8 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -124,9 +124,9 @@ pub(crate) struct Options { /// temporary directory if not set. pub(crate) persist_doctests: Option, /// Runtool to run doctests with - pub(crate) runtool: Option, + pub(crate) test_runtool: Option, /// Arguments to pass to the runtool - pub(crate) runtool_args: Vec, + pub(crate) test_runtool_args: Vec, /// Whether to allow ignoring doctests on a per-target basis /// For example, using ignore-foo to ignore running the doctest on any target that /// contains "foo" as a substring @@ -215,8 +215,8 @@ impl fmt::Debug for Options { .field("persist_doctests", &self.persist_doctests) .field("show_coverage", &self.show_coverage) .field("crate_version", &self.crate_version) - .field("runtool", &self.runtool) - .field("runtool_args", &self.runtool_args) + .field("test_runtool", &self.test_runtool) + .field("test_runtool_args", &self.test_runtool_args) .field("enable-per-target-ignores", &self.enable_per_target_ignores) .field("run_check", &self.run_check) .field("no_run", &self.no_run) @@ -779,8 +779,8 @@ impl Options { let unstable_opts_strs = matches.opt_strs("Z"); let lib_strs = matches.opt_strs("L"); let extern_strs = matches.opt_strs("extern"); - let runtool = matches.opt_str("runtool"); - let runtool_args = matches.opt_strs("runtool-arg"); + let test_runtool = matches.opt_str("test-runtool"); + let test_runtool_args = matches.opt_strs("test-runtool-arg"); let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores"); let document_private = matches.opt_present("document-private-items"); let document_hidden = matches.opt_present("document-hidden-items"); @@ -843,8 +843,8 @@ impl Options { crate_version, test_run_directory, persist_doctests, - runtool, - runtool_args, + test_runtool, + test_runtool_args, enable_per_target_ignores, test_builder, run_check, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index a2808bddb3acc..ae4863dd82b86 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -781,10 +781,10 @@ fn run_test( let mut cmd; let output_file = make_maybe_absolute_path(output_file); - if let Some(tool) = &rustdoc_options.runtool { + if let Some(tool) = &rustdoc_options.test_runtool { let tool = make_maybe_absolute_path(tool.into()); cmd = Command::new(tool); - cmd.args(&rustdoc_options.runtool_args); + cmd.args(&rustdoc_options.test_runtool_args); cmd.arg(&output_file); } else { cmd = Command::new(&output_file); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4fe5e13c3afe0..daa8e72edb82f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -518,7 +518,7 @@ fn opts() -> Vec { Unstable, Opt, "", - "runtool", + "test-runtool", "", "The tool to run tests with when building for a different target than host", ), @@ -526,7 +526,7 @@ fn opts() -> Vec { Unstable, Multi, "", - "runtool-arg", + "test-runtool-arg", "", "One (of possibly many) arguments to pass to the runtool", ), diff --git a/src/tools/miri/cargo-miri/src/main.rs b/src/tools/miri/cargo-miri/src/main.rs index 7d9f77f3752d9..322ef0a6c2aa8 100644 --- a/src/tools/miri/cargo-miri/src/main.rs +++ b/src/tools/miri/cargo-miri/src/main.rs @@ -53,7 +53,7 @@ fn main() { // with `RustcPhase::Rustdoc`. There we perform a check-build (needed to get the expected // build failures for `compile_fail` doctests) and then store a JSON file with the // information needed to run this test. - // - We also set `--runtool` to ourselves, which ends up in `phase_runner` with + // - We also set `--test-runtool` to ourselves, which ends up in `phase_runner` with // `RunnerPhase::Rustdoc`. There we parse the JSON file written in `phase_rustc` and invoke // the Miri driver for interpretation. diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index d7b4421061c6b..477e82f21a29d 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -666,8 +666,8 @@ pub fn phase_rustdoc(mut args: impl Iterator) { if arg == "--extern" { // Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files. forward_patched_extern_arg(&mut args, &mut cmd); - } else if arg == "--runtool" { - // An existing --runtool flag indicates cargo is running in cross-target mode, which we don't support. + } else if arg == "--test-runtool" { + // An existing --test-runtool flag indicates cargo is running in cross-target mode, which we don't support. // Note that this is only passed when cargo is run with the unstable -Zdoctest-xcompile flag; // otherwise, we won't be called as rustdoc at all. show_error!("cross-interpreting doctests is not currently supported by Miri."); @@ -693,8 +693,8 @@ pub fn phase_rustdoc(mut args: impl Iterator) { // to let phase_cargo_rustc know to expect that. We'll use this environment variable as a flag: cmd.env("MIRI_CALLED_FROM_RUSTDOC", "1"); - // The `--test-builder` and `--runtool` arguments are unstable rustdoc features, - // which are disabled by default. We first need to enable them explicitly: + // The `--test-builder` is an unstable rustdoc features, + // which is disabled by default. We first need to enable them explicitly: cmd.arg("-Zunstable-options"); // rustdoc needs to know the right sysroot. @@ -705,7 +705,7 @@ pub fn phase_rustdoc(mut args: impl Iterator) { // Make rustdoc call us back. let cargo_miri_path = env::current_exe().expect("current executable path invalid"); cmd.arg("--test-builder").arg(&cargo_miri_path); // invoked by forwarding most arguments - cmd.arg("--runtool").arg(&cargo_miri_path); // invoked with just a single path argument + cmd.arg("--test-runtool").arg(&cargo_miri_path); // invoked with just a single path argument debug_cmd("[cargo-miri rustdoc]", verbose, &cmd); exec(cmd) diff --git a/tests/run-make/doctests-runtool/rmake.rs b/tests/run-make/doctests-runtool/rmake.rs index c7be829c215e1..817001c514b52 100644 --- a/tests/run-make/doctests-runtool/rmake.rs +++ b/tests/run-make/doctests-runtool/rmake.rs @@ -1,4 +1,4 @@ -// Tests behavior of rustdoc `--runtool`. +// Tests behavior of rustdoc `--test-runtool`. use std::path::PathBuf; @@ -11,7 +11,7 @@ fn mkdir(name: &str) -> PathBuf { dir } -// Behavior with --runtool with relative paths and --test-run-directory. +// Behavior with --test-runtool with relative paths and --test-run-directory. fn main() { let run_dir_name = "rundir"; let run_dir = mkdir(run_dir_name); @@ -27,7 +27,7 @@ fn main() { .arg("--test") .arg("--test-run-directory") .arg(run_dir_name) - .arg("--runtool") + .arg("--test-runtool") .arg(&run_tool_binary) .extern_("t", "libt.rlib") .run(); diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index 01f470f6e162b..b0ca5f3bf0807 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -141,9 +141,9 @@ Options: --enable-per-target-ignores parse ignore-foo for ignoring doctests on a per-target basis - --runtool The tool to run tests with when building for a different target than host + --test-runtool The tool to run tests with when building for a different target than host - --runtool-arg One (of possibly many) arguments to pass to the runtool + --test-runtool-arg One (of possibly many) arguments to pass to the runtool --test-builder PATH The rustc-like binary to use as the test builder diff --git a/tests/rustdoc/doctest/doctest-runtool.rs b/tests/rustdoc/doctest/doctest-runtool.rs index f54dc06fb203a..75568fab83e75 100644 --- a/tests/rustdoc/doctest/doctest-runtool.rs +++ b/tests/rustdoc/doctest/doctest-runtool.rs @@ -1,10 +1,10 @@ -// Tests that the --runtool argument works. +// Tests that the --test-runtool argument works. //@ ignore-cross-compile //@ aux-bin: doctest-runtool.rs //@ compile-flags: --test -//@ compile-flags: --runtool=auxiliary/bin/doctest-runtool -//@ compile-flags: --runtool-arg=arg1 --runtool-arg +//@ compile-flags: --test-runtool=auxiliary/bin/doctest-runtool +//@ compile-flags: --test-runtool-arg=arg1 --test-runtool-arg //@ compile-flags: 'arg2 with space' //@ compile-flags: -Zunstable-options From 6441701e5ce9c779aea5a121f9b314bfeb971a85 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 15 Feb 2025 10:56:49 -0800 Subject: [PATCH 0347/2248] Stabilize --test-runtool and --test-runtool-arg --- src/doc/rustdoc/src/command-line-arguments.md | 17 +++++++++++++++++ src/doc/rustdoc/src/unstable-features.md | 19 ------------------- src/librustdoc/lib.rs | 4 ++-- tests/rustdoc/doctest/doctest-runtool.rs | 1 - 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 872592d669d6d..ac5c7f5b6596f 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -222,6 +222,23 @@ For more, see [the chapter on documentation tests](write-documentation/documenta See also `--test`. +## `--test-runtool`, `--test-runtool-arg`: program to run tests with; args to pass to it + +Using these options looks like this: + +```bash +$ rustdoc src/lib.rs --test-runtool runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing +``` + +These options can be used to run the doctest under a program, and also pass arguments to +that program. For example, if you want to run your doctests under valgrind you might run + +```bash +$ rustdoc src/lib.rs --test-runtool valgrind +``` + +Another use case would be to run a test inside an emulator, or through a Virtual Machine. + ## `--target`: generate documentation for the specified target triple Using this flag looks like this: diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 144f1c61b34b1..8d56fc86f9453 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -666,25 +666,6 @@ struct Foo; In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will override `ignore`. -## `--test-runtool`, `--test-runtool-arg`: program to run tests with; args to pass to it - - * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) - -Using these options looks like this: - -```bash -$ rustdoc src/lib.rs -Z unstable-options --test-runtool runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing -``` - -These options can be used to run the doctest under a program, and also pass arguments to -that program. For example, if you want to run your doctests under valgrind you might run - -```bash -$ rustdoc src/lib.rs -Z unstable-options --test-runtool valgrind -``` - -Another use case would be to run a test inside an emulator, or through a Virtual Machine. - ## `--with-examples`: include examples of uses of items as documentation * Tracking issue: [#88791](https://github.com/rust-lang/rust/issues/88791) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index daa8e72edb82f..c51debdfd40e8 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -515,7 +515,7 @@ fn opts() -> Vec { "", ), opt( - Unstable, + Stable, Opt, "", "test-runtool", @@ -523,7 +523,7 @@ fn opts() -> Vec { "The tool to run tests with when building for a different target than host", ), opt( - Unstable, + Stable, Multi, "", "test-runtool-arg", diff --git a/tests/rustdoc/doctest/doctest-runtool.rs b/tests/rustdoc/doctest/doctest-runtool.rs index 75568fab83e75..c4fb02e5228cc 100644 --- a/tests/rustdoc/doctest/doctest-runtool.rs +++ b/tests/rustdoc/doctest/doctest-runtool.rs @@ -6,7 +6,6 @@ //@ compile-flags: --test-runtool=auxiliary/bin/doctest-runtool //@ compile-flags: --test-runtool-arg=arg1 --test-runtool-arg //@ compile-flags: 'arg2 with space' -//@ compile-flags: -Zunstable-options /// ``` /// assert_eq!(std::env::var("DOCTEST_RUNTOOL_CHECK"), Ok("xyz".to_string())); From 7251b466a4d4dd164db1b818681af1c8cf9a3e22 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 15 Feb 2025 11:18:29 -0800 Subject: [PATCH 0348/2248] Remove and stabilize --enable-per-target-ignores This removes the `--enable-per-target-ignores` and enables it unconditionally. --- src/doc/rustdoc/src/unstable-features.md | 35 ------------------- .../documentation-tests.md | 28 +++++++++++++++ src/librustdoc/config.rs | 7 ---- src/librustdoc/doctest.rs | 2 -- src/librustdoc/doctest/markdown.rs | 8 +---- src/librustdoc/doctest/rust.rs | 6 ++-- src/librustdoc/html/markdown.rs | 30 +++++----------- src/librustdoc/html/markdown/tests.rs | 4 +-- src/librustdoc/lib.rs | 8 ----- .../passes/calculate_doc_coverage.rs | 2 +- .../passes/check_doc_test_visibility.rs | 2 +- .../output-default.stdout | 3 -- 12 files changed, 43 insertions(+), 92 deletions(-) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 8d56fc86f9453..69e5a5adbec29 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -631,41 +631,6 @@ The generated output (formatted) will look like this: `--output-format html` has no effect, as the default output is HTML. This is accepted on stable, even though the other options for this flag aren't. -## `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests - - * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) - -Using this flag looks like this: - -```bash -$ rustdoc src/lib.rs -Z unstable-options --enable-per-target-ignores -``` - -This flag allows you to tag doctests with compiletest style `ignore-foo` filters that prevent -rustdoc from running that test if the target triple string contains foo. For example: - -```rust -///```ignore-foo,ignore-bar -///assert!(2 == 2); -///``` -struct Foo; -``` - -This will not be run when the build target is `super-awesome-foo` or `less-bar-awesome`. -If the flag is not enabled, then rustdoc will consume the filter, but do nothing with it, and -the above example will be run for all targets. -If you want to preserve backwards compatibility for older versions of rustdoc, you can use - -```rust -///```ignore,ignore-foo -///assert!(2 == 2); -///``` -struct Foo; -``` - -In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will -override `ignore`. - ## `--with-examples`: include examples of uses of items as documentation * Tracking issue: [#88791](https://github.com/rust-lang/rust/issues/88791) diff --git a/src/doc/rustdoc/src/write-documentation/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md index b921f67785754..87e42fe1d3949 100644 --- a/src/doc/rustdoc/src/write-documentation/documentation-tests.md +++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md @@ -427,6 +427,34 @@ should not be merged with the others. So the previous code should use it: In this case, it means that the line information will not change if you add/remove other doctests. +### Ignoring targets + +Attributes starting with `ignore-` can be used to ignore doctests for specific +targets. For example, `ignore-x86_64` will avoid building doctests when the +target name contains `x86_64`. + +```rust +/// ```ignore-x86_64 +/// assert!(2 == 2); +/// ``` +struct Foo; +``` + +This doctest will not be built for targets such as `x86_64-unknown-linux-gnu`. + +If you want to preserve backwards compatibility for older versions of rustdoc, +you can specify both `ignore` and `ignore-`, such as: + +```rust +/// ```ignore,ignore-x86_64 +/// assert!(2 == 2); +/// ``` +struct Foo; +``` + +In older versions, this will be ignored on all targets, but starting with +version CURRENT_RUSTC_VERSION, `ignore-x86_64` will override `ignore`. + ### Custom CSS classes for code blocks ```rust diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 0eb620c01d9b8..4ef73ff48edb5 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -127,10 +127,6 @@ pub(crate) struct Options { pub(crate) test_runtool: Option, /// Arguments to pass to the runtool pub(crate) test_runtool_args: Vec, - /// Whether to allow ignoring doctests on a per-target basis - /// For example, using ignore-foo to ignore running the doctest on any target that - /// contains "foo" as a substring - pub(crate) enable_per_target_ignores: bool, /// Do not run doctests, compile them if should_test is active. pub(crate) no_run: bool, /// What sources are being mapped. @@ -217,7 +213,6 @@ impl fmt::Debug for Options { .field("crate_version", &self.crate_version) .field("test_runtool", &self.test_runtool) .field("test_runtool_args", &self.test_runtool_args) - .field("enable-per-target-ignores", &self.enable_per_target_ignores) .field("run_check", &self.run_check) .field("no_run", &self.no_run) .field("test_builder_wrappers", &self.test_builder_wrappers) @@ -781,7 +776,6 @@ impl Options { let extern_strs = matches.opt_strs("extern"); let test_runtool = matches.opt_str("test-runtool"); let test_runtool_args = matches.opt_strs("test-runtool-arg"); - let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores"); let document_private = matches.opt_present("document-private-items"); let document_hidden = matches.opt_present("document-hidden-items"); let run_check = matches.opt_present("check"); @@ -845,7 +839,6 @@ impl Options { persist_doctests, test_runtool, test_runtool_args, - enable_per_target_ignores, test_builder, run_check, no_run, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index ae4863dd82b86..39dd68937f81c 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -218,11 +218,9 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions let crate_name = tcx.crate_name(LOCAL_CRATE).to_string(); let crate_attrs = tcx.hir_attrs(CRATE_HIR_ID); let opts = scrape_test_config(crate_name, crate_attrs, args_path); - let enable_per_target_ignores = options.enable_per_target_ignores; let hir_collector = HirCollector::new( ErrorCodes::from(compiler.sess.opts.unstable_features.is_nightly_build()), - enable_per_target_ignores, tcx, ); let tests = hir_collector.collect_crate(); diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs index a0d39ce749d83..497a8d7c4a758 100644 --- a/src/librustdoc/doctest/markdown.rs +++ b/src/librustdoc/doctest/markdown.rs @@ -104,13 +104,7 @@ pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> { }; let codes = ErrorCodes::from(options.unstable_features.is_nightly_build()); - find_testable_code( - &input_str, - &mut md_collector, - codes, - options.enable_per_target_ignores, - None, - ); + find_testable_code(&input_str, &mut md_collector, codes, None); let mut collector = CreateRunnableDocTests::new(options.clone(), opts); md_collector.tests.into_iter().for_each(|t| collector.add_test(t)); diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index 12f8b26b1e3c6..504e59d08e46c 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -63,19 +63,18 @@ impl DocTestVisitor for RustCollector { pub(super) struct HirCollector<'tcx> { codes: ErrorCodes, tcx: TyCtxt<'tcx>, - enable_per_target_ignores: bool, collector: RustCollector, } impl<'tcx> HirCollector<'tcx> { - pub fn new(codes: ErrorCodes, enable_per_target_ignores: bool, tcx: TyCtxt<'tcx>) -> Self { + pub fn new(codes: ErrorCodes, tcx: TyCtxt<'tcx>) -> Self { let collector = RustCollector { source_map: tcx.sess.psess.clone_source_map(), cur_path: vec![], position: DUMMY_SP, tests: vec![], }; - Self { codes, enable_per_target_ignores, tcx, collector } + Self { codes, tcx, collector } } pub fn collect_crate(mut self) -> Vec { @@ -131,7 +130,6 @@ impl HirCollector<'_> { &doc, &mut self.collector, self.codes, - self.enable_per_target_ignores, Some(&crate::html::markdown::ExtraInfo::new(self.tcx, def_id, span)), ); } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 0d547a6a0d92d..98dae535b352c 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -246,7 +246,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { match kind { CodeBlockKind::Fenced(ref lang) => { let parse_result = - LangString::parse_without_check(lang, self.check_error_codes, false); + LangString::parse_without_check(lang, self.check_error_codes); if !parse_result.rust { let added_classes = parse_result.added_classes; let lang_string = if let Some(lang) = parse_result.unknown.first() { @@ -707,17 +707,15 @@ pub(crate) fn find_testable_code( doc: &str, tests: &mut T, error_codes: ErrorCodes, - enable_per_target_ignores: bool, extra_info: Option<&ExtraInfo<'_>>, ) { - find_codes(doc, tests, error_codes, enable_per_target_ignores, extra_info, false) + find_codes(doc, tests, error_codes, extra_info, false) } pub(crate) fn find_codes( doc: &str, tests: &mut T, error_codes: ErrorCodes, - enable_per_target_ignores: bool, extra_info: Option<&ExtraInfo<'_>>, include_non_rust: bool, ) { @@ -733,12 +731,7 @@ pub(crate) fn find_codes( if lang.is_empty() { Default::default() } else { - LangString::parse( - lang, - error_codes, - enable_per_target_ignores, - extra_info, - ) + LangString::parse(lang, error_codes, extra_info) } } CodeBlockKind::Indented => Default::default(), @@ -1162,18 +1155,13 @@ impl Default for LangString { } impl LangString { - fn parse_without_check( - string: &str, - allow_error_code_check: ErrorCodes, - enable_per_target_ignores: bool, - ) -> Self { - Self::parse(string, allow_error_code_check, enable_per_target_ignores, None) + fn parse_without_check(string: &str, allow_error_code_check: ErrorCodes) -> Self { + Self::parse(string, allow_error_code_check, None) } fn parse( string: &str, allow_error_code_check: ErrorCodes, - enable_per_target_ignores: bool, extra: Option<&ExtraInfo<'_>>, ) -> Self { let allow_error_code_check = allow_error_code_check.as_bool(); @@ -1203,10 +1191,8 @@ impl LangString { LangStringToken::LangToken(x) if let Some(ignore) = x.strip_prefix("ignore-") => { - if enable_per_target_ignores { - ignores.push(ignore.to_owned()); - seen_rust_tags = !seen_other_tags; - } + ignores.push(ignore.to_owned()); + seen_rust_tags = !seen_other_tags; } LangStringToken::LangToken("rust") => { data.rust = true; @@ -1967,7 +1953,7 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec::new(); - find_testable_code(input, &mut lines, ErrorCodes::No, false, None); + find_testable_code(input, &mut lines, ErrorCodes::No, None); assert_eq!(lines, expect); } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index c51debdfd40e8..d89cea4d5c9b7 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -506,14 +506,6 @@ fn opts() -> Vec { "calculate percentage of public items with documentation", "", ), - opt( - Unstable, - FlagMulti, - "", - "enable-per-target-ignores", - "parse ignore-foo for ignoring doctests on a per-target basis", - "", - ), opt( Stable, Opt, diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index f8f670f575bf4..4401a01440acb 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -212,7 +212,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> { let has_docs = !i.attrs.doc_strings.is_empty(); let mut tests = Tests { found_tests: 0 }; - find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, false, None); + find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, None); let has_doc_example = tests.found_tests != 0; let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap(); diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 0fefd13f76333..a885da180d694 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -122,7 +122,7 @@ pub(crate) fn look_for_tests(cx: &DocContext<'_>, dox: &str, item: &Item) { let mut tests = Tests { found_tests: 0 }; - find_testable_code(dox, &mut tests, ErrorCodes::No, false, None); + find_testable_code(dox, &mut tests, ErrorCodes::No, None); if tests.found_tests == 0 && cx.tcx.features().rustdoc_missing_doc_code_examples() { if should_have_doc_example(cx, item) { diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index b0ca5f3bf0807..e06c7b75b0fcc 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -138,9 +138,6 @@ Options: --show-coverage calculate percentage of public items with documentation - --enable-per-target-ignores - parse ignore-foo for ignoring doctests on a per-target - basis --test-runtool The tool to run tests with when building for a different target than host --test-runtool-arg One (of possibly many) arguments to pass to the runtool From af2b4b94ed6f46392043f1c652f06f402d2713fc Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 27 Mar 2025 18:17:34 -0700 Subject: [PATCH 0349/2248] Show an example of using multiple ignore attributes --- .../src/write-documentation/documentation-tests.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/doc/rustdoc/src/write-documentation/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md index 87e42fe1d3949..077b02d603d0f 100644 --- a/src/doc/rustdoc/src/write-documentation/documentation-tests.md +++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md @@ -442,6 +442,15 @@ struct Foo; This doctest will not be built for targets such as `x86_64-unknown-linux-gnu`. +Multiple ignore attributes can be specified to ignore multiple targets: + +```rust +/// ```ignore-x86_64,ignore-windows +/// assert!(2 == 2); +/// ``` +struct Foo; +``` + If you want to preserve backwards compatibility for older versions of rustdoc, you can specify both `ignore` and `ignore-`, such as: From f535922f20d8061fc3c61b165cd7a4061500e751 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 27 Mar 2025 18:20:04 -0700 Subject: [PATCH 0350/2248] Try to more clearly specify exactly what the runtool flags do --- src/doc/rustdoc/src/command-line-arguments.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index ac5c7f5b6596f..b55ddf6e0e165 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -224,14 +224,19 @@ See also `--test`. ## `--test-runtool`, `--test-runtool-arg`: program to run tests with; args to pass to it +A doctest wrapper program can be specified with the `--test-runtool` flag. +Rustdoc will execute that wrapper instead of the doctest executable when +running tests. The first arguments to the wrapper will be any arguments +specified with the `--test-runtool-arg` flag, followed by the path to the +doctest executable to run. + Using these options looks like this: ```bash -$ rustdoc src/lib.rs --test-runtool runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing +$ rustdoc src/lib.rs --test-runtool path/to/runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing ``` -These options can be used to run the doctest under a program, and also pass arguments to -that program. For example, if you want to run your doctests under valgrind you might run +For example, if you want to run your doctests under valgrind you might run: ```bash $ rustdoc src/lib.rs --test-runtool valgrind From 14410b6369e7fbe221f37421b1840c51c663c6ca Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Thu, 27 Mar 2025 23:55:48 +0200 Subject: [PATCH 0351/2248] Fix a bug in orphan rules calculation Where a fundamental type applied twice wasn't considered local. --- .../crates/hir-ty/src/method_resolution.rs | 29 +++++++++++-------- .../src/handlers/trait_impl_orphan.rs | 13 +++++++++ 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index d887013b6ff30..10b8dd2a3a625 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -874,21 +874,26 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool { return true; } - let unwrap_fundamental = |ty: Ty| match ty.kind(Interner) { - TyKind::Ref(_, _, referenced) => referenced.clone(), - &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref subs) => { - let struct_data = db.struct_data(s); - if struct_data.flags.contains(StructFlags::IS_FUNDAMENTAL) { - let next = subs.type_parameters(Interner).next(); - match next { - Some(ty) => ty, - None => ty, + let unwrap_fundamental = |mut ty: Ty| { + // Unwrap all layers of fundamental types with a loop. + loop { + match ty.kind(Interner) { + TyKind::Ref(_, _, referenced) => ty = referenced.clone(), + &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref subs) => { + let struct_data = db.struct_data(s); + if struct_data.flags.contains(StructFlags::IS_FUNDAMENTAL) { + let next = subs.type_parameters(Interner).next(); + match next { + Some(it) => ty = it, + None => break ty, + } + } else { + break ty; + } } - } else { - ty + _ => break ty, } } - _ => ty, }; // - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type. let is_not_orphan = trait_ref.substitution.type_parameters(Interner).any(|ty| { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs index 78a04e15424fd..35dc9b0fac8a3 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs @@ -104,4 +104,17 @@ impl foo::Foo for Bar {} "#, ); } + + #[test] + fn twice_fundamental() { + check_diagnostics( + r#" +//- /foo.rs crate:foo +pub trait Trait {} +//- /bar.rs crate:bar deps:foo +struct Foo; +impl foo::Trait for &&Foo {} + "#, + ); + } } From 78768361a0c06adff614515eb651a927c63c91b4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 28 Mar 2025 13:44:55 +1100 Subject: [PATCH 0352/2248] Remove `rustc_middle::ty::util::ExplicitSelf`. It's an old (2017 or earlier) type that describes a `self` receiver. It's only used in `rustc_hir_analysis` for two error messages, and much of the complexity isn't used. I suspect it used to be used for more things. This commit removes it, and moves a greatly simplified version of the `determine` method into `rustc_hir_analysis`, renamed as `get_self_string`. The big comment on the method is removed because it no longer seems relevant. --- .../src/check/compare_impl_item.rs | 35 ++++++++----- compiler/rustc_middle/src/ty/util.rs | 49 ------------------- 2 files changed, 22 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 84d07c711fa40..a4ed15ba21298 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -12,7 +12,6 @@ use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisi use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::util::ExplicitSelf; use rustc_middle::ty::{ self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, @@ -995,6 +994,26 @@ impl<'tcx> ty::FallibleTypeFolder> for RemapHiddenTyRegions<'tcx> { } } +/// Gets the string for an explicit self declaration, e.g. "self", "&self", +/// etc. +fn get_self_string<'tcx, P>(self_arg_ty: Ty<'tcx>, is_self_ty: P) -> String +where + P: Fn(Ty<'tcx>) -> bool, +{ + if is_self_ty(self_arg_ty) { + "self".to_owned() + } else if let ty::Ref(_, ty, mutbl) = self_arg_ty.kind() + && is_self_ty(*ty) + { + match mutbl { + hir::Mutability::Not => "&self".to_owned(), + hir::Mutability::Mut => "&mut self".to_owned(), + } + } else { + format!("self: {self_arg_ty}") + } +} + fn report_trait_method_mismatch<'tcx>( infcx: &InferCtxt<'tcx>, mut cause: ObligationCause<'tcx>, @@ -1020,12 +1039,7 @@ fn report_trait_method_mismatch<'tcx>( if trait_m.fn_has_self_parameter => { let ty = trait_sig.inputs()[0]; - let sugg = match ExplicitSelf::determine(ty, |ty| ty == impl_trait_ref.self_ty()) { - ExplicitSelf::ByValue => "self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(), - _ => format!("self: {ty}"), - }; + let sugg = get_self_string(ty, |ty| ty == impl_trait_ref.self_ty()); // When the `impl` receiver is an arbitrary self type, like `self: Box`, the // span points only at the type `Box, but we want to cover the whole @@ -1238,12 +1252,7 @@ fn compare_self_type<'tcx>( .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, method.def_id)); let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty); let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty); - match ExplicitSelf::determine(self_arg_ty, can_eq_self) { - ExplicitSelf::ByValue => "self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(), - _ => format!("self: {self_arg_ty}"), - } + get_self_string(self_arg_ty, can_eq_self) }; match (trait_m.fn_has_self_parameter, impl_m.fn_has_self_parameter) { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c0d4130336e52..23c5c3488fc69 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1546,55 +1546,6 @@ impl<'tcx> Ty<'tcx> { } } -pub enum ExplicitSelf<'tcx> { - ByValue, - ByReference(ty::Region<'tcx>, hir::Mutability), - ByRawPointer(hir::Mutability), - ByBox, - Other, -} - -impl<'tcx> ExplicitSelf<'tcx> { - /// Categorizes an explicit self declaration like `self: SomeType` - /// into either `self`, `&self`, `&mut self`, `Box`, or - /// `Other`. - /// This is mainly used to require the arbitrary_self_types feature - /// in the case of `Other`, to improve error messages in the common cases, - /// and to make `Other` dyn-incompatible. - /// - /// Examples: - /// - /// ```ignore (illustrative) - /// impl<'a> Foo for &'a T { - /// // Legal declarations: - /// fn method1(self: &&'a T); // ExplicitSelf::ByReference - /// fn method2(self: &'a T); // ExplicitSelf::ByValue - /// fn method3(self: Box<&'a T>); // ExplicitSelf::ByBox - /// fn method4(self: Rc<&'a T>); // ExplicitSelf::Other - /// - /// // Invalid cases will be caught by `check_method_receiver`: - /// fn method_err1(self: &'a mut T); // ExplicitSelf::Other - /// fn method_err2(self: &'static T) // ExplicitSelf::ByValue - /// fn method_err3(self: &&T) // ExplicitSelf::ByReference - /// } - /// ``` - /// - pub fn determine

(self_arg_ty: Ty<'tcx>, is_self_ty: P) -> ExplicitSelf<'tcx> - where - P: Fn(Ty<'tcx>) -> bool, - { - use self::ExplicitSelf::*; - - match *self_arg_ty.kind() { - _ if is_self_ty(self_arg_ty) => ByValue, - ty::Ref(region, ty, mutbl) if is_self_ty(ty) => ByReference(region, mutbl), - ty::RawPtr(ty, mutbl) if is_self_ty(ty) => ByRawPointer(mutbl), - _ if self_arg_ty.boxed_ty().is_some_and(is_self_ty) => ByBox, - _ => Other, - } - } -} - /// Returns a list of types such that the given type needs drop if and only if /// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if /// this type always needs drop. From 2f5aa084c8bb6e1a4b014396a44087fd65a4c1c8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 14 Mar 2025 15:56:33 +0000 Subject: [PATCH 0353/2248] Avoid wrapping constant allocations in packed structs when not necessary This way LLVM will set the string merging flag if the alloc is a nul terminated string, reducing binary sizes. --- src/consts.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/consts.rs b/src/consts.rs index c514b7a428bc6..474475f311f71 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -364,6 +364,7 @@ pub fn const_alloc_to_gcc<'gcc>( llvals.push(cx.const_bytes(bytes)); } + // FIXME(bjorn3) avoid wrapping in a struct when there is only a single element. cx.const_struct(&llvals, true) } From a1e1960efc9357210909cc3ff7e7e82d9c844192 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 20 Mar 2025 23:44:23 +0100 Subject: [PATCH 0354/2248] Move `desugar_await` to `clippy_utils` --- clippy_lints/src/redundant_async_block.rs | 26 ++--------------------- clippy_utils/src/lib.rs | 18 ++++++++++++++++ 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/redundant_async_block.rs b/clippy_lints/src/redundant_async_block.rs index 8289ec47bc7e1..d2442ad0f373a 100644 --- a/clippy_lints/src/redundant_async_block.rs +++ b/clippy_lints/src/redundant_async_block.rs @@ -1,14 +1,9 @@ -use std::ops::ControlFlow; - use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::peel_blocks; use clippy_utils::source::{snippet, walk_span_to_context}; use clippy_utils::ty::implements_trait; -use clippy_utils::visitors::for_each_expr_without_closures; +use clippy_utils::{desugar_await, peel_blocks}; use rustc_errors::Applicability; -use rustc_hir::{ - Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, MatchSource, -}; +use rustc_hir::{Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::UpvarCapture; use rustc_session::declare_lint_pass; @@ -99,20 +94,3 @@ fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Op None } } - -/// If `expr` is a desugared `.await`, return the original expression if it does not come from a -/// macro expansion. -fn desugar_await<'tcx>(expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - if let ExprKind::Match(match_value, _, MatchSource::AwaitDesugar) = expr.kind - && let ExprKind::Call(_, [into_future_arg]) = match_value.kind - && let ctxt = expr.span.ctxt() - && for_each_expr_without_closures(into_future_arg, |e| { - walk_span_to_context(e.span, ctxt).map_or(ControlFlow::Break(()), |_| ControlFlow::Continue(())) - }) - .is_none() - { - Some(into_future_arg) - } else { - None - } -} diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index e8ec42e0662bd..8d22d434ebc5b 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -126,6 +126,7 @@ use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{Ident, Symbol, kw}; use rustc_span::{InnerSpan, Span, sym}; +use source::walk_span_to_context; use visitors::{Visitable, for_each_unconsumed_temporary}; use crate::consts::{ConstEvalCtxt, Constant, mir_to_const}; @@ -3718,3 +3719,20 @@ pub fn peel_hir_ty_options<'tcx>(cx: &LateContext<'tcx>, mut hir_ty: &'tcx hir:: } hir_ty } + +/// If `expr` is a desugared `.await`, return the original expression if it does not come from a +/// macro expansion. +pub fn desugar_await<'tcx>(expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { + if let ExprKind::Match(match_value, _, MatchSource::AwaitDesugar) = expr.kind + && let ExprKind::Call(_, [into_future_arg]) = match_value.kind + && let ctxt = expr.span.ctxt() + && for_each_expr_without_closures(into_future_arg, |e| { + walk_span_to_context(e.span, ctxt).map_or(ControlFlow::Break(()), |_| ControlFlow::Continue(())) + }) + .is_none() + { + Some(into_future_arg) + } else { + None + } +} From 753cdd7adefa968f3ce1a353721f59aea6576b13 Mon Sep 17 00:00:00 2001 From: Hegui Dai Date: Fri, 28 Mar 2025 18:25:32 +0800 Subject: [PATCH 0355/2248] move "impl<> for <>" and test about it --- .../ide-completion/src/completions/item_list.rs | 2 -- .../ide-completion/src/completions/keyword.rs | 1 - .../crates/ide-completion/src/tests/expression.rs | 14 -------------- .../crates/ide-completion/src/tests/item.rs | 1 - .../crates/ide-completion/src/tests/item_list.rs | 5 ----- .../crates/ide-completion/src/tests/special.rs | 4 ---- 6 files changed, 27 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs index 30ffeff2614a7..58e7f584ed6f8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs @@ -115,7 +115,6 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option if no_vis_qualifiers { add_keyword("impl", "impl $1 {\n $0\n}"); add_keyword("impl for", "impl $1 for $2 {\n $0\n}"); - add_keyword("impl<> for <>", "impl<$4> $1 for $2<$3> {\n $0\n}"); } } @@ -147,7 +146,6 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option if no_vis_qualifiers { add_keyword("impl", "impl $1 {\n $0\n}"); add_keyword("impl for", "impl $1 for $2 {\n $0\n}"); - add_keyword("impl<> for <>", "impl<$4> $1 for $2<$3> {\n $0\n}"); } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs index d0ba910d93540..039742463c81c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs @@ -57,7 +57,6 @@ mod tests { kw fn kw impl kw impl for - kw impl<> for <> kw trait "#]], ); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index 5314be3c7fc38..46a725db6761e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -172,7 +172,6 @@ impl Unit { kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -252,7 +251,6 @@ fn complete_in_block() { kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -305,7 +303,6 @@ fn complete_after_if_expr() { kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -382,7 +379,6 @@ fn completes_in_loop_ctx() { kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -970,7 +966,6 @@ fn foo() { if foo {} $0 } kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -1014,7 +1009,6 @@ fn foo() { if foo {} el$0 } kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -1108,7 +1102,6 @@ fn foo() { if foo {} $0 let x = 92; } kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -1152,7 +1145,6 @@ fn foo() { if foo {} el$0 let x = 92; } kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -1196,7 +1188,6 @@ fn foo() { if foo {} el$0 { let x = 92; } } kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -1250,7 +1241,6 @@ pub struct UnstableThisShouldNotBeListed; kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -1306,7 +1296,6 @@ pub struct UnstableButWeAreOnNightlyAnyway; kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -1552,7 +1541,6 @@ fn main() { kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -2011,7 +1999,6 @@ fn bar() { kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -2085,7 +2072,6 @@ fn foo() { kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs index a2d2cf39c2df7..55689034fb478 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs @@ -285,7 +285,6 @@ fn bar() { kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs index ee77845588320..fcdf10c85616c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs @@ -17,7 +17,6 @@ fn in_mod_item_list() { kw fn kw impl kw impl for - kw impl<> for <> kw mod kw pub kw pub(crate) @@ -53,7 +52,6 @@ fn in_source_file_item_list() { kw fn kw impl kw impl for - kw impl<> for <> kw mod kw pub kw pub(crate) @@ -88,7 +86,6 @@ fn in_item_list_after_attr() { kw fn kw impl kw impl for - kw impl<> for <> kw mod kw pub kw pub(crate) @@ -129,7 +126,6 @@ fn after_unsafe_token() { kw fn kw impl kw impl for - kw impl<> for <> kw trait "#]], ); @@ -394,7 +390,6 @@ fn after_unit_struct() { kw fn kw impl kw impl for - kw impl<> for <> kw mod kw pub kw pub(crate) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs index ca579b8fc1e69..347febce01129 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -1009,7 +1009,6 @@ fn here_we_go() { kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -1062,7 +1061,6 @@ fn here_we_go() { kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -1189,7 +1187,6 @@ fn bar() { qu$0 } kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop @@ -1448,7 +1445,6 @@ fn foo() { kw if let kw impl kw impl for - kw impl<> for <> kw let kw letm kw loop From 40fc228443ee7677130b3ea776e44e5e24819bd3 Mon Sep 17 00:00:00 2001 From: Hegui Dai Date: Fri, 28 Mar 2025 18:28:56 +0800 Subject: [PATCH 0356/2248] update test --- .../ide-completion/src/tests/expression.rs | 40 +++++++++---------- .../ide-completion/src/tests/special.rs | 4 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index 46a725db6761e..f3d957c2edbd2 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -237,8 +237,8 @@ fn complete_in_block() { } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -287,8 +287,8 @@ fn complete_after_if_expr() { } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -363,8 +363,8 @@ fn completes_in_loop_ctx() { check( r"fn my() { loop { $0 } }", expect![[r#" - fn my() fn() - bt u32 u32 + fn my() fn() + bt u32 u32 kw async kw break kw const @@ -950,8 +950,8 @@ fn else_completion_after_if() { fn foo() { if foo {} $0 } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -993,8 +993,8 @@ fn foo() { if foo {} $0 } fn foo() { if foo {} el$0 } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -1086,8 +1086,8 @@ fn foo() { bar(if foo {} el$0) } fn foo() { if foo {} $0 let x = 92; } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -1129,8 +1129,8 @@ fn foo() { if foo {} $0 let x = 92; } fn foo() { if foo {} el$0 let x = 92; } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -1172,8 +1172,8 @@ fn foo() { if foo {} el$0 let x = 92; } fn foo() { if foo {} el$0 { let x = 92; } } "#, expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: @@ -1226,9 +1226,9 @@ fn main() { pub struct UnstableThisShouldNotBeListed; "#, expect![[r#" - fn main() fn() + fn main() fn() md std - bt u32 u32 + bt u32 u32 kw async kw const kw crate:: @@ -2057,9 +2057,9 @@ fn foo() { } "#, expect![[r#" - fn foo() fn() + fn foo() fn() md proc_macros - bt u32 u32 + bt u32 u32 kw async kw const kw crate:: diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs index 347febce01129..15518e98370ee 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -1431,8 +1431,8 @@ fn foo() { "#, Some('_'), expect![[r#" - fn foo() fn() - bt u32 u32 + fn foo() fn() + bt u32 u32 kw async kw const kw crate:: From 3e960c12d8004135a2c864a6d54753df806aeff6 Mon Sep 17 00:00:00 2001 From: Bastian Kersting Date: Wed, 15 Jan 2025 15:01:56 +0000 Subject: [PATCH 0357/2248] Make missing_const_for_fn operate on non-optimized MIR This has two reasons: First of all we don't need the optimized MIR for evaluating the checks of this lint, as const-eval anyways operates on `mir_for_ctf` which is derived from `mir_drops_elaborated_and_const_checked`. Second of all we might transform MIR in the optimization passes in a way that doesn't work with const-eval, but it is irrelevant since const-eval uses another MIR. Specifically this came up when adding a new check in debug builds (https://github.com/rust-lang/rust/pull/134424), which is added as part of an optimization pass. --- clippy_lints/src/missing_const_for_fn.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 5ac66b4c7e84b..67537a251da7f 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -155,9 +155,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { return; } - let mir = cx.tcx.optimized_mir(def_id); + let mir = cx.tcx.mir_drops_elaborated_and_const_checked(def_id); - if let Ok(()) = is_min_const_fn(cx, mir, self.msrv) + if let Ok(()) = is_min_const_fn(cx, &mir.borrow(), self.msrv) && let hir::Node::Item(hir::Item { vis_span, .. }) | hir::Node::ImplItem(hir::ImplItem { vis_span, .. }) = cx.tcx.hir_node_by_def_id(def_id) { From 8357d063102a53b0069d7380582fbaa0ca53ab42 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 20 Mar 2025 23:44:23 +0100 Subject: [PATCH 0358/2248] Factor out `clippy_utils::get_async_closure_expr()` Also, be stricter in matching the right expansion of async closures. --- clippy_utils/src/lib.rs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 8d22d434ebc5b..0f4a42cec0c17 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -106,10 +106,10 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::{ self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext, - Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArg, GenericArgs, HirId, Impl, ImplItem, - ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, - Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitFn, TraitItem, - TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, def, + CoroutineDesugaring, CoroutineKind, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArg, + GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, + Mutability, Node, OwnerId, OwnerNode, Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, + Stmt, StmtKind, TraitFn, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, def, }; use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext}; @@ -2134,15 +2134,18 @@ pub fn is_async_fn(kind: FnKind<'_>) -> bool { } } -/// Peels away all the compiler generated code surrounding the body of an async function, -pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> { - if let ExprKind::Closure(&Closure { body, .. }) = body.value.kind +/// Peels away all the compiler generated code surrounding the body of an async closure. +pub fn get_async_closure_expr<'tcx>(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> { + if let ExprKind::Closure(&Closure { + body, + kind: hir::ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)), + .. + }) = expr.kind && let ExprKind::Block( Block { - stmts: [], expr: Some(Expr { - kind: ExprKind::DropTemps(expr), + kind: ExprKind::DropTemps(inner_expr), .. }), .. @@ -2150,9 +2153,15 @@ pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'t _, ) = tcx.hir_body(body).value.kind { - return Some(expr); + Some(inner_expr) + } else { + None } - None +} + +/// Peels away all the compiler generated code surrounding the body of an async function, +pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> { + get_async_closure_expr(tcx, body.value) } // check if expr is calling method or function with #[must_use] attribute From 4ac36112254de57d886a71bd9000456fdc758805 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 20 Mar 2025 23:44:23 +0100 Subject: [PATCH 0359/2248] `implicit_return`: do not suggest adding `return` into desugared code Blocks created by desugaring will not contain an explicit `return`. Do not suggest to add it when the user has no control over the desugared code. Also, in the case of an implicit return on a `.await` expression, ensure that the suggested `return` is emitted at the right place instead of before the `await` keyword. --- clippy_lints/src/implicit_return.rs | 8 ++- tests/ui/implicit_return.fixed | 43 ++++++++++++++ tests/ui/implicit_return.rs | 43 ++++++++++++++ tests/ui/implicit_return.stderr | 90 ++++++++++++++++++++++++++++- 4 files changed, 182 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index ee141ddee15b0..076017a247b4b 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::{snippet_with_applicability, snippet_with_context, walk_span_to_context}; use clippy_utils::visitors::for_each_expr_without_closures; -use clippy_utils::{get_async_fn_body, is_async_fn, is_from_proc_macro}; +use clippy_utils::{desugar_await, get_async_closure_expr, get_async_fn_body, is_async_fn, is_from_proc_macro}; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; @@ -134,6 +134,10 @@ fn lint_implicit_returns( }, ExprKind::Match(_, arms, _) => { + if let Some(await_expr) = desugar_await(expr) { + lint_return(cx, await_expr.hir_id, await_expr.span); + return LintLocation::Inner; + } for arm in arms { let res = lint_implicit_returns( cx, @@ -241,6 +245,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitReturn { Some(e) => e, None => return, } + } else if let Some(expr) = get_async_closure_expr(cx.tcx, body.value) { + expr } else { body.value }; diff --git a/tests/ui/implicit_return.fixed b/tests/ui/implicit_return.fixed index 1cb639b60a9af..728c6e015c155 100644 --- a/tests/ui/implicit_return.fixed +++ b/tests/ui/implicit_return.fixed @@ -165,3 +165,46 @@ with_span!( x } ); + +fn desugared_closure_14446() { + let _ = async || return 0; + //~^ implicit_return + #[rustfmt::skip] + let _ = async || -> i32 { return 0 }; + //~^ implicit_return + let _ = async |a: i32| return a; + //~^ implicit_return + #[rustfmt::skip] + let _ = async |a: i32| { return a }; + //~^ implicit_return + + let _ = async || return 0; + let _ = async || -> i32 { return 0 }; + let _ = async |a: i32| return a; + #[rustfmt::skip] + let _ = async |a: i32| { return a; }; + + let _ = async || return foo().await; + //~^ implicit_return + let _ = async || { + foo().await; + return foo().await + }; + //~^^ implicit_return + #[rustfmt::skip] + let _ = async || { return foo().await }; + //~^ implicit_return + let _ = async || -> bool { return foo().await }; + //~^ implicit_return + + let _ = async || return foo().await; + let _ = async || { + foo().await; + return foo().await; + }; + #[rustfmt::skip] + let _ = async || { return foo().await; }; + let _ = async || -> bool { + return foo().await; + }; +} diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index 99d75e4987e47..3381fffb6e450 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -165,3 +165,46 @@ with_span!( x } ); + +fn desugared_closure_14446() { + let _ = async || 0; + //~^ implicit_return + #[rustfmt::skip] + let _ = async || -> i32 { 0 }; + //~^ implicit_return + let _ = async |a: i32| a; + //~^ implicit_return + #[rustfmt::skip] + let _ = async |a: i32| { a }; + //~^ implicit_return + + let _ = async || return 0; + let _ = async || -> i32 { return 0 }; + let _ = async |a: i32| return a; + #[rustfmt::skip] + let _ = async |a: i32| { return a; }; + + let _ = async || foo().await; + //~^ implicit_return + let _ = async || { + foo().await; + foo().await + }; + //~^^ implicit_return + #[rustfmt::skip] + let _ = async || { foo().await }; + //~^ implicit_return + let _ = async || -> bool { foo().await }; + //~^ implicit_return + + let _ = async || return foo().await; + let _ = async || { + foo().await; + return foo().await; + }; + #[rustfmt::skip] + let _ = async || { return foo().await; }; + let _ = async || -> bool { + return foo().await; + }; +} diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index 02044df47ac3c..05cd7f62583b1 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -183,5 +183,93 @@ help: add `return` as shown LL | return true | ++++++ -error: aborting due to 16 previous errors +error: missing `return` statement + --> tests/ui/implicit_return.rs:170:22 + | +LL | let _ = async || 0; + | ^ + | +help: add `return` as shown + | +LL | let _ = async || return 0; + | ++++++ + +error: missing `return` statement + --> tests/ui/implicit_return.rs:173:31 + | +LL | let _ = async || -> i32 { 0 }; + | ^ + | +help: add `return` as shown + | +LL | let _ = async || -> i32 { return 0 }; + | ++++++ + +error: missing `return` statement + --> tests/ui/implicit_return.rs:175:28 + | +LL | let _ = async |a: i32| a; + | ^ + | +help: add `return` as shown + | +LL | let _ = async |a: i32| return a; + | ++++++ + +error: missing `return` statement + --> tests/ui/implicit_return.rs:178:30 + | +LL | let _ = async |a: i32| { a }; + | ^ + | +help: add `return` as shown + | +LL | let _ = async |a: i32| { return a }; + | ++++++ + +error: missing `return` statement + --> tests/ui/implicit_return.rs:187:22 + | +LL | let _ = async || foo().await; + | ^^^^^ + | +help: add `return` as shown + | +LL | let _ = async || return foo().await; + | ++++++ + +error: missing `return` statement + --> tests/ui/implicit_return.rs:191:9 + | +LL | foo().await + | ^^^^^ + | +help: add `return` as shown + | +LL | return foo().await + | ++++++ + +error: missing `return` statement + --> tests/ui/implicit_return.rs:195:24 + | +LL | let _ = async || { foo().await }; + | ^^^^^ + | +help: add `return` as shown + | +LL | let _ = async || { return foo().await }; + | ++++++ + +error: missing `return` statement + --> tests/ui/implicit_return.rs:197:32 + | +LL | let _ = async || -> bool { foo().await }; + | ^^^^^ + | +help: add `return` as shown + | +LL | let _ = async || -> bool { return foo().await }; + | ++++++ + +error: aborting due to 24 previous errors From 0ce025175d6919b93f057f2650ced63b16f03ced Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Mar 2025 13:40:53 +0100 Subject: [PATCH 0360/2248] uses_power_alignment: wording tweaks --- compiler/rustc_lint/src/types.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7109fefbe783e..d98b439ba89fe 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -756,10 +756,10 @@ declare_lint! { /// *subsequent* fields of the associated structs to use an alignment value /// where the floating-point type is aligned on a 4-byte boundary. /// - /// The power alignment rule for structs needed for C compatibility is - /// unimplementable within `repr(C)` in the compiler without building in - /// handling of references to packed fields and infectious nested layouts, - /// so a warning is produced in these situations. + /// Effectively, subsequent floating-point fields act as-if they are `repr(packed(4))`. This + /// would be unsound to do in a `repr(C)` type without all the restrictions that come with + /// `repr(packed)`. Rust instead chooses a layout that maintains soundness of Rust code, at the + /// expense of incompatibility with C code. /// /// ### Example /// @@ -791,8 +791,10 @@ declare_lint! { /// - offset_of!(Floats, a) == 0 /// - offset_of!(Floats, b) == 8 /// - offset_of!(Floats, c) == 12 - /// However, rust currently aligns `c` at offset_of!(Floats, c) == 16. - /// Thus, a warning should be produced for the above struct in this case. + /// + /// However, Rust currently aligns `c` at `offset_of!(Floats, c) == 16`. + /// Using offset 12 would be unsound since `f64` generally must be 8-aligned on this target. + /// Thus, a warning is produced for the above struct. USES_POWER_ALIGNMENT, Warn, "Structs do not follow the power alignment rule under repr(C)" From 65bf8a8866557408b9e23ce3a99ec44c29dcb625 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Mar 2025 14:48:13 +0100 Subject: [PATCH 0361/2248] machine clock: make 'monotonic' explicit --- src/tools/miri/src/clock.rs | 30 +++++++++++++----------- src/tools/miri/src/concurrency/thread.rs | 16 ++++++------- src/tools/miri/src/lib.rs | 2 +- src/tools/miri/src/machine.rs | 8 +++---- src/tools/miri/src/shims/time.rs | 8 ++++--- 5 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/tools/miri/src/clock.rs b/src/tools/miri/src/clock.rs index c9bffc449f7f0..34465e9cac60d 100644 --- a/src/tools/miri/src/clock.rs +++ b/src/tools/miri/src/clock.rs @@ -62,12 +62,12 @@ impl Instant { /// A monotone clock used for `Instant` simulation. #[derive(Debug)] -pub struct Clock { - kind: ClockKind, +pub struct MonotonicClock { + kind: MonotonicClockKind, } #[derive(Debug)] -enum ClockKind { +enum MonotonicClockKind { Host { /// The "epoch" for this machine's monotone clock: /// the moment we consider to be time = 0. @@ -79,13 +79,13 @@ enum ClockKind { }, } -impl Clock { +impl MonotonicClock { /// Create a new clock based on the availability of communication with the host. pub fn new(communicate: bool) -> Self { let kind = if communicate { - ClockKind::Host { epoch: StdInstant::now() } + MonotonicClockKind::Host { epoch: StdInstant::now() } } else { - ClockKind::Virtual { nanoseconds: 0.into() } + MonotonicClockKind::Virtual { nanoseconds: 0.into() } }; Self { kind } @@ -94,10 +94,10 @@ impl Clock { /// Let the time pass for a small interval. pub fn tick(&self) { match &self.kind { - ClockKind::Host { .. } => { + MonotonicClockKind::Host { .. } => { // Time will pass without us doing anything. } - ClockKind::Virtual { nanoseconds } => { + MonotonicClockKind::Virtual { nanoseconds } => { nanoseconds.update(|x| x + NANOSECONDS_PER_BASIC_BLOCK); } } @@ -106,8 +106,8 @@ impl Clock { /// Sleep for the desired duration. pub fn sleep(&self, duration: Duration) { match &self.kind { - ClockKind::Host { .. } => std::thread::sleep(duration), - ClockKind::Virtual { nanoseconds } => { + MonotonicClockKind::Host { .. } => std::thread::sleep(duration), + MonotonicClockKind::Virtual { nanoseconds } => { // Just pretend that we have slept for some time. let nanos: u128 = duration.as_nanos(); nanoseconds.update(|x| { @@ -121,15 +121,17 @@ impl Clock { /// Return the `epoch` instant (time = 0), to convert between monotone instants and absolute durations. pub fn epoch(&self) -> Instant { match &self.kind { - ClockKind::Host { epoch } => Instant { kind: InstantKind::Host(*epoch) }, - ClockKind::Virtual { .. } => Instant { kind: InstantKind::Virtual { nanoseconds: 0 } }, + MonotonicClockKind::Host { epoch } => Instant { kind: InstantKind::Host(*epoch) }, + MonotonicClockKind::Virtual { .. } => + Instant { kind: InstantKind::Virtual { nanoseconds: 0 } }, } } pub fn now(&self) -> Instant { match &self.kind { - ClockKind::Host { .. } => Instant { kind: InstantKind::Host(StdInstant::now()) }, - ClockKind::Virtual { nanoseconds } => + MonotonicClockKind::Host { .. } => + Instant { kind: InstantKind::Host(StdInstant::now()) }, + MonotonicClockKind::Virtual { nanoseconds } => Instant { kind: InstantKind::Virtual { nanoseconds: nanoseconds.get() } }, } } diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 94629964ea604..72fa918e8e511 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -347,7 +347,7 @@ enum Timeout { impl Timeout { /// How long do we have to wait from now until the specified time? - fn get_wait_time(&self, clock: &Clock) -> Duration { + fn get_wait_time(&self, clock: &MonotonicClock) -> Duration { match self { Timeout::Monotonic(instant) => instant.duration_since(clock.now()), Timeout::RealTime(time) => @@ -683,7 +683,7 @@ impl<'tcx> ThreadManager<'tcx> { } /// Get the wait time for the next timeout, or `None` if no timeout is pending. - fn next_callback_wait_time(&self, clock: &Clock) -> Option { + fn next_callback_wait_time(&self, clock: &MonotonicClock) -> Option { self.threads .iter() .filter_map(|t| { @@ -702,7 +702,7 @@ impl<'tcx> ThreadManager<'tcx> { /// used in stateless model checkers such as Loom: run the active thread as /// long as we can and switch only when we have to (the active thread was /// blocked, terminated, or has explicitly asked to be preempted). - fn schedule(&mut self, clock: &Clock) -> InterpResult<'tcx, SchedulingAction> { + fn schedule(&mut self, clock: &MonotonicClock) -> InterpResult<'tcx, SchedulingAction> { // This thread and the program can keep going. if self.threads[self.active_thread].state.is_enabled() && !self.yield_active_thread { // The currently active thread is still enabled, just continue with it. @@ -772,7 +772,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { for (id, thread) in this.machine.threads.threads.iter_enumerated_mut() { match &thread.state { ThreadState::Blocked { timeout: Some(timeout), .. } - if timeout.get_wait_time(&this.machine.clock) == Duration::ZERO => + if timeout.get_wait_time(&this.machine.monotonic_clock) == Duration::ZERO => { let old_state = mem::replace(&mut thread.state, ThreadState::Enabled); let ThreadState::Blocked { callback, .. } = old_state else { unreachable!() }; @@ -1006,8 +1006,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } TimeoutClock::Monotonic => Timeout::Monotonic(match anchor { - TimeoutAnchor::Absolute => this.machine.clock.epoch(), - TimeoutAnchor::Relative => this.machine.clock.now(), + TimeoutAnchor::Absolute => this.machine.monotonic_clock.epoch(), + TimeoutAnchor::Relative => this.machine.monotonic_clock.now(), }), }; anchor.add_lossy(duration) @@ -1152,7 +1152,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.machine.handle_abnormal_termination(); throw_machine_stop!(TerminationInfo::Interrupted); } - match this.machine.threads.schedule(&this.machine.clock)? { + match this.machine.threads.schedule(&this.machine.monotonic_clock)? { SchedulingAction::ExecuteStep => { if !this.step()? { // See if this thread can do something else. @@ -1167,7 +1167,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.run_timeout_callback()?; } SchedulingAction::Sleep(duration) => { - this.machine.clock.sleep(duration); + this.machine.monotonic_clock.sleep(duration); } } } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 03f76cfa6524c..5921ba8663902 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -121,7 +121,7 @@ pub use crate::borrow_tracker::stacked_borrows::{ }; pub use crate::borrow_tracker::tree_borrows::{EvalContextExt as _, Tree}; pub use crate::borrow_tracker::{BorTag, BorrowTrackerMethod, EvalContextExt as _, RetagFields}; -pub use crate::clock::{Clock, Instant}; +pub use crate::clock::{Instant, MonotonicClock}; pub use crate::concurrency::cpu_affinity::MAX_CPUS; pub use crate::concurrency::data_race::{ AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index bd901a4ed19eb..3de20f92afa42 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -486,7 +486,7 @@ pub struct MiriMachine<'tcx> { pub(crate) epoll_interests: shims::EpollInterestTable, /// This machine's monotone clock. - pub(crate) clock: Clock, + pub(crate) monotonic_clock: MonotonicClock, /// The set of threads. pub(crate) threads: ThreadManager<'tcx>, @@ -710,7 +710,7 @@ impl<'tcx> MiriMachine<'tcx> { preemption_rate: config.preemption_rate, report_progress: config.report_progress, basic_block_count: 0, - clock: Clock::new(config.isolated_op == IsolatedOp::Allow), + monotonic_clock: MonotonicClock::new(config.isolated_op == IsolatedOp::Allow), #[cfg(unix)] native_lib: config.native_lib.as_ref().map(|lib_file_path| { let host_triple = rustc_session::config::host_tuple(); @@ -892,7 +892,7 @@ impl VisitProvenance for MiriMachine<'_> { tcx: _, isolated_op: _, validation: _, - clock: _, + monotonic_clock: _, layouts: _, static_roots: _, profiler: _, @@ -1563,7 +1563,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx.maybe_preempt_active_thread(); // Make sure some time passes. - ecx.machine.clock.tick(); + ecx.machine.monotonic_clock.tick(); interp_ok(()) } diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 64b3ce6b4e494..d7c445b47cb0e 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -79,7 +79,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.check_no_isolation("`clock_gettime` with `REALTIME` clocks")?; system_time_to_duration(&SystemTime::now())? } else if relative_clocks.contains(&clk_id) { - this.machine.clock.now().duration_since(this.machine.clock.epoch()) + this.machine.monotonic_clock.now().duration_since(this.machine.monotonic_clock.epoch()) } else { return this.set_last_error_and_return_i32(LibcError("EINVAL")); }; @@ -248,7 +248,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // QueryPerformanceCounter uses a hardware counter as its basis. // Miri will emulate a counter with a resolution of 1 nanosecond. - let duration = this.machine.clock.now().duration_since(this.machine.clock.epoch()); + let duration = + this.machine.monotonic_clock.now().duration_since(this.machine.monotonic_clock.epoch()); let qpc = i64::try_from(duration.as_nanos()).map_err(|_| { err_unsup_format!("programs running longer than 2^63 nanoseconds are not supported") })?; @@ -287,7 +288,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // This returns a u64, with time units determined dynamically by `mach_timebase_info`. // We return plain nanoseconds. - let duration = this.machine.clock.now().duration_since(this.machine.clock.epoch()); + let duration = + this.machine.monotonic_clock.now().duration_since(this.machine.monotonic_clock.epoch()); let res = u64::try_from(duration.as_nanos()).map_err(|_| { err_unsup_format!("programs running longer than 2^64 nanoseconds are not supported") })?; From cdbb219f835ebb3dad05a02c48afa10c33f21f2b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 28 Mar 2025 12:38:32 -0300 Subject: [PATCH 0362/2248] 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 ed35b9be289ba91771d218bd9debc8e30ecd8d83 Mon Sep 17 00:00:00 2001 From: Nikolai Kuklin Date: Fri, 28 Mar 2025 18:12:18 +0100 Subject: [PATCH 0363/2248] Add `slice::align_to_uninit_mut` --- library/core/src/slice/mod.rs | 53 +++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 5bb7243c4491b..058515efdfd74 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -8,7 +8,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::intrinsics::{exact_div, unchecked_sub}; -use crate::mem::{self, SizedTypeProperties}; +use crate::mem::{self, MaybeUninit, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::{OneSidedRange, OneSidedRangeBound, Range, RangeBounds, RangeInclusive}; use crate::panic::const_panic; @@ -4589,7 +4589,7 @@ impl [T] { // or generate worse code otherwise. This is also why we need to go // through a raw pointer here. let slice: *mut [T] = self; - let mut arr: mem::MaybeUninit<[&mut I::Output; N]> = mem::MaybeUninit::uninit(); + let mut arr: MaybeUninit<[&mut I::Output; N]> = MaybeUninit::uninit(); let arr_ptr = arr.as_mut_ptr(); // SAFETY: We expect `indices` to contain disjunct values that are @@ -4774,6 +4774,55 @@ impl [T] { } } +impl [MaybeUninit] { + /// Transmutes the mutable uninitialized slice to a mutable uninitialized slice of + /// another type, ensuring alignment of the types is maintained. + /// + /// This is a safe wrapper around [`slice::align_to_mut`], so inherits the same + /// guarantees as that method. + /// + /// # Examples + /// + /// ``` + /// #![feature(align_to_uninit_mut)] + /// use std::mem::MaybeUninit; + /// + /// pub struct BumpAllocator<'scope> { + /// memory: &'scope mut [MaybeUninit], + /// } + /// + /// impl<'scope> BumpAllocator<'scope> { + /// pub fn new(memory: &'scope mut [MaybeUninit]) -> Self { + /// Self { memory } + /// } + /// pub fn try_alloc_uninit(&mut self) -> Option<&'scope mut MaybeUninit> { + /// let first_end = self.memory.as_ptr().align_offset(align_of::()) + size_of::(); + /// let prefix = self.memory.split_off_mut(..first_end)?; + /// Some(&mut prefix.align_to_uninit_mut::().1[0]) + /// } + /// pub fn try_alloc_u32(&mut self, value: u32) -> Option<&'scope mut u32> { + /// let uninit = self.try_alloc_uninit()?; + /// Some(uninit.write(value)) + /// } + /// } + /// + /// let mut memory = [MaybeUninit::::uninit(); 10]; + /// let mut allocator = BumpAllocator::new(&mut memory); + /// let v = allocator.try_alloc_u32(42); + /// assert_eq!(v, Some(&mut 42)); + /// ``` + #[unstable(feature = "align_to_uninit_mut", issue = "139062")] + #[inline] + #[must_use] + pub fn align_to_uninit_mut(&mut self) -> (&mut Self, &mut [MaybeUninit], &mut Self) { + // SAFETY: `MaybeUninit` is transparent. Correct size and alignment are guaranteed by + // `align_to_mut` itself. Therefore the only thing that we have to ensure for a safe + // `transmute` is that the values are valid for the types involved. But for `MaybeUninit` + // any values are valid, so this operation is safe. + unsafe { self.align_to_mut() } + } +} + impl [[T; N]] { /// Takes a `&[[T; N]]`, and flattens it to a `&[T]`. /// From 40b1f4899a9081c0d8edf56072aaeb510b63a415 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Mar 2025 18:32:12 +0100 Subject: [PATCH 0364/2248] 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 5952f01712521d6700a58eeb0ad8b25db7c8fd68 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 28 Mar 2025 20:10:31 +0100 Subject: [PATCH 0365/2248] 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 432a8a7a7cbf057e481e698f4478be1006612b03 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 28 Mar 2025 22:03:26 +0100 Subject: [PATCH 0366/2248] Properly handle expansion in `single_match` Having a macro call as the scrutinee is supported. However, the proposed suggestion must use the macro call itself, not its expansion. When the scrutinee is a macro call, do not complain about an irrefutable match, as the user may not be aware of the result of the macro. A comparaison will be suggested instead, as if we couldn't see the outcome of the macro. Similarly, do not accept macro calls as arm patterns. --- clippy_lints/src/matches/single_match.rs | 17 +++++----- tests/ui/single_match.fixed | 36 ++++++++++++++++++++ tests/ui/single_match.rs | 42 ++++++++++++++++++++++++ tests/ui/single_match.stderr | 20 ++++++++++- 4 files changed, 106 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index 56fbd626eefc4..735ba63eb771e 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -1,5 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::{SpanRangeExt, expr_block, snippet, snippet_block_with_context}; +use clippy_utils::source::{ + SpanRangeExt, expr_block, snippet, snippet_block_with_context, snippet_with_applicability, snippet_with_context, +}; use clippy_utils::ty::implements_trait; use clippy_utils::{ is_lint_allowed, is_unit_expr, peel_blocks, peel_hir_pat_refs, peel_middle_ty_refs, peel_n_hir_expr_refs, @@ -34,8 +36,7 @@ fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool { #[rustfmt::skip] pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>], expr: &'tcx Expr<'_>, contains_comments: bool) { if let [arm1, arm2] = arms - && arm1.guard.is_none() - && arm2.guard.is_none() + && !arms.iter().any(|arm| arm.guard.is_some() || arm.pat.span.from_expansion()) && !expr.span.from_expansion() // don't lint for or patterns for now, this makes // the lint noisy in unnecessary situations @@ -106,7 +107,7 @@ fn report_single_pattern( format!(" else {}", expr_block(cx, els, ctxt, "..", Some(expr.span), &mut app)) }); - if snippet(cx, ex.span, "..") == snippet(cx, arm.pat.span, "..") { + if ex.span.eq_ctxt(expr.span) && snippet(cx, ex.span, "..") == snippet(cx, arm.pat.span, "..") { let msg = "this pattern is irrefutable, `match` is useless"; let (sugg, help) = if is_unit_expr(arm.body) { (String::new(), "`match` expression can be removed") @@ -163,10 +164,10 @@ fn report_single_pattern( let msg = "you seem to be trying to use `match` for an equality check. Consider using `if`"; let sugg = format!( "if {} == {}{} {}{els_str}", - snippet(cx, ex.span, ".."), + snippet_with_context(cx, ex.span, ctxt, "..", &mut app).0, // PartialEq for different reference counts may not exist. "&".repeat(ref_count_diff), - snippet(cx, arm.pat.span, ".."), + snippet_with_applicability(cx, arm.pat.span, "..", &mut app), expr_block(cx, arm.body, ctxt, "..", Some(expr.span), &mut app), ); (msg, sugg) @@ -174,8 +175,8 @@ fn report_single_pattern( let msg = "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`"; let sugg = format!( "if let {} = {} {}{els_str}", - snippet(cx, arm.pat.span, ".."), - snippet(cx, ex.span, ".."), + snippet_with_applicability(cx, arm.pat.span, "..", &mut app), + snippet_with_context(cx, ex.span, ctxt, "..", &mut app).0, expr_block(cx, arm.body, ctxt, "..", Some(expr.span), &mut app), ); (msg, sugg) diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed index 0e198ec79344a..db5107600ee6d 100644 --- a/tests/ui/single_match.fixed +++ b/tests/ui/single_match.fixed @@ -366,3 +366,39 @@ fn irrefutable_match() { //~^^^^^^^^^ single_match //~| NOTE: you might want to preserve the comments from inside the `match` } + +fn issue_14493() { + macro_rules! mac { + (some) => { + Some(42) + }; + (any) => { + _ + }; + (str) => { + "foo" + }; + } + + if let Some(u) = mac!(some) { println!("{u}") } + //~^^^^ single_match + + // When scrutinee comes from macro, do not tell that arm will always match + // and suggest an equality check instead. + if mac!(str) == "foo" { println!("eq") } + //~^^^^ ERROR: for an equality check + + // Do not lint if any match arm come from expansion + match Some(0) { + mac!(some) => println!("eq"), + mac!(any) => println!("neq"), + } + match Some(0) { + Some(42) => println!("eq"), + mac!(any) => println!("neq"), + } + match Some(0) { + mac!(some) => println!("eq"), + _ => println!("neq"), + } +} diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index fcac65f8aaf5e..a367b94c4ca6b 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -461,3 +461,45 @@ fn irrefutable_match() { //~^^^^^^^^^ single_match //~| NOTE: you might want to preserve the comments from inside the `match` } + +fn issue_14493() { + macro_rules! mac { + (some) => { + Some(42) + }; + (any) => { + _ + }; + (str) => { + "foo" + }; + } + + match mac!(some) { + Some(u) => println!("{u}"), + _ => (), + } + //~^^^^ single_match + + // When scrutinee comes from macro, do not tell that arm will always match + // and suggest an equality check instead. + match mac!(str) { + "foo" => println!("eq"), + _ => (), + } + //~^^^^ ERROR: for an equality check + + // Do not lint if any match arm come from expansion + match Some(0) { + mac!(some) => println!("eq"), + mac!(any) => println!("neq"), + } + match Some(0) { + Some(42) => println!("eq"), + mac!(any) => println!("neq"), + } + match Some(0) { + mac!(some) => println!("eq"), + _ => println!("neq"), + } +} diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 2467423b9c17d..1a4edc45c928d 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -321,5 +321,23 @@ LL + println!("{u}"); LL + } | -error: aborting due to 29 previous errors +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> tests/ui/single_match.rs:478:5 + | +LL | / match mac!(some) { +LL | | Some(u) => println!("{u}"), +LL | | _ => (), +LL | | } + | |_____^ help: try: `if let Some(u) = mac!(some) { println!("{u}") }` + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match.rs:486:5 + | +LL | / match mac!(str) { +LL | | "foo" => println!("eq"), +LL | | _ => (), +LL | | } + | |_____^ help: try: `if mac!(str) == "foo" { println!("eq") }` + +error: aborting due to 31 previous errors From 676e29ba7fa756f21f6072f6ca58985dd998e377 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Fri, 28 Mar 2025 22:17:31 +0000 Subject: [PATCH 0367/2248] fix docs for `Peekable::next_if{_eq}` --- library/core/src/iter/adapters/peekable.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index cc12cd9c35601..a6522659620a0 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -271,7 +271,7 @@ impl Peekable { /// assert_eq!(iter.next_if(|&x| x == 0), Some(0)); /// // The next item returned is now 1, so `next_if` will return `None`. /// assert_eq!(iter.next_if(|&x| x == 0), None); - /// // `next_if` saves the value of the next item if it was not equal to `expected`. + /// // `next_if` retains the next item if the predicate evaluates to `false` for it. /// assert_eq!(iter.next(), Some(1)); /// ``` /// @@ -304,9 +304,9 @@ impl Peekable { /// let mut iter = (0..5).peekable(); /// // The first item of the iterator is 0; consume it. /// assert_eq!(iter.next_if_eq(&0), Some(0)); - /// // The next item returned is now 1, so `next_if` will return `None`. + /// // The next item returned is now 1, so `next_if_eq` will return `None`. /// assert_eq!(iter.next_if_eq(&0), None); - /// // `next_if_eq` saves the value of the next item if it was not equal to `expected`. + /// // `next_if_eq` retains the next item if it was not equal to `expected`. /// assert_eq!(iter.next(), Some(1)); /// ``` #[stable(feature = "peekable_next_if", since = "1.51.0")] From 03cab8680b46716f99f94f2a6b0f6a8439653661 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 29 Mar 2025 07:59:59 +0100 Subject: [PATCH 0368/2248] fix: Fix, clarify and require a value for `proc_macro_cwd` of `CrateData` --- .../rust-analyzer/.github/workflows/ci.yaml | 8 +--- src/tools/rust-analyzer/Cargo.lock | 1 + .../rust-analyzer/crates/base-db/src/input.rs | 31 +++++++------ .../hir-def/src/macro_expansion_tests/mod.rs | 2 +- .../hir-def/src/nameres/tests/incremental.rs | 9 +++- .../crates/hir-expand/src/proc_macro.rs | 6 +-- src/tools/rust-analyzer/crates/ide/src/lib.rs | 8 +++- .../crates/load-cargo/src/lib.rs | 2 +- .../crates/proc-macro-api/src/lib.rs | 4 +- .../crates/project-model/src/workspace.rs | 43 +++++++++++++------ .../cargo_hello_world_project_model.txt | 20 ++++++--- ...project_model_with_selective_overrides.txt | 20 ++++++--- ..._project_model_with_wildcard_overrides.txt | 20 ++++++--- .../output/rust_project_cfg_groups.txt | 8 +++- ...rust_project_hello_world_project_model.txt | 4 +- .../crates/test-fixture/Cargo.toml | 1 + .../crates/test-fixture/src/lib.rs | 30 +++++++------ 17 files changed, 143 insertions(+), 74 deletions(-) diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index 610f8d00aae33..0e023bfe91b12 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -24,7 +24,6 @@ jobs: pull-requests: read outputs: typescript: ${{ steps.filter.outputs.typescript }} - proc_macros: ${{ steps.filter.outputs.proc_macros }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@1441771bbfdd59dcd748680ee64ebd8faab1a242 @@ -33,15 +32,10 @@ jobs: filters: | typescript: - 'editors/code/**' - proc_macros: - - 'crates/tt/**' - - 'crates/proc-macro-api/**' - - 'crates/proc-macro-srv/**' - - 'crates/proc-macro-srv-cli/**' proc-macro-srv: needs: changes - if: github.repository == 'rust-lang/rust-analyzer' && needs.changes.outputs.proc_macros == 'true' + if: github.repository == 'rust-lang/rust-analyzer' name: proc-macro-srv runs-on: ubuntu-latest env: diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 2c421451213d5..b6a32d5b6421e 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -2305,6 +2305,7 @@ dependencies = [ "cfg", "hir-expand", "intern", + "paths", "rustc-hash 2.1.1", "span", "stdx", diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index 343aba1a169cf..cfc22b7246534 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -303,9 +303,11 @@ pub struct CrateData { pub dependencies: Vec>, pub origin: CrateOrigin, pub is_proc_macro: bool, - /// The working directory to run proc-macros in. This is the workspace root of the cargo workspace - /// for workspace members, the crate manifest dir otherwise. - pub proc_macro_cwd: Option, + /// The working directory to run proc-macros in invoked in the context of this crate. + /// This is the workspace root of the cargo workspace for workspace members, the crate manifest + /// dir otherwise. + // FIXME: This ought to be a `VfsPath` or something opaque. + pub proc_macro_cwd: Arc, } pub type CrateDataBuilder = CrateData; @@ -425,7 +427,7 @@ impl CrateGraphBuilder { mut env: Env, origin: CrateOrigin, is_proc_macro: bool, - proc_macro_cwd: Option, + proc_macro_cwd: Arc, ws_data: Arc, ) -> CrateBuilderId { env.entries.shrink_to_fit(); @@ -861,6 +863,7 @@ impl fmt::Display for CyclicDependenciesError { #[cfg(test)] mod tests { use triomphe::Arc; + use vfs::AbsPathBuf; use crate::{CrateWorkspaceData, DependencyBuilder}; @@ -883,7 +886,7 @@ mod tests { Env::default(), CrateOrigin::Local { repo: None, name: None }, false, - None, + Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())), empty_ws_data(), ); let crate2 = graph.add_crate_root( @@ -896,7 +899,7 @@ mod tests { Env::default(), CrateOrigin::Local { repo: None, name: None }, false, - None, + Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())), empty_ws_data(), ); let crate3 = graph.add_crate_root( @@ -909,7 +912,7 @@ mod tests { Env::default(), CrateOrigin::Local { repo: None, name: None }, false, - None, + Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())), empty_ws_data(), ); assert!( @@ -942,7 +945,7 @@ mod tests { Env::default(), CrateOrigin::Local { repo: None, name: None }, false, - None, + Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())), empty_ws_data(), ); let crate2 = graph.add_crate_root( @@ -955,7 +958,7 @@ mod tests { Env::default(), CrateOrigin::Local { repo: None, name: None }, false, - None, + Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())), empty_ws_data(), ); assert!( @@ -983,7 +986,7 @@ mod tests { Env::default(), CrateOrigin::Local { repo: None, name: None }, false, - None, + Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())), empty_ws_data(), ); let crate2 = graph.add_crate_root( @@ -996,7 +999,7 @@ mod tests { Env::default(), CrateOrigin::Local { repo: None, name: None }, false, - None, + Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())), empty_ws_data(), ); let crate3 = graph.add_crate_root( @@ -1009,7 +1012,7 @@ mod tests { Env::default(), CrateOrigin::Local { repo: None, name: None }, false, - None, + Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())), empty_ws_data(), ); assert!( @@ -1037,7 +1040,7 @@ mod tests { Env::default(), CrateOrigin::Local { repo: None, name: None }, false, - None, + Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())), empty_ws_data(), ); let crate2 = graph.add_crate_root( @@ -1050,7 +1053,7 @@ mod tests { Env::default(), CrateOrigin::Local { repo: None, name: None }, false, - None, + Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())), empty_ws_data(), ); assert!( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs index d9fbf4b17c5d8..15eb5db056938 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -362,7 +362,7 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander { _: Span, _: Span, _: Span, - _: Option, + _: String, ) -> Result { let (parse, _) = syntax_bridge::token_tree_to_syntax_node( subtree, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs index 14653c64a6141..d3663182c997b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs @@ -52,6 +52,7 @@ pub const BAZ: u32 = 0; { // Add a dependency a -> b. let mut new_crate_graph = CrateGraphBuilder::default(); + let mut add_crate = |crate_name, root_file_idx: usize| { new_crate_graph.add_crate_root( files[root_file_idx].file_id(), @@ -63,7 +64,13 @@ pub const BAZ: u32 = 0; Env::default(), CrateOrigin::Local { repo: None, name: Some(Symbol::intern(crate_name)) }, false, - None, + Arc::new( + // FIXME: This is less than ideal + TryFrom::try_from( + &*std::env::current_dir().unwrap().as_path().to_string_lossy(), + ) + .unwrap(), + ), Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None }), ) }; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs index ceb6972a50c3e..4920d90a9747f 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs @@ -41,7 +41,7 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe + AsAny { def_site: Span, call_site: Span, mixed_site: Span, - current_dir: Option, + current_dir: String, ) -> Result; fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool; @@ -318,8 +318,8 @@ impl CustomProcMacroExpander { // Proc macros have access to the environment variables of the invoking crate. let env = calling_crate.env(db); - let current_dir = - calling_crate.data(db).proc_macro_cwd.as_deref().map(ToString::to_string); + // FIXME: Can we avoid the string allocation here? + let current_dir = calling_crate.data(db).proc_macro_cwd.to_string(); match proc_macro.expander.expand( tt, diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index f85a7bf2f2572..434059cdfbd12 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -244,6 +244,12 @@ impl Analysis { // FIXME: cfg options // Default to enable test for single file. let mut cfg_options = CfgOptions::default(); + + // FIXME: This is less than ideal + let proc_macro_cwd = Arc::new( + TryFrom::try_from(&*std::env::current_dir().unwrap().as_path().to_string_lossy()) + .unwrap(), + ); cfg_options.insert_atom(sym::test.clone()); crate_graph.add_crate_root( file_id, @@ -255,7 +261,7 @@ impl Analysis { Env::default(), CrateOrigin::Local { repo: None, name: None }, false, - None, + proc_macro_cwd, Arc::new(CrateWorkspaceData { data_layout: Err("fixture has no layout".into()), toolchain: None, diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 243619bb09fd2..c85eda70462de 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -496,7 +496,7 @@ impl ProcMacroExpander for Expander { def_site: Span, call_site: Span, mixed_site: Span, - current_dir: Option, + current_dir: String, ) -> Result, ProcMacroExpansionError> { match self.0.expand( subtree.view(), diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs index c692d5a549fee..d67d6058d50aa 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs @@ -170,7 +170,7 @@ impl ProcMacro { def_site: Span, call_site: Span, mixed_site: Span, - current_dir: Option, + current_dir: String, ) -> Result, PanicMessage>, ServerError> { let version = self.process.version(); @@ -198,7 +198,7 @@ impl ProcMacro { }, lib: self.dylib_path.to_path_buf().into(), env, - current_dir, + current_dir: Some(current_dir), }; let response = self.process.send_task(Request::ExpandMacro(Box::new(task)))?; diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 95148bb1d0cc0..857ea84d9b139 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -988,6 +988,7 @@ fn project_json_to_crate_graph( ); let mut cfg_cache: FxHashMap<&str, Vec> = FxHashMap::default(); + let project_root = Arc::new(project.project_root().to_path_buf()); let idx_to_crate_id: FxHashMap = project .crates() @@ -1067,7 +1068,10 @@ fn project_json_to_crate_graph( CrateOrigin::Local { repo: None, name: None } }, *is_proc_macro, - proc_macro_cwd.clone(), + match proc_macro_cwd { + Some(path) => Arc::new(path.clone()), + None => project_root.clone(), + }, crate_ws_data.clone(), ); debug!( @@ -1139,6 +1143,7 @@ fn cargo_to_crate_graph( let mut pkg_crates = FxHashMap::default(); // Does any crate signal to rust-analyzer that they need the rustc_private crates? let mut has_private = false; + let workspace_proc_macro_cwd = Arc::new(cargo.workspace_root().to_path_buf()); // Next, create crates for each package, target pair for pkg in cargo.packages() { @@ -1161,8 +1166,9 @@ fn cargo_to_crate_graph( let mut lib_tgt = None; for &tgt in cargo[pkg].targets.iter() { + let pkg_data = &cargo[pkg]; if !matches!(cargo[tgt].kind, TargetKind::Lib { .. }) - && (!cargo[pkg].is_member || cargo.is_sysroot()) + && (!pkg_data.is_member || cargo.is_sysroot()) { // For non-workspace-members, Cargo does not resolve dev-dependencies, so we don't // add any targets except the library target, since those will not work correctly if @@ -1176,7 +1182,6 @@ fn cargo_to_crate_graph( let Some(file_id) = load(root) else { continue }; let build_data = build_scripts.get_output(pkg); - let pkg_data = &cargo[pkg]; let crate_id = add_target_crate_root( crate_graph, proc_macros, @@ -1203,6 +1208,11 @@ fn cargo_to_crate_graph( } }, crate_ws_data.clone(), + if pkg_data.is_member { + workspace_proc_macro_cwd.clone() + } else { + Arc::new(pkg_data.manifest.parent().to_path_buf()) + }, ); if let TargetKind::Lib { .. } = kind { lib_tgt = Some((crate_id, name.clone())); @@ -1364,7 +1374,7 @@ fn detached_file_to_crate_graph( name: display_name.map(|n| n.canonical_name().to_owned()), }, false, - None, + Arc::new(detached_file.parent().to_path_buf()), crate_ws_data, ); @@ -1372,6 +1382,7 @@ fn detached_file_to_crate_graph( (crate_graph, FxHashMap::default()) } +// FIXME: There shouldn't really be a need for duplicating all of this? fn handle_rustc_crates( crate_graph: &mut CrateGraphBuilder, proc_macros: &mut ProcMacroPaths, @@ -1391,6 +1402,7 @@ fn handle_rustc_crates( // The root package of the rustc-dev component is rustc_driver, so we match that let root_pkg = rustc_workspace.packages().find(|&package| rustc_workspace[package].name == "rustc_driver"); + let workspace_proc_macro_cwd = Arc::new(cargo.workspace_root().to_path_buf()); // The rustc workspace might be incomplete (such as if rustc-dev is not // installed for the current toolchain) and `rustc_source` is set to discover. if let Some(root_pkg) = root_pkg { @@ -1404,14 +1416,15 @@ fn handle_rustc_crates( if rustc_pkg_crates.contains_key(&pkg) { continue; } - for dep in &rustc_workspace[pkg].dependencies { + let pkg_data = &rustc_workspace[pkg]; + for dep in &pkg_data.dependencies { queue.push_back(dep.pkg); } let mut cfg_options = cfg_options.clone(); - override_cfg.apply(&mut cfg_options, &rustc_workspace[pkg].name); + override_cfg.apply(&mut cfg_options, &pkg_data.name); - for &tgt in rustc_workspace[pkg].targets.iter() { + for &tgt in pkg_data.targets.iter() { let kind @ TargetKind::Lib { is_proc_macro } = rustc_workspace[tgt].kind else { continue; }; @@ -1421,14 +1434,19 @@ fn handle_rustc_crates( crate_graph, proc_macros, rustc_workspace, - &rustc_workspace[pkg], + pkg_data, build_scripts.get_output(pkg).zip(Some(build_scripts.error().is_some())), cfg_options.clone(), file_id, &rustc_workspace[tgt].name, kind, - CrateOrigin::Rustc { name: Symbol::intern(&rustc_workspace[pkg].name) }, + CrateOrigin::Rustc { name: Symbol::intern(&pkg_data.name) }, crate_ws_data.clone(), + if pkg_data.is_member { + workspace_proc_macro_cwd.clone() + } else { + Arc::new(pkg_data.manifest.parent().to_path_buf()) + }, ); pkg_to_lib_crate.insert(pkg, crate_id); // Add dependencies on core / std / alloc for this crate @@ -1490,6 +1508,7 @@ fn add_target_crate_root( kind: TargetKind, origin: CrateOrigin, crate_ws_data: Arc, + proc_macro_cwd: Arc, ) -> CrateBuilderId { let edition = pkg.edition; let potential_cfg_options = if pkg.features.is_empty() { @@ -1531,9 +1550,7 @@ fn add_target_crate_root( env, origin, matches!(kind, TargetKind::Lib { is_proc_macro: true }), - matches!(kind, TargetKind::Lib { is_proc_macro: true }).then(|| { - if pkg.is_member { cargo.workspace_root() } else { pkg.manifest.parent() }.to_path_buf() - }), + proc_macro_cwd, crate_ws_data, ); if let TargetKind::Lib { is_proc_macro: true } = kind { @@ -1706,7 +1723,7 @@ fn sysroot_to_crate_graph( Env::default(), CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)), false, - None, + Arc::new(stitched[krate].root.parent().to_path_buf()), crate_ws_data.clone(), ); Some((krate, crate_id)) diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt index d30d67ed1f3a4..4ef9d81611974 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt @@ -22,7 +22,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -104,7 +106,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -186,7 +190,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -268,7 +274,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -333,7 +341,9 @@ name: "libc", }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98", + ), }, extra: ExtraCrateData { version: Some( diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt index d30d67ed1f3a4..4ef9d81611974 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt @@ -22,7 +22,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -104,7 +106,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -186,7 +190,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -268,7 +274,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -333,7 +341,9 @@ name: "libc", }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98", + ), }, extra: ExtraCrateData { version: Some( diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt index 925233ceb4112..52089d1dbc2ce 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt @@ -22,7 +22,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -103,7 +105,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -184,7 +188,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -265,7 +271,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$hello-world", + ), }, extra: ExtraCrateData { version: Some( @@ -329,7 +337,9 @@ name: "libc", }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98", + ), }, extra: ExtraCrateData { version: Some( diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt index 5f18d5e3f08bd..98fe598eb3a32 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt @@ -13,7 +13,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$", + ), }, extra: ExtraCrateData { version: None, @@ -61,7 +63,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$", + ), }, extra: ExtraCrateData { version: None, diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt index 5cb9992b203b2..0dc373b5b47ed 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt @@ -13,7 +13,9 @@ ), }, is_proc_macro: false, - proc_macro_cwd: None, + proc_macro_cwd: AbsPathBuf( + "$ROOT$", + ), }, extra: ExtraCrateData { version: None, diff --git a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml index 2547a02a2916c..353d4c312dba8 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml +++ b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml @@ -19,6 +19,7 @@ span.workspace = true stdx.workspace = true intern.workspace = true triomphe.workspace = true +paths.workspace = true [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs index f0b85b4ab33ce..0509a39bda8c2 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs +++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs @@ -19,6 +19,7 @@ use hir_expand::{ tt::{Leaf, TokenTree, TopSubtree, TopSubtreeBuilder, TtElement, TtIter}, }; use intern::{Symbol, sym}; +use paths::AbsPathBuf; use rustc_hash::FxHashMap; use span::{Edition, EditionedFileId, FileId, Span}; use stdx::itertools::Itertools; @@ -162,6 +163,9 @@ impl ChangeFixture { let crate_ws_data = Arc::new(CrateWorkspaceData { data_layout: target_data_layout, toolchain }); + // FIXME: This is less than ideal + let proc_macro_cwd = Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())); + for entry in fixture { let mut range_or_offset = None; let text = if entry.text.contains(CURSOR_MARKER) { @@ -213,7 +217,7 @@ impl ChangeFixture { meta.env, origin, false, - None, + proc_macro_cwd.clone(), crate_ws_data.clone(), ); let prev = crates.insert(crate_name.clone(), crate_id); @@ -254,7 +258,7 @@ impl ChangeFixture { default_env, CrateOrigin::Local { repo: None, name: None }, false, - None, + proc_macro_cwd.clone(), crate_ws_data.clone(), ); } else { @@ -296,7 +300,7 @@ impl ChangeFixture { )]), CrateOrigin::Lang(LangCrateOrigin::Core), false, - None, + proc_macro_cwd.clone(), crate_ws_data.clone(), ); @@ -345,7 +349,7 @@ impl ChangeFixture { )]), CrateOrigin::Local { repo: None, name: None }, true, - None, + proc_macro_cwd.clone(), crate_ws_data, ); proc_macros.insert(proc_macros_crate, Ok(proc_macro)); @@ -650,7 +654,7 @@ impl ProcMacroExpander for IdentityProcMacroExpander { _: Span, _: Span, _: Span, - _: Option, + _: String, ) -> Result { Ok(subtree.clone()) } @@ -672,7 +676,7 @@ impl ProcMacroExpander for Issue18089ProcMacroExpander { _: Span, call_site: Span, _: Span, - _: Option, + _: String, ) -> Result { let tt::TokenTree::Leaf(macro_name) = &subtree.0[2] else { return Err(ProcMacroExpansionError::Panic("incorrect input".to_owned())); @@ -707,7 +711,7 @@ impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander { _: Span, _: Span, _: Span, - _: Option, + _: String, ) -> Result { attrs .cloned() @@ -730,7 +734,7 @@ impl ProcMacroExpander for Issue18840ProcMacroExpander { def_site: Span, _: Span, _: Span, - _: Option, + _: String, ) -> Result { // Input: // ``` @@ -765,7 +769,7 @@ impl ProcMacroExpander for MirrorProcMacroExpander { _: Span, _: Span, _: Span, - _: Option, + _: String, ) -> Result { fn traverse(builder: &mut TopSubtreeBuilder, iter: TtIter<'_>) { for tt in iter.collect_vec().into_iter().rev() { @@ -803,7 +807,7 @@ impl ProcMacroExpander for ShortenProcMacroExpander { _: Span, _: Span, _: Span, - _: Option, + _: String, ) -> Result { let mut result = input.0.clone(); for it in &mut result { @@ -845,7 +849,7 @@ impl ProcMacroExpander for Issue17479ProcMacroExpander { _: Span, _: Span, _: Span, - _: Option, + _: String, ) -> Result { let TokenTree::Leaf(Leaf::Literal(lit)) = &subtree.0[1] else { return Err(ProcMacroExpansionError::Panic("incorrect Input".into())); @@ -874,7 +878,7 @@ impl ProcMacroExpander for Issue18898ProcMacroExpander { def_site: Span, _: Span, _: Span, - _: Option, + _: String, ) -> Result { let span = subtree .token_trees() @@ -929,7 +933,7 @@ impl ProcMacroExpander for DisallowCfgProcMacroExpander { _: Span, _: Span, _: Span, - _: Option, + _: String, ) -> Result { for tt in subtree.token_trees().flat_tokens() { if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = tt { From 6a915967f1d0033ce9e1a920885829d9ffe32716 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 29 Mar 2025 00:53:12 -0700 Subject: [PATCH 0369/2248] Promise `array::from_fn` in generated in order of increasing indices --- library/core/src/array/mod.rs | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 28329bb090845..efa7bed7c8e17 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -55,12 +55,16 @@ pub fn repeat(val: T) -> [T; N] { from_trusted_iterator(repeat_n(val, N)) } -/// Creates an array of type [T; N], where each element `T` is the returned value from `cb` -/// using that element's index. +/// Creates an array where each element is produced by calling `f` with +/// that element's index while walking forward through the array. /// -/// # Arguments +/// This is essentially the same as writing +/// ```text +/// [f(0), f(1), f(2), …, f(N - 2), f(N - 1)] +/// ``` +/// and is similar to `(0..i).map(f)`, just for arrays not iterators. /// -/// * `cb`: Callback where the passed argument is the current array index. +/// If `N == 0`, this produces an empty array without ever calling `f`. /// /// # Example /// @@ -82,13 +86,30 @@ pub fn repeat(val: T) -> [T; N] { /// // indexes are: 0 1 2 3 4 /// assert_eq!(bool_arr, [true, false, true, false, true]); /// ``` +/// +/// You can also capture things, for example to create an array full of clones +/// where you can't just use `[item; N]` because it's not `Copy`: +/// ``` +/// # // TBH `array::repeat` would be better for this, but it's not stable yet. +/// let my_string = String::from("Hello"); +/// let clones: [String; 42] = std::array::from_fn(|_| my_string.clone()); +/// assert!(clones.iter().all(|x| *x == my_string)); +/// ``` +/// +/// The array is generated in ascending index order, starting from the front +/// and going towards the back, so you can use closures with mutable state: +/// ``` +/// let mut state = 1; +/// let a = std::array::from_fn(|_| { let x = state; state *= 2; x }); +/// assert_eq!(a, [1, 2, 4, 8, 16, 32]); +/// ``` #[inline] #[stable(feature = "array_from_fn", since = "1.63.0")] -pub fn from_fn(cb: F) -> [T; N] +pub fn from_fn(f: F) -> [T; N] where F: FnMut(usize) -> T, { - try_from_fn(NeverShortCircuit::wrap_mut_1(cb)).0 + try_from_fn(NeverShortCircuit::wrap_mut_1(f)).0 } /// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call. From bc701925d8313a0d3e5092378d66c1df565dc1b9 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 29 Mar 2025 11:18:49 +0100 Subject: [PATCH 0370/2248] Take advantage of match ergonomics in `clippy_utils::hir_utils` This is a style-only change in order to use match ergonomics by removing unneeded `&` and `ref`. --- clippy_utils/src/hir_utils.rs | 266 +++++++++++++++++----------------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 9938e64d24264..4b16896c2986c 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -148,7 +148,7 @@ pub struct HirEqInterExpr<'a, 'b, 'tcx> { impl HirEqInterExpr<'_, '_, '_> { pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool { match (&left.kind, &right.kind) { - (&StmtKind::Let(l), &StmtKind::Let(r)) => { + (StmtKind::Let(l), StmtKind::Let(r)) => { // This additional check ensures that the type of the locals are equivalent even if the init // expression or type have some inferred parts. if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results { @@ -166,7 +166,7 @@ impl HirEqInterExpr<'_, '_, '_> { && both(l.els.as_ref(), r.els.as_ref(), |l, r| self.eq_block(l, r)) && self.eq_pat(l.pat, r.pat) }, - (&StmtKind::Expr(l), &StmtKind::Expr(r)) | (&StmtKind::Semi(l), &StmtKind::Semi(r)) => self.eq_expr(l, r), + (StmtKind::Expr(l), StmtKind::Expr(r)) | (StmtKind::Semi(l), StmtKind::Semi(r)) => self.eq_expr(l, r), _ => false, } } @@ -260,7 +260,7 @@ impl HirEqInterExpr<'_, '_, '_> { fn should_ignore(&mut self, expr: &Expr<'_>) -> bool { macro_backtrace(expr.span).last().is_some_and(|macro_call| { matches!( - &self.inner.cx.tcx.get_diagnostic_name(macro_call.def_id), + self.inner.cx.tcx.get_diagnostic_name(macro_call.def_id), Some(sym::todo_macro | sym::unimplemented_macro) ) }) @@ -301,58 +301,58 @@ impl HirEqInterExpr<'_, '_, '_> { reduce_exprkind(self.inner.cx, &left.kind), reduce_exprkind(self.inner.cx, &right.kind), ) { - (&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => { + (ExprKind::AddrOf(lb, l_mut, le), ExprKind::AddrOf(rb, r_mut, re)) => { lb == rb && l_mut == r_mut && self.eq_expr(le, re) }, - (&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r), - (&ExprKind::Assign(ll, lr, _), &ExprKind::Assign(rl, rr, _)) => { + (ExprKind::Array(l), ExprKind::Array(r)) => self.eq_exprs(l, r), + (ExprKind::Assign(ll, lr, _), ExprKind::Assign(rl, rr, _)) => { self.inner.allow_side_effects && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }, - (&ExprKind::AssignOp(ref lo, ll, lr), &ExprKind::AssignOp(ref ro, rl, rr)) => { + (ExprKind::AssignOp(lo, ll, lr), ExprKind::AssignOp(ro, rl, rr)) => { self.inner.allow_side_effects && lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }, - (&ExprKind::Block(l, _), &ExprKind::Block(r, _)) => self.eq_block(l, r), - (&ExprKind::Binary(l_op, ll, lr), &ExprKind::Binary(r_op, rl, rr)) => { + (ExprKind::Block(l, _), ExprKind::Block(r, _)) => self.eq_block(l, r), + (ExprKind::Binary(l_op, ll, lr), ExprKind::Binary(r_op, rl, rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || swap_binop(l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| { l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }) }, - (&ExprKind::Break(li, ref le), &ExprKind::Break(ri, ref re)) => { + (ExprKind::Break(li, le), ExprKind::Break(ri, re)) => { both(li.label.as_ref(), ri.label.as_ref(), |l, r| l.ident.name == r.ident.name) && both(le.as_ref(), re.as_ref(), |l, r| self.eq_expr(l, r)) }, - (&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => { + (ExprKind::Call(l_fun, l_args), ExprKind::Call(r_fun, r_args)) => { self.inner.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) }, - (&ExprKind::Cast(lx, lt), &ExprKind::Cast(rx, rt)) => { + (ExprKind::Cast(lx, lt), ExprKind::Cast(rx, rt)) => { self.eq_expr(lx, rx) && self.eq_ty(lt, rt) }, - (&ExprKind::Closure(_l), &ExprKind::Closure(_r)) => false, - (&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body), - (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => { + (ExprKind::Closure(_l), ExprKind::Closure(_r)) => false, + (ExprKind::ConstBlock(lb), ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body), + (ExprKind::Continue(li), ExprKind::Continue(ri)) => { both(li.label.as_ref(), ri.label.as_ref(), |l, r| l.ident.name == r.ident.name) }, - (&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re), - (&ExprKind::Field(l_f_exp, ref l_f_ident), &ExprKind::Field(r_f_exp, ref r_f_ident)) => { + (ExprKind::DropTemps(le), ExprKind::DropTemps(re)) => self.eq_expr(le, re), + (ExprKind::Field(l_f_exp, l_f_ident), ExprKind::Field(r_f_exp, r_f_ident)) => { l_f_ident.name == r_f_ident.name && self.eq_expr(l_f_exp, r_f_exp) }, - (&ExprKind::Index(la, li, _), &ExprKind::Index(ra, ri, _)) => self.eq_expr(la, ra) && self.eq_expr(li, ri), - (&ExprKind::If(lc, lt, ref le), &ExprKind::If(rc, rt, ref re)) => { + (ExprKind::Index(la, li, _), ExprKind::Index(ra, ri, _)) => self.eq_expr(la, ra) && self.eq_expr(li, ri), + (ExprKind::If(lc, lt, le), ExprKind::If(rc, rt, re)) => { self.eq_expr(lc, rc) && self.eq_expr(lt, rt) && both(le.as_ref(), re.as_ref(), |l, r| self.eq_expr(l, r)) }, - (&ExprKind::Let(l), &ExprKind::Let(r)) => { + (ExprKind::Let(l), ExprKind::Let(r)) => { self.eq_pat(l.pat, r.pat) && both(l.ty.as_ref(), r.ty.as_ref(), |l, r| self.eq_ty(l, r)) && self.eq_expr(l.init, r.init) }, (ExprKind::Lit(l), ExprKind::Lit(r)) => l.node == r.node, - (&ExprKind::Loop(lb, ref ll, ref lls, _), &ExprKind::Loop(rb, ref rl, ref rls, _)) => { + (ExprKind::Loop(lb, ll, lls, _), ExprKind::Loop(rb, rl, rls, _)) => { lls == rls && self.eq_block(lb, rb) && both(ll.as_ref(), rl.as_ref(), |l, r| l.ident.name == r.ident.name) }, - (&ExprKind::Match(le, la, ref ls), &ExprKind::Match(re, ra, ref rs)) => { + (ExprKind::Match(le, la, ls), ExprKind::Match(re, ra, rs)) => { (ls == rs || (matches!((ls, rs), (TryDesugar(_), TryDesugar(_))))) && self.eq_expr(le, re) && over(la, ra, |l, r| { @@ -362,27 +362,27 @@ impl HirEqInterExpr<'_, '_, '_> { }) }, ( - &ExprKind::MethodCall(l_path, l_receiver, l_args, _), - &ExprKind::MethodCall(r_path, r_receiver, r_args, _), + ExprKind::MethodCall(l_path, l_receiver, l_args, _), + ExprKind::MethodCall(r_path, r_receiver, r_args, _), ) => { self.inner.allow_side_effects && self.eq_path_segment(l_path, r_path) && self.eq_expr(l_receiver, r_receiver) && self.eq_exprs(l_args, r_args) }, - (&ExprKind::UnsafeBinderCast(lkind, le, None), &ExprKind::UnsafeBinderCast(rkind, re, None)) => + (ExprKind::UnsafeBinderCast(lkind, le, None), ExprKind::UnsafeBinderCast(rkind, re, None)) => lkind == rkind && self.eq_expr(le, re), - (&ExprKind::UnsafeBinderCast(lkind, le, Some(lt)), &ExprKind::UnsafeBinderCast(rkind, re, Some(rt))) => + (ExprKind::UnsafeBinderCast(lkind, le, Some(lt)), ExprKind::UnsafeBinderCast(rkind, re, Some(rt))) => lkind == rkind && self.eq_expr(le, re) && self.eq_ty(lt, rt), - (&ExprKind::OffsetOf(l_container, l_fields), &ExprKind::OffsetOf(r_container, r_fields)) => { + (ExprKind::OffsetOf(l_container, l_fields), ExprKind::OffsetOf(r_container, r_fields)) => { self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name) }, (ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r), - (&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => { + (ExprKind::Repeat(le, ll), ExprKind::Repeat(re, rl)) => { self.eq_expr(le, re) && self.eq_const_arg(ll, rl) }, (ExprKind::Ret(l), ExprKind::Ret(r)) => both(l.as_ref(), r.as_ref(), |l, r| self.eq_expr(l, r)), - (&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => { + (ExprKind::Struct(l_path, lf, lo), ExprKind::Struct(r_path, rf, ro)) => { self.eq_qpath(l_path, r_path) && match (lo, ro) { (StructTailExpr::Base(l),StructTailExpr::Base(r)) => self.eq_expr(l, r), @@ -392,58 +392,58 @@ impl HirEqInterExpr<'_, '_, '_> { } && over(lf, rf, |l, r| self.eq_expr_field(l, r)) }, - (&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup), - (&ExprKind::Use(l_expr, _), &ExprKind::Use(r_expr, _)) => self.eq_expr(l_expr, r_expr), - (&ExprKind::Type(le, lt), &ExprKind::Type(re, rt)) => self.eq_expr(le, re) && self.eq_ty(lt, rt), - (&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re), - (&ExprKind::Yield(le, _), &ExprKind::Yield(re, _)) => return self.eq_expr(le, re), + (ExprKind::Tup(l_tup), ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup), + (ExprKind::Use(l_expr, _), ExprKind::Use(r_expr, _)) => self.eq_expr(l_expr, r_expr), + (ExprKind::Type(le, lt), ExprKind::Type(re, rt)) => self.eq_expr(le, re) && self.eq_ty(lt, rt), + (ExprKind::Unary(l_op, le), ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re), + (ExprKind::Yield(le, _), ExprKind::Yield(re, _)) => return self.eq_expr(le, re), ( // Else branches for branches above, grouped as per `match_same_arms`. - | &ExprKind::AddrOf(..) - | &ExprKind::Array(..) - | &ExprKind::Assign(..) - | &ExprKind::AssignOp(..) - | &ExprKind::Binary(..) - | &ExprKind::Become(..) - | &ExprKind::Block(..) - | &ExprKind::Break(..) - | &ExprKind::Call(..) - | &ExprKind::Cast(..) - | &ExprKind::ConstBlock(..) - | &ExprKind::Continue(..) - | &ExprKind::DropTemps(..) - | &ExprKind::Field(..) - | &ExprKind::Index(..) - | &ExprKind::If(..) - | &ExprKind::Let(..) - | &ExprKind::Lit(..) - | &ExprKind::Loop(..) - | &ExprKind::Match(..) - | &ExprKind::MethodCall(..) - | &ExprKind::OffsetOf(..) - | &ExprKind::Path(..) - | &ExprKind::Repeat(..) - | &ExprKind::Ret(..) - | &ExprKind::Struct(..) - | &ExprKind::Tup(..) - | &ExprKind::Use(..) - | &ExprKind::Type(..) - | &ExprKind::Unary(..) - | &ExprKind::Yield(..) - | &ExprKind::UnsafeBinderCast(..) + | ExprKind::AddrOf(..) + | ExprKind::Array(..) + | ExprKind::Assign(..) + | ExprKind::AssignOp(..) + | ExprKind::Binary(..) + | ExprKind::Become(..) + | ExprKind::Block(..) + | ExprKind::Break(..) + | ExprKind::Call(..) + | ExprKind::Cast(..) + | ExprKind::ConstBlock(..) + | ExprKind::Continue(..) + | ExprKind::DropTemps(..) + | ExprKind::Field(..) + | ExprKind::Index(..) + | ExprKind::If(..) + | ExprKind::Let(..) + | ExprKind::Lit(..) + | ExprKind::Loop(..) + | ExprKind::Match(..) + | ExprKind::MethodCall(..) + | ExprKind::OffsetOf(..) + | ExprKind::Path(..) + | ExprKind::Repeat(..) + | ExprKind::Ret(..) + | ExprKind::Struct(..) + | ExprKind::Tup(..) + | ExprKind::Use(..) + | ExprKind::Type(..) + | ExprKind::Unary(..) + | ExprKind::Yield(..) + | ExprKind::UnsafeBinderCast(..) // --- Special cases that do not have a positive branch. // `Err` represents an invalid expression, so let's never assume that // an invalid expressions is equal to anything. - | &ExprKind::Err(..) + | ExprKind::Err(..) // For the time being, we always consider that two closures are unequal. // This behavior may change in the future. - | &ExprKind::Closure(..) + | ExprKind::Closure(..) // For the time being, we always consider that two instances of InlineAsm are different. // This behavior may change in the future. - | &ExprKind::InlineAsm(_) + | ExprKind::InlineAsm(_) , _ ) => false, }; @@ -494,11 +494,11 @@ impl HirEqInterExpr<'_, '_, '_> { fn eq_pat_expr(&mut self, left: &PatExpr<'_>, right: &PatExpr<'_>) -> bool { match (&left.kind, &right.kind) { ( - &PatExprKind::Lit { + PatExprKind::Lit { lit: left, negated: left_neg, }, - &PatExprKind::Lit { + PatExprKind::Lit { lit: right, negated: right_neg, }, @@ -512,47 +512,47 @@ impl HirEqInterExpr<'_, '_, '_> { /// Checks whether two patterns are the same. fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool { match (&left.kind, &right.kind) { - (&PatKind::Box(l), &PatKind::Box(r)) => self.eq_pat(l, r), - (&PatKind::Struct(ref lp, la, ..), &PatKind::Struct(ref rp, ra, ..)) => { + (PatKind::Box(l), PatKind::Box(r)) => self.eq_pat(l, r), + (PatKind::Struct(lp, la, ..), PatKind::Struct(rp, ra, ..)) => { self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat_field(l, r)) }, - (&PatKind::TupleStruct(ref lp, la, ls), &PatKind::TupleStruct(ref rp, ra, rs)) => { + (PatKind::TupleStruct(lp, la, ls), PatKind::TupleStruct(rp, ra, rs)) => { self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs }, - (&PatKind::Binding(lb, li, _, ref lp), &PatKind::Binding(rb, ri, _, ref rp)) => { + (PatKind::Binding(lb, li, _, lp), PatKind::Binding(rb, ri, _, rp)) => { let eq = lb == rb && both(lp.as_ref(), rp.as_ref(), |l, r| self.eq_pat(l, r)); if eq { - self.locals.insert(li, ri); + self.locals.insert(*li, *ri); } eq }, - (&PatKind::Expr(l), &PatKind::Expr(r)) => self.eq_pat_expr(l, r), - (&PatKind::Tuple(l, ls), &PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)), - (&PatKind::Range(ref ls, ref le, li), &PatKind::Range(ref rs, ref re, ri)) => { + (PatKind::Expr(l), PatKind::Expr(r)) => self.eq_pat_expr(l, r), + (PatKind::Tuple(l, ls), PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)), + (PatKind::Range(ls, le, li), PatKind::Range(rs, re, ri)) => { both(ls.as_ref(), rs.as_ref(), |a, b| self.eq_pat_expr(a, b)) && both(le.as_ref(), re.as_ref(), |a, b| self.eq_pat_expr(a, b)) && (li == ri) }, - (&PatKind::Ref(le, ref lm), &PatKind::Ref(re, ref rm)) => lm == rm && self.eq_pat(le, re), - (&PatKind::Slice(ls, ref li, le), &PatKind::Slice(rs, ref ri, re)) => { + (PatKind::Ref(le, lm), PatKind::Ref(re, rm)) => lm == rm && self.eq_pat(le, re), + (PatKind::Slice(ls, li, le), PatKind::Slice(rs, ri, re)) => { over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r)) && both(li.as_ref(), ri.as_ref(), |l, r| self.eq_pat(l, r)) }, - (&PatKind::Wild, &PatKind::Wild) => true, + (PatKind::Wild, PatKind::Wild) => true, _ => false, } } fn eq_qpath(&mut self, left: &QPath<'_>, right: &QPath<'_>) -> bool { match (left, right) { - (&QPath::Resolved(ref lty, lpath), &QPath::Resolved(ref rty, rpath)) => { + (QPath::Resolved(lty, lpath), QPath::Resolved(rty, rpath)) => { both(lty.as_ref(), rty.as_ref(), |l, r| self.eq_ty(l, r)) && self.eq_path(lpath, rpath) }, - (&QPath::TypeRelative(lty, lseg), &QPath::TypeRelative(rty, rseg)) => { + (QPath::TypeRelative(lty, lseg), QPath::TypeRelative(rty, rseg)) => { self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg) }, - (&QPath::LangItem(llang_item, ..), &QPath::LangItem(rlang_item, ..)) => llang_item == rlang_item, + (QPath::LangItem(llang_item, ..), QPath::LangItem(rlang_item, ..)) => llang_item == rlang_item, _ => false, } } @@ -611,15 +611,15 @@ impl HirEqInterExpr<'_, '_, '_> { pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool { match (&left.kind, &right.kind) { - (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec), - (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl), + (TyKind::Slice(l_vec), TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec), + (TyKind::Array(lt, ll), TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl), (TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty), (TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => { l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty) }, (TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r), - (&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)), - (&TyKind::Infer(()), &TyKind::Infer(())) => true, + (TyKind::Tup(l), TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)), + (TyKind::Infer(()), TyKind::Infer(())) => true, _ => false, } } @@ -853,9 +853,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { std::mem::discriminant(&e.kind).hash(&mut self.s); - match e.kind { + match &e.kind { ExprKind::AddrOf(kind, m, e) => { - std::mem::discriminant(&kind).hash(&mut self.s); + std::mem::discriminant(kind).hash(&mut self.s); m.hash(&mut self.s); self.hash_expr(e); }, @@ -871,7 +871,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(l); self.hash_expr(r); }, - ExprKind::AssignOp(ref o, l, r) => { + ExprKind::AssignOp(o, l, r) => { std::mem::discriminant(&o.node).hash(&mut self.s); self.hash_expr(l); self.hash_expr(r); @@ -887,11 +887,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(l); self.hash_expr(r); }, - ExprKind::Break(i, ref j) => { + ExprKind::Break(i, j) => { if let Some(i) = i.label { self.hash_name(i.ident.name); } - if let Some(j) = *j { + if let Some(j) = j { self.hash_expr(j); } }, @@ -903,20 +903,20 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(e); self.hash_ty(ty); }, - ExprKind::Closure(&Closure { + ExprKind::Closure(Closure { capture_clause, body, .. }) => { - std::mem::discriminant(&capture_clause).hash(&mut self.s); + std::mem::discriminant(capture_clause).hash(&mut self.s); // closures inherit TypeckResults - self.hash_expr(self.cx.tcx.hir_body(body).value); + self.hash_expr(self.cx.tcx.hir_body(*body).value); }, - ExprKind::ConstBlock(ref l_id) => { + ExprKind::ConstBlock(l_id) => { self.hash_body(l_id.body); }, ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => { self.hash_expr(e); }, - ExprKind::Field(e, ref f) => { + ExprKind::Field(e, f) => { self.hash_expr(e); self.hash_name(f.name); }, @@ -991,23 +991,23 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { ExprKind::Lit(l) => { l.node.hash(&mut self.s); }, - ExprKind::Loop(b, ref i, ..) => { + ExprKind::Loop(b, i, ..) => { self.hash_block(b); - if let Some(i) = *i { + if let Some(i) = i { self.hash_name(i.ident.name); } }, - ExprKind::If(cond, then, ref else_opt) => { + ExprKind::If(cond, then, else_opt) => { self.hash_expr(cond); self.hash_expr(then); - if let Some(e) = *else_opt { + if let Some(e) = else_opt { self.hash_expr(e); } }, - ExprKind::Match(e, arms, ref s) => { + ExprKind::Match(e, arms, s) => { self.hash_expr(e); - for arm in arms { + for arm in *arms { self.hash_pat(arm.pat); if let Some(e) = arm.guard { self.hash_expr(e); @@ -1017,38 +1017,38 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { s.hash(&mut self.s); }, - ExprKind::MethodCall(path, receiver, args, ref _fn_span) => { + ExprKind::MethodCall(path, receiver, args, _fn_span) => { self.hash_name(path.ident.name); self.hash_expr(receiver); self.hash_exprs(args); }, ExprKind::OffsetOf(container, fields) => { self.hash_ty(container); - for field in fields { + for field in *fields { self.hash_name(field.name); } }, - ExprKind::Path(ref qpath) => { + ExprKind::Path(qpath) => { self.hash_qpath(qpath); }, ExprKind::Repeat(e, len) => { self.hash_expr(e); self.hash_const_arg(len); }, - ExprKind::Ret(ref e) => { - if let Some(e) = *e { + ExprKind::Ret(e) => { + if let Some(e) = e { self.hash_expr(e); } }, - ExprKind::Struct(path, fields, ref expr) => { + ExprKind::Struct(path, fields, expr) => { self.hash_qpath(path); - for f in fields { + for f in *fields { self.hash_name(f.ident.name); self.hash_expr(f.expr); } - if let StructTailExpr::Base(e) = *expr { + if let StructTailExpr::Base(e) = expr { self.hash_expr(e); } }, @@ -1059,11 +1059,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(expr); }, ExprKind::Unary(lop, le) => { - std::mem::discriminant(&lop).hash(&mut self.s); + std::mem::discriminant(lop).hash(&mut self.s); self.hash_expr(le); }, ExprKind::UnsafeBinderCast(kind, expr, ty) => { - std::mem::discriminant(&kind).hash(&mut self.s); + std::mem::discriminant(kind).hash(&mut self.s); self.hash_expr(expr); if let Some(ty) = ty { self.hash_ty(ty); @@ -1084,7 +1084,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } pub fn hash_qpath(&mut self, p: &QPath<'_>) { - match *p { + match p { QPath::Resolved(_, path) => { self.hash_path(path); }, @@ -1092,7 +1092,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_name(path.ident.name); }, QPath::LangItem(lang_item, ..) => { - std::mem::discriminant(&lang_item).hash(&mut self.s); + std::mem::discriminant(lang_item).hash(&mut self.s); }, } // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s); @@ -1123,10 +1123,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_pat(&mut self, pat: &Pat<'_>) { std::mem::discriminant(&pat.kind).hash(&mut self.s); - match pat.kind { + match &pat.kind { PatKind::Binding(BindingMode(by_ref, mutability), _, _, pat) => { - std::mem::discriminant(&by_ref).hash(&mut self.s); - std::mem::discriminant(&mutability).hash(&mut self.s); + std::mem::discriminant(by_ref).hash(&mut self.s); + std::mem::discriminant(mutability).hash(&mut self.s); if let Some(pat) = pat { self.hash_pat(pat); } @@ -1134,7 +1134,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { PatKind::Box(pat) | PatKind::Deref(pat) => self.hash_pat(pat), PatKind::Expr(expr) => self.hash_pat_expr(expr), PatKind::Or(pats) => { - for pat in pats { + for pat in *pats { self.hash_pat(pat); } }, @@ -1145,44 +1145,44 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { if let Some(e) = e { self.hash_pat_expr(e); } - std::mem::discriminant(&i).hash(&mut self.s); + std::mem::discriminant(i).hash(&mut self.s); }, PatKind::Ref(pat, mu) => { self.hash_pat(pat); - std::mem::discriminant(&mu).hash(&mut self.s); + std::mem::discriminant(mu).hash(&mut self.s); }, PatKind::Guard(pat, guard) => { self.hash_pat(pat); self.hash_expr(guard); }, PatKind::Slice(l, m, r) => { - for pat in l { + for pat in *l { self.hash_pat(pat); } if let Some(pat) = m { self.hash_pat(pat); } - for pat in r { + for pat in *r { self.hash_pat(pat); } }, - PatKind::Struct(ref qpath, fields, e) => { + PatKind::Struct(qpath, fields, e) => { self.hash_qpath(qpath); - for f in fields { + for f in *fields { self.hash_name(f.ident.name); self.hash_pat(f.pat); } e.hash(&mut self.s); }, PatKind::Tuple(pats, e) => { - for pat in pats { + for pat in *pats { self.hash_pat(pat); } e.hash(&mut self.s); }, - PatKind::TupleStruct(ref qpath, pats, e) => { + PatKind::TupleStruct(qpath, pats, e) => { self.hash_qpath(qpath); - for pat in pats { + for pat in *pats { self.hash_pat(pat); } e.hash(&mut self.s); @@ -1260,7 +1260,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { TyKind::Slice(ty) => { self.hash_ty(ty); }, - &TyKind::Array(ty, len) => { + TyKind::Array(ty, len) => { self.hash_ty(ty); self.hash_const_arg(len); }, @@ -1333,11 +1333,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) { for arg in arg_list { - match *arg { + match arg { GenericArg::Lifetime(l) => self.hash_lifetime(l), GenericArg::Type(ty) => self.hash_ty(ty.as_unambig_ty()), GenericArg::Const(ca) => self.hash_const_arg(ca.as_unambig_ct()), - GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()), + GenericArg::Infer(inf) => self.hash_ty(&inf.to_ty()), } } } From 3a4dd1b7b279435b4289b9b9a45db6647f1d3f9c Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 29 Mar 2025 13:08:18 +0100 Subject: [PATCH 0371/2248] std: make `cmath` functions safe --- library/std/src/f128.rs | 32 +++++----- library/std/src/f16.rs | 32 +++++----- library/std/src/f32.rs | 34 +++++----- library/std/src/f64.rs | 34 +++++----- library/std/src/sys/cmath.rs | 118 +++++++++++++++++------------------ 5 files changed, 125 insertions(+), 125 deletions(-) diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index ede2196905118..217528fdf1c10 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -666,7 +666,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cbrt(self) -> f128 { - unsafe { cmath::cbrtf128(self) } + cmath::cbrtf128(self) } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -703,7 +703,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn hypot(self, other: f128) -> f128 { - unsafe { cmath::hypotf128(self, other) } + cmath::hypotf128(self, other) } /// Computes the sine of a number (in radians). @@ -789,7 +789,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tan(self) -> f128 { - unsafe { cmath::tanf128(self) } + cmath::tanf128(self) } /// Computes the arcsine of a number. Return value is in radians in @@ -824,7 +824,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn asin(self) -> f128 { - unsafe { cmath::asinf128(self) } + cmath::asinf128(self) } /// Computes the arccosine of a number. Return value is in radians in @@ -859,7 +859,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn acos(self) -> f128 { - unsafe { cmath::acosf128(self) } + cmath::acosf128(self) } /// Computes the arctangent of a number. Return value is in radians in the @@ -893,7 +893,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan(self) -> f128 { - unsafe { cmath::atanf128(self) } + cmath::atanf128(self) } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -939,7 +939,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan2(self, other: f128) -> f128 { - unsafe { cmath::atan2f128(self, other) } + cmath::atan2f128(self, other) } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -1008,7 +1008,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp_m1(self) -> f128 { - unsafe { cmath::expm1f128(self) } + cmath::expm1f128(self) } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -1055,7 +1055,7 @@ impl f128 { #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] pub fn ln_1p(self) -> f128 { - unsafe { cmath::log1pf128(self) } + cmath::log1pf128(self) } /// Hyperbolic sine function. @@ -1090,7 +1090,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sinh(self) -> f128 { - unsafe { cmath::sinhf128(self) } + cmath::sinhf128(self) } /// Hyperbolic cosine function. @@ -1125,7 +1125,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cosh(self) -> f128 { - unsafe { cmath::coshf128(self) } + cmath::coshf128(self) } /// Hyperbolic tangent function. @@ -1160,7 +1160,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tanh(self) -> f128 { - unsafe { cmath::tanhf128(self) } + cmath::tanhf128(self) } /// Inverse hyperbolic sine function. @@ -1289,7 +1289,7 @@ impl f128 { // #[unstable(feature = "float_gamma", issue = "99842")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn gamma(self) -> f128 { - unsafe { cmath::tgammaf128(self) } + cmath::tgammaf128(self) } /// Natural logarithm of the absolute value of the gamma function @@ -1325,7 +1325,7 @@ impl f128 { #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln_gamma(self) -> (f128, i32) { let mut signgamp: i32 = 0; - let x = unsafe { cmath::lgammaf128_r(self, &mut signgamp) }; + let x = cmath::lgammaf128_r(self, &mut signgamp); (x, signgamp) } @@ -1365,7 +1365,7 @@ impl f128 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f128 { - unsafe { cmath::erff128(self) } + cmath::erff128(self) } /// Complementary error function. @@ -1398,6 +1398,6 @@ impl f128 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f128 { - unsafe { cmath::erfcf128(self) } + cmath::erfcf128(self) } } diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 286993d736b9c..4dadcbb518556 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -665,7 +665,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cbrt(self) -> f16 { - (unsafe { cmath::cbrtf(self as f32) }) as f16 + cmath::cbrtf(self as f32) as f16 } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -701,7 +701,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn hypot(self, other: f16) -> f16 { - (unsafe { cmath::hypotf(self as f32, other as f32) }) as f16 + cmath::hypotf(self as f32, other as f32) as f16 } /// Computes the sine of a number (in radians). @@ -787,7 +787,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tan(self) -> f16 { - (unsafe { cmath::tanf(self as f32) }) as f16 + cmath::tanf(self as f32) as f16 } /// Computes the arcsine of a number. Return value is in radians in @@ -822,7 +822,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn asin(self) -> f16 { - (unsafe { cmath::asinf(self as f32) }) as f16 + cmath::asinf(self as f32) as f16 } /// Computes the arccosine of a number. Return value is in radians in @@ -857,7 +857,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn acos(self) -> f16 { - (unsafe { cmath::acosf(self as f32) }) as f16 + cmath::acosf(self as f32) as f16 } /// Computes the arctangent of a number. Return value is in radians in the @@ -891,7 +891,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan(self) -> f16 { - (unsafe { cmath::atanf(self as f32) }) as f16 + cmath::atanf(self as f32) as f16 } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -937,7 +937,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan2(self, other: f16) -> f16 { - (unsafe { cmath::atan2f(self as f32, other as f32) }) as f16 + cmath::atan2f(self as f32, other as f32) as f16 } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -1006,7 +1006,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp_m1(self) -> f16 { - (unsafe { cmath::expm1f(self as f32) }) as f16 + cmath::expm1f(self as f32) as f16 } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -1053,7 +1053,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln_1p(self) -> f16 { - (unsafe { cmath::log1pf(self as f32) }) as f16 + cmath::log1pf(self as f32) as f16 } /// Hyperbolic sine function. @@ -1088,7 +1088,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sinh(self) -> f16 { - (unsafe { cmath::sinhf(self as f32) }) as f16 + cmath::sinhf(self as f32) as f16 } /// Hyperbolic cosine function. @@ -1123,7 +1123,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cosh(self) -> f16 { - (unsafe { cmath::coshf(self as f32) }) as f16 + cmath::coshf(self as f32) as f16 } /// Hyperbolic tangent function. @@ -1158,7 +1158,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tanh(self) -> f16 { - (unsafe { cmath::tanhf(self as f32) }) as f16 + cmath::tanhf(self as f32) as f16 } /// Inverse hyperbolic sine function. @@ -1287,7 +1287,7 @@ impl f16 { // #[unstable(feature = "float_gamma", issue = "99842")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn gamma(self) -> f16 { - (unsafe { cmath::tgammaf(self as f32) }) as f16 + cmath::tgammaf(self as f32) as f16 } /// Natural logarithm of the absolute value of the gamma function @@ -1323,7 +1323,7 @@ impl f16 { #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln_gamma(self) -> (f16, i32) { let mut signgamp: i32 = 0; - let x = (unsafe { cmath::lgammaf_r(self as f32, &mut signgamp) }) as f16; + let x = cmath::lgammaf_r(self as f32, &mut signgamp) as f16; (x, signgamp) } @@ -1363,7 +1363,7 @@ impl f16 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f16 { - (unsafe { cmath::erff(self as f32) }) as f16 + cmath::erff(self as f32) as f16 } /// Complementary error function. @@ -1396,6 +1396,6 @@ impl f16 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f16 { - (unsafe { cmath::erfcf(self as f32) }) as f16 + cmath::erfcf(self as f32) as f16 } } diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 980e7f7793af2..baf7002f3803c 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -599,7 +599,7 @@ impl f32 { filing an issue describing your use-case too)." )] pub fn abs_sub(self, other: f32) -> f32 { - unsafe { cmath::fdimf(self, other) } + cmath::fdimf(self, other) } /// Returns the cube root of a number. @@ -626,7 +626,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cbrt(self) -> f32 { - unsafe { cmath::cbrtf(self) } + cmath::cbrtf(self) } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -657,7 +657,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn hypot(self, other: f32) -> f32 { - unsafe { cmath::hypotf(self, other) } + cmath::hypotf(self, other) } /// Computes the sine of a number (in radians). @@ -730,7 +730,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tan(self) -> f32 { - unsafe { cmath::tanf(self) } + cmath::tanf(self) } /// Computes the arcsine of a number. Return value is in radians in @@ -760,7 +760,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asin(self) -> f32 { - unsafe { cmath::asinf(self) } + cmath::asinf(self) } /// Computes the arccosine of a number. Return value is in radians in @@ -790,7 +790,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acos(self) -> f32 { - unsafe { cmath::acosf(self) } + cmath::acosf(self) } /// Computes the arctangent of a number. Return value is in radians in the @@ -819,7 +819,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan(self) -> f32 { - unsafe { cmath::atanf(self) } + cmath::atanf(self) } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -860,7 +860,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan2(self, other: f32) -> f32 { - unsafe { cmath::atan2f(self, other) } + cmath::atan2f(self, other) } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -919,7 +919,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp_m1(self) -> f32 { - unsafe { cmath::expm1f(self) } + cmath::expm1f(self) } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -957,7 +957,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln_1p(self) -> f32 { - unsafe { cmath::log1pf(self) } + cmath::log1pf(self) } /// Hyperbolic sine function. @@ -987,7 +987,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sinh(self) -> f32 { - unsafe { cmath::sinhf(self) } + cmath::sinhf(self) } /// Hyperbolic cosine function. @@ -1017,7 +1017,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cosh(self) -> f32 { - unsafe { cmath::coshf(self) } + cmath::coshf(self) } /// Hyperbolic tangent function. @@ -1047,7 +1047,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tanh(self) -> f32 { - unsafe { cmath::tanhf(self) } + cmath::tanhf(self) } /// Inverse hyperbolic sine function. @@ -1158,7 +1158,7 @@ impl f32 { #[unstable(feature = "float_gamma", issue = "99842")] #[inline] pub fn gamma(self) -> f32 { - unsafe { cmath::tgammaf(self) } + cmath::tgammaf(self) } /// Natural logarithm of the absolute value of the gamma function @@ -1188,7 +1188,7 @@ impl f32 { #[inline] pub fn ln_gamma(self) -> (f32, i32) { let mut signgamp: i32 = 0; - let x = unsafe { cmath::lgammaf_r(self, &mut signgamp) }; + let x = cmath::lgammaf_r(self, &mut signgamp); (x, signgamp) } @@ -1224,7 +1224,7 @@ impl f32 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f32 { - unsafe { cmath::erff(self) } + cmath::erff(self) } /// Complementary error function. @@ -1253,6 +1253,6 @@ impl f32 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f32 { - unsafe { cmath::erfcf(self) } + cmath::erfcf(self) } } diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 2aaab3ffc8352..84fd9bfb7b680 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -599,7 +599,7 @@ impl f64 { filing an issue describing your use-case too)." )] pub fn abs_sub(self, other: f64) -> f64 { - unsafe { cmath::fdim(self, other) } + cmath::fdim(self, other) } /// Returns the cube root of a number. @@ -626,7 +626,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cbrt(self) -> f64 { - unsafe { cmath::cbrt(self) } + cmath::cbrt(self) } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -657,7 +657,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn hypot(self, other: f64) -> f64 { - unsafe { cmath::hypot(self, other) } + cmath::hypot(self, other) } /// Computes the sine of a number (in radians). @@ -730,7 +730,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tan(self) -> f64 { - unsafe { cmath::tan(self) } + cmath::tan(self) } /// Computes the arcsine of a number. Return value is in radians in @@ -760,7 +760,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asin(self) -> f64 { - unsafe { cmath::asin(self) } + cmath::asin(self) } /// Computes the arccosine of a number. Return value is in radians in @@ -790,7 +790,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acos(self) -> f64 { - unsafe { cmath::acos(self) } + cmath::acos(self) } /// Computes the arctangent of a number. Return value is in radians in the @@ -819,7 +819,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan(self) -> f64 { - unsafe { cmath::atan(self) } + cmath::atan(self) } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -860,7 +860,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan2(self, other: f64) -> f64 { - unsafe { cmath::atan2(self, other) } + cmath::atan2(self, other) } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -919,7 +919,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp_m1(self) -> f64 { - unsafe { cmath::expm1(self) } + cmath::expm1(self) } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -957,7 +957,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln_1p(self) -> f64 { - unsafe { cmath::log1p(self) } + cmath::log1p(self) } /// Hyperbolic sine function. @@ -987,7 +987,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sinh(self) -> f64 { - unsafe { cmath::sinh(self) } + cmath::sinh(self) } /// Hyperbolic cosine function. @@ -1017,7 +1017,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cosh(self) -> f64 { - unsafe { cmath::cosh(self) } + cmath::cosh(self) } /// Hyperbolic tangent function. @@ -1047,7 +1047,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tanh(self) -> f64 { - unsafe { cmath::tanh(self) } + cmath::tanh(self) } /// Inverse hyperbolic sine function. @@ -1158,7 +1158,7 @@ impl f64 { #[unstable(feature = "float_gamma", issue = "99842")] #[inline] pub fn gamma(self) -> f64 { - unsafe { cmath::tgamma(self) } + cmath::tgamma(self) } /// Natural logarithm of the absolute value of the gamma function @@ -1188,7 +1188,7 @@ impl f64 { #[inline] pub fn ln_gamma(self) -> (f64, i32) { let mut signgamp: i32 = 0; - let x = unsafe { cmath::lgamma_r(self, &mut signgamp) }; + let x = cmath::lgamma_r(self, &mut signgamp); (x, signgamp) } @@ -1224,7 +1224,7 @@ impl f64 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f64 { - unsafe { cmath::erf(self) } + cmath::erf(self) } /// Complementary error function. @@ -1253,6 +1253,6 @@ impl f64 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f64 { - unsafe { cmath::erfc(self) } + cmath::erfc(self) } } diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs index c9969b4e376ea..668fd92853400 100644 --- a/library/std/src/sys/cmath.rs +++ b/library/std/src/sys/cmath.rs @@ -3,70 +3,70 @@ // These symbols are all defined by `libm`, // or by `compiler-builtins` on unsupported platforms. unsafe extern "C" { - pub fn acos(n: f64) -> f64; - pub fn asin(n: f64) -> f64; - pub fn atan(n: f64) -> f64; - pub fn atan2(a: f64, b: f64) -> f64; - pub fn cbrt(n: f64) -> f64; - pub fn cbrtf(n: f32) -> f32; - pub fn cosh(n: f64) -> f64; - pub fn expm1(n: f64) -> f64; - pub fn expm1f(n: f32) -> f32; - pub fn fdim(a: f64, b: f64) -> f64; - pub fn fdimf(a: f32, b: f32) -> f32; + pub safe fn acos(n: f64) -> f64; + pub safe fn asin(n: f64) -> f64; + pub safe fn atan(n: f64) -> f64; + pub safe fn atan2(a: f64, b: f64) -> f64; + pub safe fn cbrt(n: f64) -> f64; + pub safe fn cbrtf(n: f32) -> f32; + pub safe fn cosh(n: f64) -> f64; + pub safe fn expm1(n: f64) -> f64; + pub safe fn expm1f(n: f32) -> f32; + pub safe fn fdim(a: f64, b: f64) -> f64; + pub safe fn fdimf(a: f32, b: f32) -> f32; #[cfg_attr(target_env = "msvc", link_name = "_hypot")] - pub fn hypot(x: f64, y: f64) -> f64; + pub safe fn hypot(x: f64, y: f64) -> f64; #[cfg_attr(target_env = "msvc", link_name = "_hypotf")] - pub fn hypotf(x: f32, y: f32) -> f32; - pub fn log1p(n: f64) -> f64; - pub fn log1pf(n: f32) -> f32; - pub fn sinh(n: f64) -> f64; - pub fn tan(n: f64) -> f64; - pub fn tanh(n: f64) -> f64; - pub fn tgamma(n: f64) -> f64; - pub fn tgammaf(n: f32) -> f32; - pub fn lgamma_r(n: f64, s: &mut i32) -> f64; + pub safe fn hypotf(x: f32, y: f32) -> f32; + pub safe fn log1p(n: f64) -> f64; + pub safe fn log1pf(n: f32) -> f32; + pub safe fn sinh(n: f64) -> f64; + pub safe fn tan(n: f64) -> f64; + pub safe fn tanh(n: f64) -> f64; + pub safe fn tgamma(n: f64) -> f64; + pub safe fn tgammaf(n: f32) -> f32; + pub safe fn lgamma_r(n: f64, s: &mut i32) -> f64; #[cfg(not(target_os = "aix"))] - pub fn lgammaf_r(n: f32, s: &mut i32) -> f32; - pub fn erf(n: f64) -> f64; - pub fn erff(n: f32) -> f32; - pub fn erfc(n: f64) -> f64; - pub fn erfcf(n: f32) -> f32; + pub safe fn lgammaf_r(n: f32, s: &mut i32) -> f32; + pub safe fn erf(n: f64) -> f64; + pub safe fn erff(n: f32) -> f32; + pub safe fn erfc(n: f64) -> f64; + pub safe fn erfcf(n: f32) -> f32; - pub fn acosf128(n: f128) -> f128; - pub fn asinf128(n: f128) -> f128; - pub fn atanf128(n: f128) -> f128; - pub fn atan2f128(a: f128, b: f128) -> f128; - pub fn cbrtf128(n: f128) -> f128; - pub fn coshf128(n: f128) -> f128; - pub fn expm1f128(n: f128) -> f128; - pub fn hypotf128(x: f128, y: f128) -> f128; - pub fn log1pf128(n: f128) -> f128; - pub fn sinhf128(n: f128) -> f128; - pub fn tanf128(n: f128) -> f128; - pub fn tanhf128(n: f128) -> f128; - pub fn tgammaf128(n: f128) -> f128; - pub fn lgammaf128_r(n: f128, s: &mut i32) -> f128; - pub fn erff128(n: f128) -> f128; - pub fn erfcf128(n: f128) -> f128; + pub safe fn acosf128(n: f128) -> f128; + pub safe fn asinf128(n: f128) -> f128; + pub safe fn atanf128(n: f128) -> f128; + pub safe fn atan2f128(a: f128, b: f128) -> f128; + pub safe fn cbrtf128(n: f128) -> f128; + pub safe fn coshf128(n: f128) -> f128; + pub safe fn expm1f128(n: f128) -> f128; + pub safe fn hypotf128(x: f128, y: f128) -> f128; + pub safe fn log1pf128(n: f128) -> f128; + pub safe fn sinhf128(n: f128) -> f128; + pub safe fn tanf128(n: f128) -> f128; + pub safe fn tanhf128(n: f128) -> f128; + pub safe fn tgammaf128(n: f128) -> f128; + pub safe fn lgammaf128_r(n: f128, s: &mut i32) -> f128; + pub safe fn erff128(n: f128) -> f128; + pub safe fn erfcf128(n: f128) -> f128; cfg_if::cfg_if! { if #[cfg(not(all(target_os = "windows", target_env = "msvc", target_arch = "x86")))] { - pub fn acosf(n: f32) -> f32; - pub fn asinf(n: f32) -> f32; - pub fn atan2f(a: f32, b: f32) -> f32; - pub fn atanf(n: f32) -> f32; - pub fn coshf(n: f32) -> f32; - pub fn sinhf(n: f32) -> f32; - pub fn tanf(n: f32) -> f32; - pub fn tanhf(n: f32) -> f32; + pub safe fn acosf(n: f32) -> f32; + pub safe fn asinf(n: f32) -> f32; + pub safe fn atan2f(a: f32, b: f32) -> f32; + pub safe fn atanf(n: f32) -> f32; + pub safe fn coshf(n: f32) -> f32; + pub safe fn sinhf(n: f32) -> f32; + pub safe fn tanf(n: f32) -> f32; + pub safe fn tanhf(n: f32) -> f32; }} } // On AIX, we don't have lgammaf_r only the f64 version, so we can // use the f64 version lgamma_r #[cfg(target_os = "aix")] -pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 { +pub fn lgammaf_r(n: f32, s: &mut i32) -> f32 { lgamma_r(n.into(), s) as f32 } @@ -76,42 +76,42 @@ pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 { cfg_if::cfg_if! { if #[cfg(all(target_os = "windows", target_env = "msvc", target_arch = "x86"))] { #[inline] - pub unsafe fn acosf(n: f32) -> f32 { + pub fn acosf(n: f32) -> f32 { f64::acos(n as f64) as f32 } #[inline] - pub unsafe fn asinf(n: f32) -> f32 { + pub fn asinf(n: f32) -> f32 { f64::asin(n as f64) as f32 } #[inline] - pub unsafe fn atan2f(n: f32, b: f32) -> f32 { + pub fn atan2f(n: f32, b: f32) -> f32 { f64::atan2(n as f64, b as f64) as f32 } #[inline] - pub unsafe fn atanf(n: f32) -> f32 { + pub fn atanf(n: f32) -> f32 { f64::atan(n as f64) as f32 } #[inline] - pub unsafe fn coshf(n: f32) -> f32 { + pub fn coshf(n: f32) -> f32 { f64::cosh(n as f64) as f32 } #[inline] - pub unsafe fn sinhf(n: f32) -> f32 { + pub fn sinhf(n: f32) -> f32 { f64::sinh(n as f64) as f32 } #[inline] - pub unsafe fn tanf(n: f32) -> f32 { + pub fn tanf(n: f32) -> f32 { f64::tan(n as f64) as f32 } #[inline] - pub unsafe fn tanhf(n: f32) -> f32 { + pub fn tanhf(n: f32) -> f32 { f64::tanh(n as f64) as f32 } }} From 2df6bba5b06dfb073b93199517803a6bd0aa15a0 Mon Sep 17 00:00:00 2001 From: yanglsh Date: Thu, 13 Mar 2025 16:49:34 +0800 Subject: [PATCH 0372/2248] fix: `unnested_or_patterns` suggests wrongly in `let` --- clippy_lints/src/unnested_or_patterns.rs | 13 ++++++-- tests/ui/unnested_or_patterns.fixed | 13 ++++++++ tests/ui/unnested_or_patterns.rs | 13 ++++++++ tests/ui/unnested_or_patterns.stderr | 38 +++++++++++++++++++++++- 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index f43715d6752e3..913a67b18a66e 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -120,18 +120,25 @@ fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) { /// Remove all `(p)` patterns in `pat`. fn remove_all_parens(pat: &mut P) { - struct Visitor; + #[derive(Default)] + struct Visitor { + /// If is not in the outer most pattern. This is needed to avoid removing the outermost + /// parens because top-level or-patterns are not allowed in let statements. + is_inner: bool, + } + impl MutVisitor for Visitor { fn visit_pat(&mut self, pat: &mut P) { + let is_inner = mem::replace(&mut self.is_inner, true); walk_pat(self, pat); let inner = match &mut pat.kind { - Paren(i) => mem::replace(&mut i.kind, Wild), + Paren(i) if is_inner => mem::replace(&mut i.kind, Wild), _ => return, }; pat.kind = inner; } } - Visitor.visit_pat(pat); + Visitor::default().visit_pat(pat); } /// Insert parens where necessary according to Rust's precedence rules for patterns. diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index 791b2fa131f23..2081772d06b36 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -64,3 +64,16 @@ fn msrv_1_53() { if let [1 | 53] = [0] {} //~^ unnested_or_patterns } + +mod issue9952 { + fn or_in_local() { + let (0 | 1 | _) = 0; + //~^ unnested_or_patterns + + if let (0 | 1 | _) = 0 {} + //~^ unnested_or_patterns + } + + fn or_in_param((x | x | x): i32) {} + //~^ unnested_or_patterns +} diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index e7e7c7cd2e494..6bf8fce36616c 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -64,3 +64,16 @@ fn msrv_1_53() { if let [1] | [53] = [0] {} //~^ unnested_or_patterns } + +mod issue9952 { + fn or_in_local() { + let (0 | (1 | _)) = 0; + //~^ unnested_or_patterns + + if let (0 | (1 | _)) = 0 {} + //~^ unnested_or_patterns + } + + fn or_in_param((x | (x | x)): i32) {} + //~^ unnested_or_patterns +} diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr index ec5eb983c5a01..c805dc992b1c2 100644 --- a/tests/ui/unnested_or_patterns.stderr +++ b/tests/ui/unnested_or_patterns.stderr @@ -204,5 +204,41 @@ LL - if let [1] | [53] = [0] {} LL + if let [1 | 53] = [0] {} | -error: aborting due to 17 previous errors +error: unnested or-patterns + --> tests/ui/unnested_or_patterns.rs:70:13 + | +LL | let (0 | (1 | _)) = 0; + | ^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL - let (0 | (1 | _)) = 0; +LL + let (0 | 1 | _) = 0; + | + +error: unnested or-patterns + --> tests/ui/unnested_or_patterns.rs:73:16 + | +LL | if let (0 | (1 | _)) = 0 {} + | ^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL - if let (0 | (1 | _)) = 0 {} +LL + if let (0 | 1 | _) = 0 {} + | + +error: unnested or-patterns + --> tests/ui/unnested_or_patterns.rs:77:20 + | +LL | fn or_in_param((x | (x | x)): i32) {} + | ^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL - fn or_in_param((x | (x | x)): i32) {} +LL + fn or_in_param((x | x | x): i32) {} + | + +error: aborting due to 20 previous errors From 814d7c37d4374f03b50fe8e656997fb2ccca9966 Mon Sep 17 00:00:00 2001 From: Inflation <2375962+inflation@users.noreply.github.com> Date: Sat, 29 Mar 2025 21:28:50 +0800 Subject: [PATCH 0373/2248] Fix debug sourceFileMap when using cppvsdbg - Fix #18782 --- src/tools/rust-analyzer/editors/code/src/debug.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts index 04211d77e779f..a04a6db7adb69 100644 --- a/src/tools/rust-analyzer/editors/code/src/debug.ts +++ b/src/tools/rust-analyzer/editors/code/src/debug.ts @@ -225,7 +225,7 @@ async function discoverSourceFileMap( const commitHash = rx.exec(data)?.[1]; if (commitHash) { const rustlib = path.normalize(sysroot + "/lib/rustlib/src/rust"); - return { source: rustlib, destination: rustlib }; + return { source: "/rustc/" + commitHash, destination: rustlib }; } } From ffaecd008d8c2361d1043a20e06c7090f64193c3 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 29 Mar 2025 17:36:04 +0100 Subject: [PATCH 0374/2248] manually fulfill lint expectations for all unsafe blocks with metavars --- clippy_lints/src/macro_metavars_in_unsafe.rs | 11 ++++++++++- .../macro_metavars_in_unsafe/default/test.rs | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/macro_metavars_in_unsafe.rs b/clippy_lints/src/macro_metavars_in_unsafe.rs index 006addb987f5b..0f9d373f0a3d7 100644 --- a/clippy_lints/src/macro_metavars_in_unsafe.rs +++ b/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -5,7 +5,7 @@ use itertools::Itertools; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt}; use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, Level, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::{Span, SyntaxContext, sym}; use std::collections::BTreeMap; @@ -249,6 +249,15 @@ impl<'tcx> LateLintPass<'tcx> for ExprMetavarsInUnsafe { }) .flatten() .copied() + .inspect(|&unsafe_block| { + if let Level::Expect(id) = cx.tcx.lint_level_at_node(MACRO_METAVARS_IN_UNSAFE, unsafe_block).0 { + // Since we're going to deduplicate expanded unsafe blocks by its enclosing macro definition soon, + // which would lead to unfulfilled `#[expect()]`s in all other unsafe blocks that are filtered out + // except for the one we emit the warning at, we must manually fulfill the lint + // for all unsafe blocks here. + cx.fulfill_expectation(id); + } + }) .map(|id| { // Remove the syntax context to hide "in this macro invocation" in the diagnostic. // The invocation doesn't matter. Also we want to dedupe by the unsafe block and not by anything diff --git a/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs b/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs index 2465fe45645f1..d3d5b0c103e7f 100644 --- a/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs +++ b/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs @@ -251,6 +251,16 @@ pub mod issue13219 { } } +#[macro_export] +macro_rules! issue14488 { + ($e:expr) => { + #[expect(clippy::macro_metavars_in_unsafe)] + unsafe { + $e + } + }; +} + fn main() { allow_works!(1); simple!(1); @@ -271,4 +281,10 @@ fn main() { multiple_unsafe_blocks!(1, 1, 1); unsafe_from_root_ctxt!(unsafe { 1 }); nested_macros!(1, 1); + + // These two invocations lead to two expanded unsafe blocks, each with an `#[expect]` on it. + // Only of them gets a warning, which used to result in an unfulfilled expectation for the other + // expanded unsafe block. + issue14488!(1); + issue14488!(2); } From 865a5a7e164950cf728439d12efb762e29c46c2c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 29 Mar 2025 20:02:01 +0200 Subject: [PATCH 0375/2248] 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 0376/2248] 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 0377/2248] 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 0378/2248] 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 41fdd280ff1089d1618487d59ed49f83160d2513 Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 22 Mar 2025 16:09:37 -0400 Subject: [PATCH 0379/2248] 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 8f3a0db64fa599238969502ea4991a4be31aec93 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 29 Mar 2025 17:45:21 +0100 Subject: [PATCH 0380/2248] don't hardcode repository owner in changelog CI --- .github/workflows/clippy_changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clippy_changelog.yml b/.github/workflows/clippy_changelog.yml index a2657bfea490d..1e97154bf8a34 100644 --- a/.github/workflows/clippy_changelog.yml +++ b/.github/workflows/clippy_changelog.yml @@ -24,7 +24,7 @@ jobs: - name: Check Changelog if: ${{ github.event_name == 'pull_request' }} run: | - body=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$PR_NUMBER" | \ + body=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -s "https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER" | \ python -c "import sys, json; print(json.load(sys.stdin)['body'])") output=$(awk '/^changelog:\s*\S/ && !/changelog: \[.*\]: your change/' <<< "$body" | sed "s/changelog:\s*//g") if [ -z "$output" ]; then From 4f2baaa9c6b75d4267eea9e1096339d56d380615 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Mar 2025 18:57:04 +0000 Subject: [PATCH 0381/2248] 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 18c787f48f08352ad5167b99920c395e3d703f62 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 30 Mar 2025 04:21:20 +0000 Subject: [PATCH 0382/2248] Fix up partial res of segment in primitive resolution hack --- compiler/rustc_resolve/src/late.rs | 5 +++++ tests/ui/resolve/auxiliary/empty.rs | 1 + tests/ui/resolve/prim-crate-partial-res.rs | 8 ++++++++ tests/ui/resolve/prim-crate-partial-res.stderr | 17 +++++++++++++++++ 4 files changed, 31 insertions(+) create mode 100644 tests/ui/resolve/auxiliary/empty.rs create mode 100644 tests/ui/resolve/prim-crate-partial-res.rs create mode 100644 tests/ui/resolve/prim-crate-partial-res.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0d23ae501f04b..606d25c558a18 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4598,6 +4598,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } }; + // Fix up partial res of segment from `resolve_path` call. + if let Some(id) = path[0].id { + self.r.partial_res_map.insert(id, PartialRes::new(Res::PrimTy(prim))); + } + PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1) } PathResult::Module(ModuleOrUniformRoot::Module(module)) => { diff --git a/tests/ui/resolve/auxiliary/empty.rs b/tests/ui/resolve/auxiliary/empty.rs new file mode 100644 index 0000000000000..bd9ec079d80d4 --- /dev/null +++ b/tests/ui/resolve/auxiliary/empty.rs @@ -0,0 +1 @@ +// Intentionally empty. diff --git a/tests/ui/resolve/prim-crate-partial-res.rs b/tests/ui/resolve/prim-crate-partial-res.rs new file mode 100644 index 0000000000000..955f4fa2aee71 --- /dev/null +++ b/tests/ui/resolve/prim-crate-partial-res.rs @@ -0,0 +1,8 @@ +//@ aux-build: empty.rs + +extern crate empty as usize; + +fn foo() -> usize<()> { 0 } +//~^ ERROR type arguments are not allowed on builtin type `usize` + +fn main() {} diff --git a/tests/ui/resolve/prim-crate-partial-res.stderr b/tests/ui/resolve/prim-crate-partial-res.stderr new file mode 100644 index 0000000000000..d10d37c9f1b08 --- /dev/null +++ b/tests/ui/resolve/prim-crate-partial-res.stderr @@ -0,0 +1,17 @@ +error[E0109]: type arguments are not allowed on builtin type `usize` + --> $DIR/prim-crate-partial-res.rs:5:19 + | +LL | fn foo() -> usize<()> { 0 } + | ----- ^^ type argument not allowed + | | + | not allowed on builtin type `usize` + | +help: primitive type `usize` doesn't have generic parameters + | +LL - fn foo() -> usize<()> { 0 } +LL + fn foo() -> usize { 0 } + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0109`. From fb32aaf9ac75b503e0f344dc32ad2bf0f50f6952 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 21 Sep 2024 18:44:33 +0000 Subject: [PATCH 0383/2248] new lint: `chars_enumerate_for_byte_indices` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + .../loops/chars_enumerate_for_byte_indices.rs | 138 ++++++++++++++++++ clippy_lints/src/loops/mod.rs | 45 ++++++ .../ui/chars_enumerate_for_byte_indices.fixed | 59 ++++++++ tests/ui/chars_enumerate_for_byte_indices.rs | 59 ++++++++ .../chars_enumerate_for_byte_indices.stderr | 123 ++++++++++++++++ 7 files changed, 426 insertions(+) create mode 100644 clippy_lints/src/loops/chars_enumerate_for_byte_indices.rs create mode 100644 tests/ui/chars_enumerate_for_byte_indices.fixed create mode 100644 tests/ui/chars_enumerate_for_byte_indices.rs create mode 100644 tests/ui/chars_enumerate_for_byte_indices.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e6f00e857f70..68387498c0d3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5517,6 +5517,7 @@ Released 2018-09-13 [`cast_slice_from_raw_parts`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_slice_from_raw_parts [`cfg_not_test`]: https://rust-lang.github.io/rust-clippy/master/index.html#cfg_not_test [`char_lit_as_u8`]: https://rust-lang.github.io/rust-clippy/master/index.html#char_lit_as_u8 +[`chars_enumerate_for_byte_indices`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_enumerate_for_byte_indices [`chars_last_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_last_cmp [`chars_next_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_next_cmp [`checked_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index c2274f0a619cf..cd3f40a003dbd 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -287,6 +287,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::literal_representation::UNREADABLE_LITERAL_INFO, crate::literal_representation::UNUSUAL_BYTE_GROUPINGS_INFO, crate::literal_string_with_formatting_args::LITERAL_STRING_WITH_FORMATTING_ARGS_INFO, + crate::loops::CHARS_ENUMERATE_FOR_BYTE_INDICES_INFO, crate::loops::EMPTY_LOOP_INFO, crate::loops::EXPLICIT_COUNTER_LOOP_INFO, crate::loops::EXPLICIT_INTO_ITER_LOOP_INFO, diff --git a/clippy_lints/src/loops/chars_enumerate_for_byte_indices.rs b/clippy_lints/src/loops/chars_enumerate_for_byte_indices.rs new file mode 100644 index 0000000000000..40274311d7800 --- /dev/null +++ b/clippy_lints/src/loops/chars_enumerate_for_byte_indices.rs @@ -0,0 +1,138 @@ +use std::ops::ControlFlow; + +use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::ty::is_type_lang_item; +use clippy_utils::visitors::for_each_expr; +use clippy_utils::{eq_expr_value, higher, path_to_local_id}; +use rustc_errors::{Applicability, MultiSpan}; +use rustc_hir::{Expr, ExprKind, LangItem, Node, Pat, PatKind}; +use rustc_lint::LateContext; +use rustc_middle::ty::Ty; +use rustc_span::{Span, sym}; + +use super::CHARS_ENUMERATE_FOR_BYTE_INDICES; + +// The list of `str` methods we want to lint that have a `usize` argument representing a byte index. +// Note: `String` also has methods that work with byte indices, +// but they all take `&mut self` and aren't worth considering since the user couldn't have called +// them while the chars iterator is live anyway. +const BYTE_INDEX_METHODS: &[&str] = &[ + "is_char_boundary", + "floor_char_boundary", + "ceil_char_boundary", + "get", + "index", + "index_mut", + "get_mut", + "get_unchecked", + "get_unchecked_mut", + "slice_unchecked", + "slice_mut_unchecked", + "split_at", + "split_at_mut", + "split_at_checked", + "split_at_mut_checked", +]; + +const CONTINUE: ControlFlow = ControlFlow::Continue(()); + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>, iterable: &Expr<'_>, body: &'tcx Expr<'tcx>) { + if let ExprKind::MethodCall(_, enumerate_recv, _, enumerate_span) = iterable.kind + && let Some(method_id) = cx.typeck_results().type_dependent_def_id(iterable.hir_id) + && cx.tcx.is_diagnostic_item(sym::enumerate_method, method_id) + && let ExprKind::MethodCall(_, chars_recv, _, chars_span) = enumerate_recv.kind + && let Some(method_id) = cx.typeck_results().type_dependent_def_id(enumerate_recv.hir_id) + && cx.tcx.is_diagnostic_item(sym::str_chars, method_id) + { + if let PatKind::Tuple([pat, _], _) = pat.kind + && let PatKind::Binding(_, binding_id, ..) = pat.kind + { + // Destructured iterator element `(idx, _)`, look for uses of the binding + for_each_expr(cx, body, |expr| { + if path_to_local_id(expr, binding_id) { + check_index_usage(cx, expr, pat, enumerate_span, chars_span, chars_recv); + } + CONTINUE + }); + } else if let PatKind::Binding(_, binding_id, ..) = pat.kind { + // Bound as a tuple, look for `tup.0` + for_each_expr(cx, body, |expr| { + if let ExprKind::Field(e, field) = expr.kind + && path_to_local_id(e, binding_id) + && field.name == sym::integer(0) + { + check_index_usage(cx, expr, pat, enumerate_span, chars_span, chars_recv); + } + CONTINUE + }); + } + } +} + +fn check_index_usage<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + pat: &Pat<'_>, + enumerate_span: Span, + chars_span: Span, + chars_recv: &Expr<'_>, +) { + let Some(parent_expr) = index_consumed_at(cx, expr) else { + return; + }; + + let is_string_like = |ty: Ty<'_>| ty.is_str() || is_type_lang_item(cx, ty, LangItem::String); + let message = match parent_expr.kind { + ExprKind::MethodCall(segment, recv, ..) + if cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_str() + && BYTE_INDEX_METHODS.contains(&segment.ident.name.as_str()) + && eq_expr_value(cx, chars_recv, recv) => + { + "passing a character position to a method that expects a byte index" + }, + ExprKind::Index(target, ..) + if is_string_like(cx.typeck_results().expr_ty_adjusted(target).peel_refs()) + && eq_expr_value(cx, chars_recv, target) => + { + "indexing into a string with a character position where a byte index is expected" + }, + _ => return, + }; + + span_lint_hir_and_then( + cx, + CHARS_ENUMERATE_FOR_BYTE_INDICES, + expr.hir_id, + expr.span, + message, + |diag| { + diag.note("a character can take up more than one byte, so they are not interchangeable") + .span_note( + MultiSpan::from_spans(vec![pat.span, enumerate_span]), + "position comes from the enumerate iterator", + ) + .span_suggestion_verbose( + chars_span.to(enumerate_span), + "consider using `.char_indices()` instead", + "char_indices()", + Applicability::MaybeIncorrect, + ); + }, + ); +} + +/// Returns the expression which ultimately consumes the index. +/// This is usually the parent expression, i.e. `.split_at(idx)` for `idx`, +/// but for `.get(..idx)` we want to consider the method call the consuming expression, +/// which requires skipping past the range expression. +fn index_consumed_at<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { + for (_, node) in cx.tcx.hir().parent_iter(expr.hir_id) { + match node { + Node::Expr(expr) if higher::Range::hir(expr).is_some() => {}, + Node::ExprField(_) => {}, + Node::Expr(expr) => return Some(expr), + _ => break, + } + } + None +} diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 4b0bf5a4b3c94..10ba739909f79 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -1,3 +1,4 @@ +mod chars_enumerate_for_byte_indices; mod empty_loop; mod explicit_counter_loop; mod explicit_into_iter_loop; @@ -740,6 +741,48 @@ declare_clippy_lint! { "manually filling a slice with a value" } +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of a character position yielded by `.chars().enumerate()` in a context where a **byte index** is expected, + /// such as an argument to a specific `str` method or indexing into a `str` or `String`. + /// + /// ### Why is this bad? + /// A character (more specifically, a Unicode scalar value) that is yielded by `str::chars` can take up multiple bytes, + /// so a character position does not necessarily have the same byte index at which the character is stored. + /// Thus, using the character position where a byte index is expected can unexpectedly return wrong values + /// or panic when the string consists of multibyte characters. + /// + /// For example, the character `a` in `äa` is stored at byte index 2 but has the character position 1. + /// Using the character position 1 to index into the string will lead to a panic as it is in the middle of the first character. + /// + /// Instead of `.chars().enumerate()`, the correct iterator to use is `.char_indices()`, which yields byte indices. + /// + /// This pattern is technically fine if the strings are known to only use the ASCII subset, + /// but there is also no downside to just using `.char_indices()` directly. + /// + /// You may also want to read the [chapter on strings in the Rust Book](https://doc.rust-lang.org/book/ch08-02-strings.html) + /// which goes into this in more detail. + /// + /// ### Example + /// ```no_run + /// # let s = "..."; + /// for (idx, c) in s.chars().enumerate() { + /// let _ = s[idx..]; // ⚠️ Panics for strings consisting of multibyte characters + /// } + /// ``` + /// Use instead: + /// ```no_run + /// # let s = "..."; + /// for (idx, c) in s.char_indices() { + /// let _ = s[idx..]; + /// } + /// ``` + #[clippy::version = "1.83.0"] + pub CHARS_ENUMERATE_FOR_BYTE_INDICES, + correctness, + "using the character position yielded by `.chars().enumerate()` in a context where a byte index is expected" +} + pub struct Loops { msrv: Msrv, enforce_iter_loop_reborrow: bool, @@ -777,6 +820,7 @@ impl_lint_pass!(Loops => [ UNUSED_ENUMERATE_INDEX, INFINITE_LOOP, MANUAL_SLICE_FILL, + CHARS_ENUMERATE_FOR_BYTE_INDICES, ]); impl<'tcx> LateLintPass<'tcx> for Loops { @@ -860,6 +904,7 @@ impl Loops { manual_flatten::check(cx, pat, arg, body, span, self.msrv); manual_find::check(cx, pat, arg, body, span, expr); unused_enumerate_index::check(cx, pat, arg, body); + chars_enumerate_for_byte_indices::check(cx, pat, arg, body); } fn check_for_loop_arg(&self, cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) { diff --git a/tests/ui/chars_enumerate_for_byte_indices.fixed b/tests/ui/chars_enumerate_for_byte_indices.fixed new file mode 100644 index 0000000000000..7a4f87fa2d484 --- /dev/null +++ b/tests/ui/chars_enumerate_for_byte_indices.fixed @@ -0,0 +1,59 @@ +#![feature(round_char_boundary)] +#![warn(clippy::chars_enumerate_for_byte_indices)] + +trait StrExt { + fn use_index(&self, _: usize); +} +impl StrExt for str { + fn use_index(&self, _: usize) {} +} + +fn bad(prim: &str, string: String) { + for (idx, _) in prim.char_indices() { + let _ = prim[..idx]; + //~^ chars_enumerate_for_byte_indices + prim.split_at(idx); + //~^ chars_enumerate_for_byte_indices + + // This won't panic, but it can still return a wrong substring + let _ = prim[..prim.floor_char_boundary(idx)]; + //~^ chars_enumerate_for_byte_indices + + // can't use #[expect] here because the .fixed file will still have the attribute and create an + // unfulfilled expectation, but make sure lint level attributes work on the use expression: + #[allow(clippy::chars_enumerate_for_byte_indices)] + let _ = prim[..idx]; + } + + for c in prim.char_indices() { + let _ = prim[..c.0]; + //~^ chars_enumerate_for_byte_indices + prim.split_at(c.0); + //~^ chars_enumerate_for_byte_indices + } + + for (idx, _) in string.char_indices() { + let _ = string[..idx]; + //~^ chars_enumerate_for_byte_indices + string.split_at(idx); + //~^ chars_enumerate_for_byte_indices + } +} + +fn good(prim: &str, prim2: &str) { + for (idx, _) in prim.chars().enumerate() { + // Indexing into a different string + let _ = prim2[..idx]; + + // Unknown use + std::hint::black_box(idx); + + // Method call to user defined extension trait + prim.use_index(idx); + + // str method taking a usize that doesn't represent a byte index + prim.splitn(idx, prim2); + } +} + +fn main() {} diff --git a/tests/ui/chars_enumerate_for_byte_indices.rs b/tests/ui/chars_enumerate_for_byte_indices.rs new file mode 100644 index 0000000000000..1e8f555846a44 --- /dev/null +++ b/tests/ui/chars_enumerate_for_byte_indices.rs @@ -0,0 +1,59 @@ +#![feature(round_char_boundary)] +#![warn(clippy::chars_enumerate_for_byte_indices)] + +trait StrExt { + fn use_index(&self, _: usize); +} +impl StrExt for str { + fn use_index(&self, _: usize) {} +} + +fn bad(prim: &str, string: String) { + for (idx, _) in prim.chars().enumerate() { + let _ = prim[..idx]; + //~^ chars_enumerate_for_byte_indices + prim.split_at(idx); + //~^ chars_enumerate_for_byte_indices + + // This won't panic, but it can still return a wrong substring + let _ = prim[..prim.floor_char_boundary(idx)]; + //~^ chars_enumerate_for_byte_indices + + // can't use #[expect] here because the .fixed file will still have the attribute and create an + // unfulfilled expectation, but make sure lint level attributes work on the use expression: + #[allow(clippy::chars_enumerate_for_byte_indices)] + let _ = prim[..idx]; + } + + for c in prim.chars().enumerate() { + let _ = prim[..c.0]; + //~^ chars_enumerate_for_byte_indices + prim.split_at(c.0); + //~^ chars_enumerate_for_byte_indices + } + + for (idx, _) in string.chars().enumerate() { + let _ = string[..idx]; + //~^ chars_enumerate_for_byte_indices + string.split_at(idx); + //~^ chars_enumerate_for_byte_indices + } +} + +fn good(prim: &str, prim2: &str) { + for (idx, _) in prim.chars().enumerate() { + // Indexing into a different string + let _ = prim2[..idx]; + + // Unknown use + std::hint::black_box(idx); + + // Method call to user defined extension trait + prim.use_index(idx); + + // str method taking a usize that doesn't represent a byte index + prim.splitn(idx, prim2); + } +} + +fn main() {} diff --git a/tests/ui/chars_enumerate_for_byte_indices.stderr b/tests/ui/chars_enumerate_for_byte_indices.stderr new file mode 100644 index 0000000000000..0159eb0387b9e --- /dev/null +++ b/tests/ui/chars_enumerate_for_byte_indices.stderr @@ -0,0 +1,123 @@ +error: indexing into a string with a character position where a byte index is expected + --> tests/ui/chars_enumerate_for_byte_indices.rs:13:24 + | +LL | let _ = prim[..idx]; + | ^^^ + | + = note: a character can take up more than one byte, so they are not interchangeable +note: position comes from the enumerate iterator + --> tests/ui/chars_enumerate_for_byte_indices.rs:12:10 + | +LL | for (idx, _) in prim.chars().enumerate() { + | ^^^ ^^^^^^^^^^^ + = note: `-D clippy::chars-enumerate-for-byte-indices` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::chars_enumerate_for_byte_indices)]` +help: consider using `.char_indices()` instead + | +LL | for (idx, _) in prim.char_indices() { + | ~~~~~~~~~~~~~~ + +error: passing a character position to a method that expects a byte index + --> tests/ui/chars_enumerate_for_byte_indices.rs:15:23 + | +LL | prim.split_at(idx); + | ^^^ + | + = note: a character can take up more than one byte, so they are not interchangeable +note: position comes from the enumerate iterator + --> tests/ui/chars_enumerate_for_byte_indices.rs:12:10 + | +LL | for (idx, _) in prim.chars().enumerate() { + | ^^^ ^^^^^^^^^^^ +help: consider using `.char_indices()` instead + | +LL | for (idx, _) in prim.char_indices() { + | ~~~~~~~~~~~~~~ + +error: passing a character position to a method that expects a byte index + --> tests/ui/chars_enumerate_for_byte_indices.rs:19:49 + | +LL | let _ = prim[..prim.floor_char_boundary(idx)]; + | ^^^ + | + = note: a character can take up more than one byte, so they are not interchangeable +note: position comes from the enumerate iterator + --> tests/ui/chars_enumerate_for_byte_indices.rs:12:10 + | +LL | for (idx, _) in prim.chars().enumerate() { + | ^^^ ^^^^^^^^^^^ +help: consider using `.char_indices()` instead + | +LL | for (idx, _) in prim.char_indices() { + | ~~~~~~~~~~~~~~ + +error: indexing into a string with a character position where a byte index is expected + --> tests/ui/chars_enumerate_for_byte_indices.rs:29:24 + | +LL | let _ = prim[..c.0]; + | ^^^ + | + = note: a character can take up more than one byte, so they are not interchangeable +note: position comes from the enumerate iterator + --> tests/ui/chars_enumerate_for_byte_indices.rs:28:9 + | +LL | for c in prim.chars().enumerate() { + | ^ ^^^^^^^^^^^ +help: consider using `.char_indices()` instead + | +LL | for c in prim.char_indices() { + | ~~~~~~~~~~~~~~ + +error: passing a character position to a method that expects a byte index + --> tests/ui/chars_enumerate_for_byte_indices.rs:31:23 + | +LL | prim.split_at(c.0); + | ^^^ + | + = note: a character can take up more than one byte, so they are not interchangeable +note: position comes from the enumerate iterator + --> tests/ui/chars_enumerate_for_byte_indices.rs:28:9 + | +LL | for c in prim.chars().enumerate() { + | ^ ^^^^^^^^^^^ +help: consider using `.char_indices()` instead + | +LL | for c in prim.char_indices() { + | ~~~~~~~~~~~~~~ + +error: indexing into a string with a character position where a byte index is expected + --> tests/ui/chars_enumerate_for_byte_indices.rs:36:26 + | +LL | let _ = string[..idx]; + | ^^^ + | + = note: a character can take up more than one byte, so they are not interchangeable +note: position comes from the enumerate iterator + --> tests/ui/chars_enumerate_for_byte_indices.rs:35:10 + | +LL | for (idx, _) in string.chars().enumerate() { + | ^^^ ^^^^^^^^^^^ +help: consider using `.char_indices()` instead + | +LL | for (idx, _) in string.char_indices() { + | ~~~~~~~~~~~~~~ + +error: passing a character position to a method that expects a byte index + --> tests/ui/chars_enumerate_for_byte_indices.rs:38:25 + | +LL | string.split_at(idx); + | ^^^ + | + = note: a character can take up more than one byte, so they are not interchangeable +note: position comes from the enumerate iterator + --> tests/ui/chars_enumerate_for_byte_indices.rs:35:10 + | +LL | for (idx, _) in string.chars().enumerate() { + | ^^^ ^^^^^^^^^^^ +help: consider using `.char_indices()` instead + | +LL | for (idx, _) in string.char_indices() { + | ~~~~~~~~~~~~~~ + +error: aborting due to 7 previous errors + From 32cf88450bd1d97a1ec1cfcb67c04173ea92db3c Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 3 Dec 2024 04:24:56 +0100 Subject: [PATCH 0384/2248] add a note for `str::bytes` --- clippy_lints/src/loops/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 10ba739909f79..9a3fd147fb556 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -758,7 +758,8 @@ declare_clippy_lint! { /// Instead of `.chars().enumerate()`, the correct iterator to use is `.char_indices()`, which yields byte indices. /// /// This pattern is technically fine if the strings are known to only use the ASCII subset, - /// but there is also no downside to just using `.char_indices()` directly. + /// though in those cases it would be better to use `bytes()` directly to make the intent clearer, + /// but there is also no downside to just using `.char_indices()` directly and supporting non-ASCII strings. /// /// You may also want to read the [chapter on strings in the Rust Book](https://doc.rust-lang.org/book/ch08-02-strings.html) /// which goes into this in more detail. From d5d2189c715bba5b12585c52ac8e30ac52c484f9 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 3 Dec 2024 04:33:01 +0100 Subject: [PATCH 0385/2248] rename lint to `char_indices_as_byte_indices` --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- ...ces.rs => char_indices_as_byte_indices.rs} | 4 +-- clippy_lints/src/loops/mod.rs | 8 ++--- ...xed => char_indices_as_byte_indices.fixed} | 18 +++++------ ...ces.rs => char_indices_as_byte_indices.rs} | 18 +++++------ ...rr => char_indices_as_byte_indices.stderr} | 32 +++++++++---------- 7 files changed, 42 insertions(+), 42 deletions(-) rename clippy_lints/src/loops/{chars_enumerate_for_byte_indices.rs => char_indices_as_byte_indices.rs} (98%) rename tests/ui/{chars_enumerate_for_byte_indices.fixed => char_indices_as_byte_indices.fixed} (74%) rename tests/ui/{chars_enumerate_for_byte_indices.rs => char_indices_as_byte_indices.rs} (75%) rename tests/ui/{chars_enumerate_for_byte_indices.stderr => char_indices_as_byte_indices.stderr} (79%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68387498c0d3b..ee16c442c0f8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5516,8 +5516,8 @@ Released 2018-09-13 [`cast_slice_different_sizes`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_slice_different_sizes [`cast_slice_from_raw_parts`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_slice_from_raw_parts [`cfg_not_test`]: https://rust-lang.github.io/rust-clippy/master/index.html#cfg_not_test +[`char_indices_as_byte_indices`]: https://rust-lang.github.io/rust-clippy/master/index.html#char_indices_as_byte_indices [`char_lit_as_u8`]: https://rust-lang.github.io/rust-clippy/master/index.html#char_lit_as_u8 -[`chars_enumerate_for_byte_indices`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_enumerate_for_byte_indices [`chars_last_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_last_cmp [`chars_next_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_next_cmp [`checked_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index cd3f40a003dbd..7ee898ec75a94 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -287,7 +287,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::literal_representation::UNREADABLE_LITERAL_INFO, crate::literal_representation::UNUSUAL_BYTE_GROUPINGS_INFO, crate::literal_string_with_formatting_args::LITERAL_STRING_WITH_FORMATTING_ARGS_INFO, - crate::loops::CHARS_ENUMERATE_FOR_BYTE_INDICES_INFO, + crate::loops::CHAR_INDICES_AS_BYTE_INDICES_INFO, crate::loops::EMPTY_LOOP_INFO, crate::loops::EXPLICIT_COUNTER_LOOP_INFO, crate::loops::EXPLICIT_INTO_ITER_LOOP_INFO, diff --git a/clippy_lints/src/loops/chars_enumerate_for_byte_indices.rs b/clippy_lints/src/loops/char_indices_as_byte_indices.rs similarity index 98% rename from clippy_lints/src/loops/chars_enumerate_for_byte_indices.rs rename to clippy_lints/src/loops/char_indices_as_byte_indices.rs index 40274311d7800..90e6f71e41ad4 100644 --- a/clippy_lints/src/loops/chars_enumerate_for_byte_indices.rs +++ b/clippy_lints/src/loops/char_indices_as_byte_indices.rs @@ -10,7 +10,7 @@ use rustc_lint::LateContext; use rustc_middle::ty::Ty; use rustc_span::{Span, sym}; -use super::CHARS_ENUMERATE_FOR_BYTE_INDICES; +use super::CHAR_INDICES_AS_BYTE_INDICES; // The list of `str` methods we want to lint that have a `usize` argument representing a byte index. // Note: `String` also has methods that work with byte indices, @@ -101,7 +101,7 @@ fn check_index_usage<'tcx>( span_lint_hir_and_then( cx, - CHARS_ENUMERATE_FOR_BYTE_INDICES, + CHAR_INDICES_AS_BYTE_INDICES, expr.hir_id, expr.span, message, diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 9a3fd147fb556..2b66827e82eeb 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -1,4 +1,4 @@ -mod chars_enumerate_for_byte_indices; +mod char_indices_as_byte_indices; mod empty_loop; mod explicit_counter_loop; mod explicit_into_iter_loop; @@ -779,7 +779,7 @@ declare_clippy_lint! { /// } /// ``` #[clippy::version = "1.83.0"] - pub CHARS_ENUMERATE_FOR_BYTE_INDICES, + pub CHAR_INDICES_AS_BYTE_INDICES, correctness, "using the character position yielded by `.chars().enumerate()` in a context where a byte index is expected" } @@ -821,7 +821,7 @@ impl_lint_pass!(Loops => [ UNUSED_ENUMERATE_INDEX, INFINITE_LOOP, MANUAL_SLICE_FILL, - CHARS_ENUMERATE_FOR_BYTE_INDICES, + CHAR_INDICES_AS_BYTE_INDICES, ]); impl<'tcx> LateLintPass<'tcx> for Loops { @@ -905,7 +905,7 @@ impl Loops { manual_flatten::check(cx, pat, arg, body, span, self.msrv); manual_find::check(cx, pat, arg, body, span, expr); unused_enumerate_index::check(cx, pat, arg, body); - chars_enumerate_for_byte_indices::check(cx, pat, arg, body); + char_indices_as_byte_indices::check(cx, pat, arg, body); } fn check_for_loop_arg(&self, cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) { diff --git a/tests/ui/chars_enumerate_for_byte_indices.fixed b/tests/ui/char_indices_as_byte_indices.fixed similarity index 74% rename from tests/ui/chars_enumerate_for_byte_indices.fixed rename to tests/ui/char_indices_as_byte_indices.fixed index 7a4f87fa2d484..a7c6bcd2681a5 100644 --- a/tests/ui/chars_enumerate_for_byte_indices.fixed +++ b/tests/ui/char_indices_as_byte_indices.fixed @@ -1,5 +1,5 @@ #![feature(round_char_boundary)] -#![warn(clippy::chars_enumerate_for_byte_indices)] +#![warn(clippy::char_indices_as_byte_indices)] trait StrExt { fn use_index(&self, _: usize); @@ -11,32 +11,32 @@ impl StrExt for str { fn bad(prim: &str, string: String) { for (idx, _) in prim.char_indices() { let _ = prim[..idx]; - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices prim.split_at(idx); - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices // This won't panic, but it can still return a wrong substring let _ = prim[..prim.floor_char_boundary(idx)]; - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices // can't use #[expect] here because the .fixed file will still have the attribute and create an // unfulfilled expectation, but make sure lint level attributes work on the use expression: - #[allow(clippy::chars_enumerate_for_byte_indices)] + #[allow(clippy::char_indices_as_byte_indices)] let _ = prim[..idx]; } for c in prim.char_indices() { let _ = prim[..c.0]; - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices prim.split_at(c.0); - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices } for (idx, _) in string.char_indices() { let _ = string[..idx]; - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices string.split_at(idx); - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices } } diff --git a/tests/ui/chars_enumerate_for_byte_indices.rs b/tests/ui/char_indices_as_byte_indices.rs similarity index 75% rename from tests/ui/chars_enumerate_for_byte_indices.rs rename to tests/ui/char_indices_as_byte_indices.rs index 1e8f555846a44..bb0f5df19bc76 100644 --- a/tests/ui/chars_enumerate_for_byte_indices.rs +++ b/tests/ui/char_indices_as_byte_indices.rs @@ -1,5 +1,5 @@ #![feature(round_char_boundary)] -#![warn(clippy::chars_enumerate_for_byte_indices)] +#![warn(clippy::char_indices_as_byte_indices)] trait StrExt { fn use_index(&self, _: usize); @@ -11,32 +11,32 @@ impl StrExt for str { fn bad(prim: &str, string: String) { for (idx, _) in prim.chars().enumerate() { let _ = prim[..idx]; - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices prim.split_at(idx); - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices // This won't panic, but it can still return a wrong substring let _ = prim[..prim.floor_char_boundary(idx)]; - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices // can't use #[expect] here because the .fixed file will still have the attribute and create an // unfulfilled expectation, but make sure lint level attributes work on the use expression: - #[allow(clippy::chars_enumerate_for_byte_indices)] + #[allow(clippy::char_indices_as_byte_indices)] let _ = prim[..idx]; } for c in prim.chars().enumerate() { let _ = prim[..c.0]; - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices prim.split_at(c.0); - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices } for (idx, _) in string.chars().enumerate() { let _ = string[..idx]; - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices string.split_at(idx); - //~^ chars_enumerate_for_byte_indices + //~^ char_indices_as_byte_indices } } diff --git a/tests/ui/chars_enumerate_for_byte_indices.stderr b/tests/ui/char_indices_as_byte_indices.stderr similarity index 79% rename from tests/ui/chars_enumerate_for_byte_indices.stderr rename to tests/ui/char_indices_as_byte_indices.stderr index 0159eb0387b9e..a3c8457839258 100644 --- a/tests/ui/chars_enumerate_for_byte_indices.stderr +++ b/tests/ui/char_indices_as_byte_indices.stderr @@ -1,31 +1,31 @@ error: indexing into a string with a character position where a byte index is expected - --> tests/ui/chars_enumerate_for_byte_indices.rs:13:24 + --> tests/ui/char_indices_as_byte_indices.rs:13:24 | LL | let _ = prim[..idx]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/chars_enumerate_for_byte_indices.rs:12:10 + --> tests/ui/char_indices_as_byte_indices.rs:12:10 | LL | for (idx, _) in prim.chars().enumerate() { | ^^^ ^^^^^^^^^^^ - = note: `-D clippy::chars-enumerate-for-byte-indices` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::chars_enumerate_for_byte_indices)]` + = note: `-D clippy::char-indices-as-byte-indices` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::char_indices_as_byte_indices)]` help: consider using `.char_indices()` instead | LL | for (idx, _) in prim.char_indices() { | ~~~~~~~~~~~~~~ error: passing a character position to a method that expects a byte index - --> tests/ui/chars_enumerate_for_byte_indices.rs:15:23 + --> tests/ui/char_indices_as_byte_indices.rs:15:23 | LL | prim.split_at(idx); | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/chars_enumerate_for_byte_indices.rs:12:10 + --> tests/ui/char_indices_as_byte_indices.rs:12:10 | LL | for (idx, _) in prim.chars().enumerate() { | ^^^ ^^^^^^^^^^^ @@ -35,14 +35,14 @@ LL | for (idx, _) in prim.char_indices() { | ~~~~~~~~~~~~~~ error: passing a character position to a method that expects a byte index - --> tests/ui/chars_enumerate_for_byte_indices.rs:19:49 + --> tests/ui/char_indices_as_byte_indices.rs:19:49 | LL | let _ = prim[..prim.floor_char_boundary(idx)]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/chars_enumerate_for_byte_indices.rs:12:10 + --> tests/ui/char_indices_as_byte_indices.rs:12:10 | LL | for (idx, _) in prim.chars().enumerate() { | ^^^ ^^^^^^^^^^^ @@ -52,14 +52,14 @@ LL | for (idx, _) in prim.char_indices() { | ~~~~~~~~~~~~~~ error: indexing into a string with a character position where a byte index is expected - --> tests/ui/chars_enumerate_for_byte_indices.rs:29:24 + --> tests/ui/char_indices_as_byte_indices.rs:29:24 | LL | let _ = prim[..c.0]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/chars_enumerate_for_byte_indices.rs:28:9 + --> tests/ui/char_indices_as_byte_indices.rs:28:9 | LL | for c in prim.chars().enumerate() { | ^ ^^^^^^^^^^^ @@ -69,14 +69,14 @@ LL | for c in prim.char_indices() { | ~~~~~~~~~~~~~~ error: passing a character position to a method that expects a byte index - --> tests/ui/chars_enumerate_for_byte_indices.rs:31:23 + --> tests/ui/char_indices_as_byte_indices.rs:31:23 | LL | prim.split_at(c.0); | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/chars_enumerate_for_byte_indices.rs:28:9 + --> tests/ui/char_indices_as_byte_indices.rs:28:9 | LL | for c in prim.chars().enumerate() { | ^ ^^^^^^^^^^^ @@ -86,14 +86,14 @@ LL | for c in prim.char_indices() { | ~~~~~~~~~~~~~~ error: indexing into a string with a character position where a byte index is expected - --> tests/ui/chars_enumerate_for_byte_indices.rs:36:26 + --> tests/ui/char_indices_as_byte_indices.rs:36:26 | LL | let _ = string[..idx]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/chars_enumerate_for_byte_indices.rs:35:10 + --> tests/ui/char_indices_as_byte_indices.rs:35:10 | LL | for (idx, _) in string.chars().enumerate() { | ^^^ ^^^^^^^^^^^ @@ -103,14 +103,14 @@ LL | for (idx, _) in string.char_indices() { | ~~~~~~~~~~~~~~ error: passing a character position to a method that expects a byte index - --> tests/ui/chars_enumerate_for_byte_indices.rs:38:25 + --> tests/ui/char_indices_as_byte_indices.rs:38:25 | LL | string.split_at(idx); | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/chars_enumerate_for_byte_indices.rs:35:10 + --> tests/ui/char_indices_as_byte_indices.rs:35:10 | LL | for (idx, _) in string.chars().enumerate() { | ^^^ ^^^^^^^^^^^ From c7390279cafacabaf18c927225751623b9da2cb1 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 30 Mar 2025 13:53:12 +0200 Subject: [PATCH 0386/2248] add comment and `.clone()` test case --- .../src/loops/char_indices_as_byte_indices.rs | 5 ++- tests/ui/char_indices_as_byte_indices.fixed | 6 ++++ tests/ui/char_indices_as_byte_indices.rs | 6 ++++ tests/ui/char_indices_as_byte_indices.stderr | 35 +++++++++++-------- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/loops/char_indices_as_byte_indices.rs b/clippy_lints/src/loops/char_indices_as_byte_indices.rs index 90e6f71e41ad4..8916454ada16e 100644 --- a/clippy_lints/src/loops/char_indices_as_byte_indices.rs +++ b/clippy_lints/src/loops/char_indices_as_byte_indices.rs @@ -84,6 +84,9 @@ fn check_index_usage<'tcx>( let is_string_like = |ty: Ty<'_>| ty.is_str() || is_type_lang_item(cx, ty, LangItem::String); let message = match parent_expr.kind { ExprKind::MethodCall(segment, recv, ..) + // We currently only lint `str` methods (which `String` can deref to), so a `.is_str()` check is sufficient here + // (contrary to the `ExprKind::Index` case which needs to handle both with `is_string_like` because `String` implements + // `Index` directly and no deref to `str` would happen in that case). if cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_str() && BYTE_INDEX_METHODS.contains(&segment.ident.name.as_str()) && eq_expr_value(cx, chars_recv, recv) => @@ -126,7 +129,7 @@ fn check_index_usage<'tcx>( /// but for `.get(..idx)` we want to consider the method call the consuming expression, /// which requires skipping past the range expression. fn index_consumed_at<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { - for (_, node) in cx.tcx.hir().parent_iter(expr.hir_id) { + for (_, node) in cx.tcx.hir_parent_iter(expr.hir_id) { match node { Node::Expr(expr) if higher::Range::hir(expr).is_some() => {}, Node::ExprField(_) => {}, diff --git a/tests/ui/char_indices_as_byte_indices.fixed b/tests/ui/char_indices_as_byte_indices.fixed index a7c6bcd2681a5..04c8f6782c51e 100644 --- a/tests/ui/char_indices_as_byte_indices.fixed +++ b/tests/ui/char_indices_as_byte_indices.fixed @@ -54,6 +54,12 @@ fn good(prim: &str, prim2: &str) { // str method taking a usize that doesn't represent a byte index prim.splitn(idx, prim2); } + + let mut string = "äa".to_owned(); + for (idx, _) in string.clone().chars().enumerate() { + // Even though the receiver is the same expression, it should not be treated as the same value. + string.clone().remove(idx); + } } fn main() {} diff --git a/tests/ui/char_indices_as_byte_indices.rs b/tests/ui/char_indices_as_byte_indices.rs index bb0f5df19bc76..773a4fc65f12f 100644 --- a/tests/ui/char_indices_as_byte_indices.rs +++ b/tests/ui/char_indices_as_byte_indices.rs @@ -54,6 +54,12 @@ fn good(prim: &str, prim2: &str) { // str method taking a usize that doesn't represent a byte index prim.splitn(idx, prim2); } + + let mut string = "äa".to_owned(); + for (idx, _) in string.clone().chars().enumerate() { + // Even though the receiver is the same expression, it should not be treated as the same value. + string.clone().remove(idx); + } } fn main() {} diff --git a/tests/ui/char_indices_as_byte_indices.stderr b/tests/ui/char_indices_as_byte_indices.stderr index a3c8457839258..e2b4c1db78cf4 100644 --- a/tests/ui/char_indices_as_byte_indices.stderr +++ b/tests/ui/char_indices_as_byte_indices.stderr @@ -14,8 +14,9 @@ LL | for (idx, _) in prim.chars().enumerate() { = help: to override `-D warnings` add `#[allow(clippy::char_indices_as_byte_indices)]` help: consider using `.char_indices()` instead | -LL | for (idx, _) in prim.char_indices() { - | ~~~~~~~~~~~~~~ +LL - for (idx, _) in prim.chars().enumerate() { +LL + for (idx, _) in prim.char_indices() { + | error: passing a character position to a method that expects a byte index --> tests/ui/char_indices_as_byte_indices.rs:15:23 @@ -31,8 +32,9 @@ LL | for (idx, _) in prim.chars().enumerate() { | ^^^ ^^^^^^^^^^^ help: consider using `.char_indices()` instead | -LL | for (idx, _) in prim.char_indices() { - | ~~~~~~~~~~~~~~ +LL - for (idx, _) in prim.chars().enumerate() { +LL + for (idx, _) in prim.char_indices() { + | error: passing a character position to a method that expects a byte index --> tests/ui/char_indices_as_byte_indices.rs:19:49 @@ -48,8 +50,9 @@ LL | for (idx, _) in prim.chars().enumerate() { | ^^^ ^^^^^^^^^^^ help: consider using `.char_indices()` instead | -LL | for (idx, _) in prim.char_indices() { - | ~~~~~~~~~~~~~~ +LL - for (idx, _) in prim.chars().enumerate() { +LL + for (idx, _) in prim.char_indices() { + | error: indexing into a string with a character position where a byte index is expected --> tests/ui/char_indices_as_byte_indices.rs:29:24 @@ -65,8 +68,9 @@ LL | for c in prim.chars().enumerate() { | ^ ^^^^^^^^^^^ help: consider using `.char_indices()` instead | -LL | for c in prim.char_indices() { - | ~~~~~~~~~~~~~~ +LL - for c in prim.chars().enumerate() { +LL + for c in prim.char_indices() { + | error: passing a character position to a method that expects a byte index --> tests/ui/char_indices_as_byte_indices.rs:31:23 @@ -82,8 +86,9 @@ LL | for c in prim.chars().enumerate() { | ^ ^^^^^^^^^^^ help: consider using `.char_indices()` instead | -LL | for c in prim.char_indices() { - | ~~~~~~~~~~~~~~ +LL - for c in prim.chars().enumerate() { +LL + for c in prim.char_indices() { + | error: indexing into a string with a character position where a byte index is expected --> tests/ui/char_indices_as_byte_indices.rs:36:26 @@ -99,8 +104,9 @@ LL | for (idx, _) in string.chars().enumerate() { | ^^^ ^^^^^^^^^^^ help: consider using `.char_indices()` instead | -LL | for (idx, _) in string.char_indices() { - | ~~~~~~~~~~~~~~ +LL - for (idx, _) in string.chars().enumerate() { +LL + for (idx, _) in string.char_indices() { + | error: passing a character position to a method that expects a byte index --> tests/ui/char_indices_as_byte_indices.rs:38:25 @@ -116,8 +122,9 @@ LL | for (idx, _) in string.chars().enumerate() { | ^^^ ^^^^^^^^^^^ help: consider using `.char_indices()` instead | -LL | for (idx, _) in string.char_indices() { - | ~~~~~~~~~~~~~~ +LL - for (idx, _) in string.chars().enumerate() { +LL + for (idx, _) in string.char_indices() { + | error: aborting due to 7 previous errors From ebae4c65a10a593b838d9c2f07f4c13e342ec03e Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 30 Mar 2025 13:21:01 +0100 Subject: [PATCH 0387/2248] 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 2eee361a1ae8146d5f499f88690c71a7867828d2 Mon Sep 17 00:00:00 2001 From: WeiTheShinobi Date: Sun, 30 Mar 2025 22:00:01 +0800 Subject: [PATCH 0388/2248] use `is_automatically_derived()` instead of `has_attr(sym::automatically_derived)` --- clippy_lints/src/derivable_impls.rs | 2 +- clippy_lints/src/derive.rs | 6 +++--- clippy_lints/src/missing_fields_in_debug.rs | 2 +- clippy_lints/src/partialeq_ne_impl.rs | 2 +- clippy_lints/src/unconditional_recursion.rs | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 479422f7378ed..10331b3855b84 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -188,7 +188,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls { self_ty, .. }) = item.kind - && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived) + && !cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) && !item.span.from_expansion() && let Some(def_id) = trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::Default, def_id) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index e5ec17d89a115..a05d57d6836a5 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -206,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive { }) = item.kind { let ty = cx.tcx.type_of(item.owner_id).instantiate_identity(); - let is_automatically_derived = cx.tcx.has_attr(item.owner_id, sym::automatically_derived); + let is_automatically_derived = cx.tcx.is_automatically_derived(item.owner_id.to_def_id()); check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived); @@ -235,7 +235,7 @@ fn check_hash_peq<'tcx>( { // Look for the PartialEq implementations for `ty` cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { - let peq_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived); + let peq_is_automatically_derived = cx.tcx.is_automatically_derived(impl_id); if !hash_is_automatically_derived || peq_is_automatically_derived { return; @@ -278,7 +278,7 @@ fn check_ord_partial_ord<'tcx>( { // Look for the PartialOrd implementations for `ty` cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| { - let partial_ord_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived); + let partial_ord_is_automatically_derived = cx.tcx.is_automatically_derived(impl_id); if partial_ord_is_automatically_derived == ord_is_automatically_derived { return; diff --git a/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs index 05517a5d869c9..1932d2d5f9785 100644 --- a/clippy_lints/src/missing_fields_in_debug.rs +++ b/clippy_lints/src/missing_fields_in_debug.rs @@ -209,7 +209,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { && let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, self_path_did) = self_path.res && cx.tcx.is_diagnostic_item(sym::Debug, trait_def_id) // don't trigger if this impl was derived - && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived) + && !cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) && !item.span.from_expansion() // find `Debug::fmt` function && let Some(fmt_item) = items.iter().find(|i| i.ident.name == sym::fmt) diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 65671b478ba74..8eaf65e63065e 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -38,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl { items: impl_items, .. }) = item.kind - && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived) + && !cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) && let Some(eq_trait) = cx.tcx.lang_items().eq_trait() && trait_ref.path.res.def_id() == eq_trait { diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs index 11e938b5e4dd5..e07257f4aef07 100644 --- a/clippy_lints/src/unconditional_recursion.rs +++ b/clippy_lints/src/unconditional_recursion.rs @@ -135,7 +135,7 @@ fn get_impl_trait_def_id(cx: &LateContext<'_>, method_def_id: LocalDefId) -> Opt }), )) = cx.tcx.hir_parent_iter(hir_id).next() // We exclude `impl` blocks generated from rustc's proc macros. - && !cx.tcx.has_attr(*owner_id, sym::automatically_derived) + && !cx.tcx.is_automatically_derived(owner_id.to_def_id()) // It is a implementation of a trait. && let Some(trait_) = impl_.of_trait { @@ -240,7 +240,7 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local }), )) = cx.tcx.hir_parent_iter(hir_id).next() // We exclude `impl` blocks generated from rustc's proc macros. - && !cx.tcx.has_attr(*owner_id, sym::automatically_derived) + && !cx.tcx.is_automatically_derived(owner_id.to_def_id()) // It is a implementation of a trait. && let Some(trait_) = impl_.of_trait && let Some(trait_def_id) = trait_.trait_def_id() @@ -337,7 +337,7 @@ impl UnconditionalRecursion { for (ty, impl_def_ids) in impls.non_blanket_impls() { let Some(self_def_id) = ty.def() else { continue }; for impl_def_id in impl_def_ids { - if !cx.tcx.has_attr(*impl_def_id, sym::automatically_derived) && + if !cx.tcx.is_automatically_derived(*impl_def_id) && let Some(assoc_item) = cx .tcx .associated_items(impl_def_id) 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 0389/2248] 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 5f26d0e9703544c751952ba5e13bb55a64f55abf Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 9 Mar 2025 14:55:46 +0100 Subject: [PATCH 0390/2248] Drop `clippy::invalid_null_ptr_usage` --- clippy_lints/src/declared_lints.rs | 1 - clippy_lints/src/deprecated_lints.rs | 2 + clippy_lints/src/ptr.rs | 73 +--------- tests/ui/crashes/ice-1782.rs | 2 +- tests/ui/invalid_null_ptr_usage.fixed | 66 --------- tests/ui/invalid_null_ptr_usage.rs | 66 --------- tests/ui/invalid_null_ptr_usage.stderr | 136 ------------------ tests/ui/invalid_null_ptr_usage_no_std.fixed | 79 ---------- tests/ui/invalid_null_ptr_usage_no_std.rs | 79 ---------- tests/ui/invalid_null_ptr_usage_no_std.stderr | 136 ------------------ tests/ui/rename.fixed | 1 + tests/ui/rename.rs | 1 + tests/ui/rename.stderr | 30 ++-- 13 files changed, 24 insertions(+), 648 deletions(-) delete mode 100644 tests/ui/invalid_null_ptr_usage.fixed delete mode 100644 tests/ui/invalid_null_ptr_usage.rs delete mode 100644 tests/ui/invalid_null_ptr_usage.stderr delete mode 100644 tests/ui/invalid_null_ptr_usage_no_std.fixed delete mode 100644 tests/ui/invalid_null_ptr_usage_no_std.rs delete mode 100644 tests/ui/invalid_null_ptr_usage_no_std.stderr diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 7fa23dad69817..39e4516370709 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/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/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 0031da406f17f..de66ead4f4204 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/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/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 55f1ece05593f..50ef56db167c1 100644 --- a/clippy_lints/src/ptr.rs +++ b/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/tests/ui/crashes/ice-1782.rs b/tests/ui/crashes/ice-1782.rs index fefdc405cce2a..4a1886c08af6a 100644 --- a/tests/ui/crashes/ice-1782.rs +++ b/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/tests/ui/invalid_null_ptr_usage.fixed b/tests/ui/invalid_null_ptr_usage.fixed deleted file mode 100644 index ce78e89ee829c..0000000000000 --- a/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/tests/ui/invalid_null_ptr_usage.rs b/tests/ui/invalid_null_ptr_usage.rs deleted file mode 100644 index 361865fbd9601..0000000000000 --- a/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/tests/ui/invalid_null_ptr_usage.stderr b/tests/ui/invalid_null_ptr_usage.stderr deleted file mode 100644 index 3f9d15b904018..0000000000000 --- a/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/tests/ui/invalid_null_ptr_usage_no_std.fixed b/tests/ui/invalid_null_ptr_usage_no_std.fixed deleted file mode 100644 index df7ab166187de..0000000000000 --- a/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/tests/ui/invalid_null_ptr_usage_no_std.rs b/tests/ui/invalid_null_ptr_usage_no_std.rs deleted file mode 100644 index 38ddfff055353..0000000000000 --- a/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/tests/ui/invalid_null_ptr_usage_no_std.stderr b/tests/ui/invalid_null_ptr_usage_no_std.stderr deleted file mode 100644 index b5dd21ce6248f..0000000000000 --- a/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/tests/ui/rename.fixed b/tests/ui/rename.fixed index 501811fa491b3..7964047069689 100644 --- a/tests/ui/rename.fixed +++ b/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/tests/ui/rename.rs b/tests/ui/rename.rs index 7f4b8062e1b4b..aa7b905b4b818 100644 --- a/tests/ui/rename.rs +++ b/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/tests/ui/rename.stderr b/tests/ui/rename.stderr index f24eaec3917ad..b3c88167c1115 100644 --- a/tests/ui/rename.stderr +++ b/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 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 0391/2248] 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 0392/2248] 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 0393/2248] 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 0394/2248] 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 0395/2248] 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 0396/2248] 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 19648ce5cd12b11889eccacac50c70ca8ac78fee Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 23 Mar 2025 18:45:08 -0700 Subject: [PATCH 0397/2248] codegen test for non-memcmp array comparison --- tests/codegen/array-cmp.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/codegen/array-cmp.rs b/tests/codegen/array-cmp.rs index 2565a385b61b5..f9b7be8988282 100644 --- a/tests/codegen/array-cmp.rs +++ b/tests/codegen/array-cmp.rs @@ -17,3 +17,15 @@ pub fn compare() -> bool { [0x00, 0x00, 0x48, 0x41] } } + +// CHECK-LABEL: @array_of_tuple_le +// CHECK: call{{.+}}i8 @llvm.scmp.i8.i16 +// CHECK: call{{.+}}i8 @llvm.ucmp.i8.i16 +// CHECK: call{{.+}}i8 @llvm.scmp.i8.i16 +// CHECK: call{{.+}}i8 @llvm.ucmp.i8.i16 +// CHECK: %[[RET:.+]] = icmp slt i8 {{.+}}, 1 +// CHECK: ret i8 %[[RET]] +#[no_mangle] +pub fn array_of_tuple_le(a: &[(i16, u16); 2], b: &[(i16, u16); 2]) -> bool { + a <= b +} From 04d9d864b39c56aa6efa6b5f7845b4735d7a6428 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 31 Mar 2025 14:53:39 +0800 Subject: [PATCH 0398/2248] std: clarify Mutex::get_mut more clearly Signed-off-by: xizheyin --- library/std/src/sync/poison/mutex.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 9362c764173a8..adb74bb6f3de7 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -582,7 +582,9 @@ impl Mutex { /// Returns a mutable reference to the underlying data. /// /// Since this call borrows the `Mutex` mutably, no actual locking needs to - /// take place -- the mutable borrow statically guarantees no locks exist. + /// take place -- the mutable borrow statically guarantees no new locks can be acquired + /// while this reference exists. Note that this method does not clear any previous abandoned locks + /// (e.g., via [`forget()`] on a [`MutexGuard`]). /// /// # Errors /// @@ -599,6 +601,8 @@ impl Mutex { /// *mutex.get_mut().unwrap() = 10; /// assert_eq!(*mutex.lock().unwrap(), 10); /// ``` + /// + /// [`forget()`]: mem::forget #[stable(feature = "mutex_get_mut", since = "1.6.0")] pub fn get_mut(&mut self) -> LockResult<&mut T> { let data = self.data.get_mut(); From a451b04d0140a25d8b55393b634be35e624021f4 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 31 Mar 2025 07:43:08 +0200 Subject: [PATCH 0399/2248] fix: Cleanup param name inlay hint filtering --- .../rust-analyzer/crates/hir/src/attrs.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 16 +- .../src/handlers/extract_function.rs | 2 +- .../ide-db/src/syntax_helpers/node_ext.rs | 4 +- .../ide/src/inlay_hints/generic_param.rs | 49 ++-- .../crates/ide/src/inlay_hints/param_name.rs | 222 +++++++++++------- .../crates/syntax/src/ast/node_ext.rs | 10 + 7 files changed, 187 insertions(+), 118 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index 70637028eff98..e71b51bfa432c 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -260,7 +260,7 @@ fn resolve_impl_trait_item( // attributes here. Use path resolution directly instead. // // FIXME: resolve type aliases (which are not yielded by iterate_path_candidates) - method_resolution::iterate_path_candidates( + _ = method_resolution::iterate_path_candidates( &canonical, db, environment, diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index c5ed0446839f2..7f0382fa93f48 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -2922,10 +2922,14 @@ impl Trait { db: &dyn HirDatabase, ) -> Option> { let mut violations = vec![]; - hir_ty::dyn_compatibility::dyn_compatibility_with_callback(db, self.id, &mut |violation| { - violations.push(violation); - ControlFlow::Continue(()) - }); + _ = hir_ty::dyn_compatibility::dyn_compatibility_with_callback( + db, + self.id, + &mut |violation| { + violations.push(violation); + ControlFlow::Continue(()) + }, + ); violations.is_empty().not().then_some(violations) } @@ -5514,7 +5518,7 @@ impl Type { .generic_def() .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); - method_resolution::iterate_method_candidates_dyn( + _ = method_resolution::iterate_method_candidates_dyn( &canonical, db, environment, @@ -5601,7 +5605,7 @@ impl Type { .generic_def() .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); - method_resolution::iterate_path_candidates( + _ = method_resolution::iterate_path_candidates( &canonical, db, environment, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs index abc0698b0141e..5a6a7ede35264 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs @@ -751,7 +751,7 @@ impl FunctionBody { ast::Stmt::Item(_) => (), ast::Stmt::LetStmt(stmt) => { if let Some(pat) = stmt.pat() { - walk_pat(&pat, &mut |pat| { + _ = walk_pat(&pat, &mut |pat| { cb(pat); std::ops::ControlFlow::<(), ()>::Continue(()) }); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs index cd47524caa3c5..bdff64dd0812c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs @@ -121,7 +121,7 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) { match ast::Stmt::cast(node.clone()) { Some(ast::Stmt::LetStmt(l)) => { if let Some(pat) = l.pat() { - walk_pat(&pat, &mut |pat| { + _ = walk_pat(&pat, &mut |pat| { cb(pat); ControlFlow::<(), ()>::Continue(()) }); @@ -159,7 +159,7 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) { } } else if let Some(pat) = ast::Pat::cast(node) { preorder.skip_subtree(); - walk_pat(&pat, &mut |pat| { + _ = walk_pat(&pat, &mut |pat| { cb(pat); ControlFlow::<(), ()>::Continue(()) }); diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs index fc1083fdca657..730732df860f9 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs @@ -1,4 +1,5 @@ //! Implementation of inlay hints for generic parameters. +use either::Either; use ide_db::{active_parameter::generic_def_for_node, famous_defs::FamousDefs}; use syntax::{ AstNode, @@ -6,7 +7,8 @@ use syntax::{ }; use crate::{ - InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind, inlay_hints::GenericParameterHints, + InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind, + inlay_hints::{GenericParameterHints, param_name}, }; use super::param_name::is_argument_similar_to_param_name; @@ -62,8 +64,17 @@ pub(crate) fn hints( let param_name = param.name(sema.db); let should_hide = { - let argument = get_string_representation(&arg)?; - is_argument_similar_to_param_name(&argument, param_name.as_str()) + let param_name = param_name.as_str(); + get_segment_representation(&arg).map_or(false, |seg| match seg { + Either::Left(Either::Left(argument)) => { + is_argument_similar_to_param_name(&argument, param_name) + } + Either::Left(Either::Right(argument)) => argument + .segment() + .and_then(|it| it.name_ref()) + .is_some_and(|it| it.text().eq_ignore_ascii_case(param_name)), + Either::Right(lifetime) => lifetime.text().eq_ignore_ascii_case(param_name), + }) }; if should_hide { @@ -111,32 +122,34 @@ pub(crate) fn hints( Some(()) } -fn get_string_representation(arg: &ast::GenericArg) -> Option { +fn get_segment_representation( + arg: &ast::GenericArg, +) -> Option, ast::Path>, ast::Lifetime>> { return match arg { ast::GenericArg::AssocTypeArg(_) => None, - ast::GenericArg::ConstArg(const_arg) => Some(const_arg.to_string()), + ast::GenericArg::ConstArg(const_arg) => { + param_name::get_segment_representation(&const_arg.expr()?).map(Either::Left) + } ast::GenericArg::LifetimeArg(lifetime_arg) => { let lifetime = lifetime_arg.lifetime()?; - Some(lifetime.to_string()) + Some(Either::Right(lifetime)) } ast::GenericArg::TypeArg(type_arg) => { let ty = type_arg.ty()?; - Some( - type_path_segment(&ty) - .map_or_else(|| type_arg.to_string(), |segment| segment.to_string()), - ) + type_path(&ty).map(Either::Right).map(Either::Left) } }; - fn type_path_segment(ty: &ast::Type) -> Option { + fn type_path(ty: &ast::Type) -> Option { match ty { - ast::Type::ArrayType(it) => type_path_segment(&it.ty()?), - ast::Type::ForType(it) => type_path_segment(&it.ty()?), - ast::Type::ParenType(it) => type_path_segment(&it.ty()?), - ast::Type::PathType(path_type) => path_type.path()?.segment(), - ast::Type::PtrType(it) => type_path_segment(&it.ty()?), - ast::Type::RefType(it) => type_path_segment(&it.ty()?), - ast::Type::SliceType(it) => type_path_segment(&it.ty()?), + ast::Type::ArrayType(it) => type_path(&it.ty()?), + ast::Type::ForType(it) => type_path(&it.ty()?), + ast::Type::ParenType(it) => type_path(&it.ty()?), + ast::Type::PathType(path_type) => path_type.path(), + ast::Type::PtrType(it) => type_path(&it.ty()?), + ast::Type::RefType(it) => type_path(&it.ty()?), + ast::Type::SliceType(it) => type_path(&it.ty()?), + ast::Type::MacroType(macro_type) => macro_type.macro_call()?.path(), _ => None, } } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs index 44ea5351fbdd6..99c698ce02954 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs @@ -4,16 +4,15 @@ //! _ = max(/*x*/4, /*y*/4); //! ``` +use std::iter::zip; + use either::Either; -use hir::{Callable, Semantics}; +use hir::Semantics; use ide_db::{RootDatabase, famous_defs::FamousDefs}; use span::EditionedFileId; use stdx::to_lower_snake_case; -use syntax::{ - ToSmolStr, - ast::{self, AstNode, HasArgList, HasName, UnaryOp}, -}; +use syntax::ast::{self, AstNode, HasArgList, HasName, UnaryOp}; use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind}; @@ -29,6 +28,12 @@ pub(super) fn hints( } let (callable, arg_list) = get_callable(sema, &expr)?; + let unary_function = callable.n_params() == 1; + let function_name = match callable.kind() { + hir::CallableKind::Function(function) => Some(function.name(sema.db)), + _ => None, + }; + let function_name = function_name.as_ref().map(|it| it.as_str()); let hints = callable .params() .into_iter() @@ -40,7 +45,13 @@ pub(super) fn hints( Some((p, param_name, arg, range)) }) .filter(|(_, param_name, arg, _)| { - !should_hide_param_name_hint(sema, &callable, param_name.as_str(), arg) + !should_hide_param_name_hint( + sema, + unary_function, + function_name, + param_name.as_str(), + arg, + ) }) .map(|(param, param_name, _, hir::FileRange { range, .. })| { let colon = if config.render_colons { ":" } else { "" }; @@ -94,9 +105,13 @@ fn get_callable( } } +const INSIGNIFICANT_METHOD_NAMES: &[&str] = &["clone", "as_ref", "into"]; +const INSIGNIFICANT_PARAMETER_NAMES: &[&str] = &["predicate", "value", "pat", "rhs", "other"]; + fn should_hide_param_name_hint( sema: &Semantics<'_, RootDatabase>, - callable: &hir::Callable, + unary_function: bool, + function_name: Option<&str>, param_name: &str, argument: &ast::Expr, ) -> bool { @@ -114,95 +129,128 @@ fn should_hide_param_name_hint( return true; } - if matches!(argument, ast::Expr::PrefixExpr(prefix) if prefix.op_kind() == Some(UnaryOp::Not)) { - return false; + if param_name.starts_with("ra_fixture") { + return true; } - let fn_name = match callable.kind() { - hir::CallableKind::Function(it) => Some(it.name(sema.db).as_str().to_smolstr()), - _ => None, - }; - let fn_name = fn_name.as_deref(); - is_param_name_suffix_of_fn_name(param_name, callable, fn_name) - || is_argument_expr_similar_to_param_name(argument, param_name) - || param_name.starts_with("ra_fixture") - || (callable.n_params() == 1 && is_obvious_param(param_name)) - || is_adt_constructor_similar_to_param_name(sema, argument, param_name) + if unary_function { + if let Some(function_name) = function_name { + if is_param_name_suffix_of_fn_name(param_name, function_name) { + return true; + } + } + if is_obvious_param(param_name) { + return true; + } + } + + is_argument_expr_similar_to_param_name(sema, argument, param_name) } /// Hide the parameter name of a unary function if it is a `_` - prefixed suffix of the function's name, or equal. /// /// `fn strip_suffix(suffix)` will be hidden. /// `fn stripsuffix(suffix)` will not be hidden. -fn is_param_name_suffix_of_fn_name( +fn is_param_name_suffix_of_fn_name(param_name: &str, fn_name: &str) -> bool { + fn_name == param_name + || fn_name + .len() + .checked_sub(param_name.len()) + .and_then(|at| fn_name.is_char_boundary(at).then(|| fn_name.split_at(at))) + .is_some_and(|(prefix, suffix)| { + suffix.eq_ignore_ascii_case(param_name) && prefix.ends_with('_') + }) +} + +fn is_argument_expr_similar_to_param_name( + sema: &Semantics<'_, RootDatabase>, + argument: &ast::Expr, param_name: &str, - callable: &Callable, - fn_name: Option<&str>, ) -> bool { - match (callable.n_params(), fn_name) { - (1, Some(function)) => { - function == param_name - || function - .len() - .checked_sub(param_name.len()) - .and_then(|at| function.is_char_boundary(at).then(|| function.split_at(at))) - .is_some_and(|(prefix, suffix)| { - suffix.eq_ignore_ascii_case(param_name) && prefix.ends_with('_') - }) + match get_segment_representation(argument) { + Some(Either::Left(argument)) => is_argument_similar_to_param_name(&argument, param_name), + Some(Either::Right(path)) => { + path.segment() + .and_then(|it| it.name_ref()) + .is_some_and(|name_ref| name_ref.text().eq_ignore_ascii_case(param_name)) + || is_adt_constructor_similar_to_param_name(sema, &path, param_name) } - _ => false, + None => false, } } -fn is_argument_expr_similar_to_param_name(argument: &ast::Expr, param_name: &str) -> bool { - let argument = match get_string_representation(argument) { - Some(argument) => argument, - None => return false, - }; - is_argument_similar_to_param_name(&argument, param_name) -} - /// Check whether param_name and argument are the same or /// whether param_name is a prefix/suffix of argument(split at `_`). -pub(super) fn is_argument_similar_to_param_name(argument: &str, param_name: &str) -> bool { - // std is honestly too panic happy... - let str_split_at = |str: &str, at| str.is_char_boundary(at).then(|| argument.split_at(at)); - - let param_name = param_name.trim_start_matches('_'); - let argument = argument.trim_start_matches('_'); - - match str_split_at(argument, param_name.len()) { - Some((prefix, rest)) if prefix.eq_ignore_ascii_case(param_name) => { - return rest.is_empty() || rest.starts_with('_'); - } - _ => (), - } - match argument.len().checked_sub(param_name.len()).and_then(|at| str_split_at(argument, at)) { - Some((rest, suffix)) if param_name.eq_ignore_ascii_case(suffix) => { - return rest.is_empty() || rest.ends_with('_'); - } - _ => (), - } - false +pub(super) fn is_argument_similar_to_param_name( + argument: &[ast::NameRef], + param_name: &str, +) -> bool { + debug_assert!(!argument.is_empty()); + debug_assert!(!param_name.is_empty()); + let param_name = param_name.split('_'); + let argument = argument.iter().flat_map(|it| it.text_non_mutable().split('_')); + + let prefix_match = zip(argument.clone(), param_name.clone()) + .all(|(arg, param)| arg.eq_ignore_ascii_case(param)); + let postfix_match = || { + zip(argument.rev(), param_name.rev()).all(|(arg, param)| arg.eq_ignore_ascii_case(param)) + }; + prefix_match || postfix_match() } -fn get_string_representation(expr: &ast::Expr) -> Option { +pub(super) fn get_segment_representation( + expr: &ast::Expr, +) -> Option, ast::Path>> { match expr { ast::Expr::MethodCallExpr(method_call_expr) => { + let receiver = + method_call_expr.receiver().and_then(|expr| get_segment_representation(&expr)); let name_ref = method_call_expr.name_ref()?; - match name_ref.text().as_str() { - "clone" | "as_ref" => method_call_expr.receiver().map(|rec| rec.to_string()), - name_ref => Some(name_ref.to_owned()), + if INSIGNIFICANT_METHOD_NAMES.contains(&name_ref.text().as_str()) { + return receiver; } + Some(Either::Left(match receiver { + Some(Either::Left(mut left)) => { + left.push(name_ref); + left + } + Some(Either::Right(_)) | None => vec![name_ref], + })) + } + ast::Expr::FieldExpr(field_expr) => { + let expr = field_expr.expr().and_then(|expr| get_segment_representation(&expr)); + let name_ref = field_expr.name_ref()?; + let res = match expr { + Some(Either::Left(mut left)) => { + left.push(name_ref); + left + } + Some(Either::Right(_)) | None => vec![name_ref], + }; + Some(Either::Left(res)) } - ast::Expr::MacroExpr(macro_expr) => { - Some(macro_expr.macro_call()?.path()?.segment()?.to_string()) + // paths + ast::Expr::MacroExpr(macro_expr) => macro_expr.macro_call()?.path().map(Either::Right), + ast::Expr::RecordExpr(record_expr) => record_expr.path().map(Either::Right), + ast::Expr::PathExpr(path_expr) => { + let path = path_expr.path()?; + // single segment paths are likely locals + Some(match path.as_single_name_ref() { + None => Either::Right(path), + Some(name_ref) => Either::Left(vec![name_ref]), + }) } - ast::Expr::FieldExpr(field_expr) => Some(field_expr.name_ref()?.to_string()), - ast::Expr::PathExpr(path_expr) => Some(path_expr.path()?.segment()?.to_string()), - ast::Expr::PrefixExpr(prefix_expr) => get_string_representation(&prefix_expr.expr()?), - ast::Expr::RefExpr(ref_expr) => get_string_representation(&ref_expr.expr()?), - ast::Expr::CastExpr(cast_expr) => get_string_representation(&cast_expr.expr()?), + ast::Expr::PrefixExpr(prefix_expr) if prefix_expr.op_kind() == Some(UnaryOp::Not) => None, + // recurse + ast::Expr::PrefixExpr(prefix_expr) => get_segment_representation(&prefix_expr.expr()?), + ast::Expr::RefExpr(ref_expr) => get_segment_representation(&ref_expr.expr()?), + ast::Expr::CastExpr(cast_expr) => get_segment_representation(&cast_expr.expr()?), + ast::Expr::CallExpr(call_expr) => get_segment_representation(&call_expr.expr()?), + ast::Expr::AwaitExpr(await_expr) => get_segment_representation(&await_expr.expr()?), + ast::Expr::IndexExpr(index_expr) => get_segment_representation(&index_expr.base()?), + ast::Expr::ParenExpr(paren_expr) => get_segment_representation(&paren_expr.expr()?), + ast::Expr::TryExpr(try_expr) => get_segment_representation(&try_expr.expr()?), + // ast::Expr::ClosureExpr(closure_expr) => todo!(), _ => None, } } @@ -210,30 +258,15 @@ fn get_string_representation(expr: &ast::Expr) -> Option { fn is_obvious_param(param_name: &str) -> bool { // avoid displaying hints for common functions like map, filter, etc. // or other obvious words used in std - let is_obvious_param_name = - matches!(param_name, "predicate" | "value" | "pat" | "rhs" | "other"); - param_name.len() == 1 || is_obvious_param_name + param_name.len() == 1 || INSIGNIFICANT_PARAMETER_NAMES.contains(¶m_name) } fn is_adt_constructor_similar_to_param_name( sema: &Semantics<'_, RootDatabase>, - argument: &ast::Expr, + path: &ast::Path, param_name: &str, ) -> bool { - let path = match argument { - ast::Expr::CallExpr(c) => c.expr().and_then(|e| match e { - ast::Expr::PathExpr(p) => p.path(), - _ => None, - }), - ast::Expr::PathExpr(p) => p.path(), - ast::Expr::RecordExpr(r) => r.path(), - _ => return false, - }; - let path = match path { - Some(it) => it, - None => return false, - }; - (|| match sema.resolve_path(&path)? { + (|| match sema.resolve_path(path)? { hir::PathResolution::Def(hir::ModuleDef::Adt(_)) => { Some(to_lower_snake_case(&path.segment()?.name_ref()?.text()) == param_name) } @@ -501,6 +534,7 @@ fn enum_matches_param_name(completion_kind: CompletionKind) {} fn foo(param: u32) {} fn bar(param_eter: u32) {} +fn baz(a_d_e: u32) {} enum CompletionKind { Keyword, @@ -553,6 +587,14 @@ fn main() { //^^^^^^^^^^^ param_eter non_ident_pat((0, 0)); + + baz(a.d.e); + baz(a.dc.e); + // ^^^^^^ a_d_e + baz(ac.d.e); + // ^^^^^^ a_d_e + baz(a.d.ec); + // ^^^^^^ a_d_e }"#, ); } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs index a5ac59dd7d7b4..b9ccd34cff064 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs @@ -36,6 +36,16 @@ impl ast::NameRef { pub fn text(&self) -> TokenText<'_> { text_of_first_token(self.syntax()) } + pub fn text_non_mutable(&self) -> &str { + fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData { + green_ref.children().next().and_then(NodeOrToken::into_token).unwrap() + } + + match self.syntax().green() { + Cow::Borrowed(green_ref) => first_token(green_ref).text(), + Cow::Owned(_) => unreachable!(), + } + } pub fn as_tuple_field(&self) -> Option { self.text().parse().ok() 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 0400/2248] 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 0401/2248] 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 0402/2248] 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 0403/2248] 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 0404/2248] 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 0405/2248] 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 76034a648d63f88d00e3b24f369ba356c6e52282 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 31 Mar 2025 11:51:06 +0200 Subject: [PATCH 0406/2248] do not run EnvVars::cleanup if there was an interpreter error --- src/tools/miri/src/eval.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index ed13f670a90e3..7586b5efd4b2b 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -459,8 +459,13 @@ pub fn eval_entry<'tcx>( ecx.handle_ice(); panic::resume_unwind(panic_payload) }); - // `Ok` can never happen. + // `Ok` can never happen; the interpreter loop always exits with an "error" + // (but that "error" might be just "regular program termination"). let Err(err) = res.report_err(); + // Show diagnostic, if any. + let (return_code, leak_check) = report_error(&ecx, err)?; + + // If we get here there was no fatal error. // Machine cleanup. Only do this if all threads have terminated; threads that are still running // might cause Stacked Borrows errors (https://github.com/rust-lang/miri/issues/2396). @@ -472,8 +477,7 @@ pub fn eval_entry<'tcx>( EnvVars::cleanup(&mut ecx).expect("error during env var cleanup"); } - // Process the result. - let (return_code, leak_check) = report_error(&ecx, err)?; + // Possibly check for memory leaks. if leak_check && !ignore_leaks { // Check for thread leaks. if !ecx.have_all_terminated() { From 53f4397bd9c6b83936725fcf8d640be231c6facd Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 31 Mar 2025 11:01:46 +0100 Subject: [PATCH 0407/2248] 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 ed75e2a79a752386099be07a21aabab0e8724945 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 31 Mar 2025 13:26:52 +0200 Subject: [PATCH 0408/2248] fix: Fix new nightly lints --- .../crates/hir-def/src/expr_store/lower.rs | 3 +- .../crates/hir-def/src/generics.rs | 20 ++++++++----- .../crates/hir-expand/src/attrs.rs | 5 ++-- .../hir-expand/src/builtin/derive_macro.rs | 6 ++-- .../crates/hir-ty/src/chalk_db.rs | 29 +++++++++---------- .../hir-ty/src/diagnostics/match_check.rs | 5 ++-- .../rust-analyzer/crates/hir-ty/src/drop.rs | 4 +-- .../crates/hir-ty/src/dyn_compatibility.rs | 4 +-- .../hir-ty/src/dyn_compatibility/tests.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/infer.rs | 2 +- .../crates/hir-ty/src/infer/closure.rs | 11 ++++--- .../crates/hir-ty/src/infer/expr.rs | 6 ++-- .../crates/hir-ty/src/infer/unify.rs | 6 ++-- .../rust-analyzer/crates/hir-ty/src/lib.rs | 2 +- .../crates/hir-ty/src/method_resolution.rs | 12 ++++---- .../crates/hir-ty/src/mir/lower.rs | 10 ++++--- src/tools/rust-analyzer/crates/hir/src/lib.rs | 6 ++-- .../extract_expressions_from_format_string.rs | 6 ++-- .../ide-completion/src/render/pattern.rs | 6 ++-- .../crates/ide-ssr/src/matching.rs | 6 ++-- .../crates/ide/src/goto_type_definition.rs | 5 ++-- .../ide/src/syntax_highlighting/highlight.rs | 6 ++-- .../crates/proc-macro-api/src/process.rs | 5 ++-- .../crates/rust-analyzer/src/command.rs | 9 ++---- src/tools/rust-analyzer/crates/tt/src/lib.rs | 6 ++-- .../rust-analyzer/lib/lsp-server/src/stdio.rs | 2 +- 26 files changed, 88 insertions(+), 96 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 8059023f0bb89..c56b85715613a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -1360,8 +1360,7 @@ impl ExprCollector<'_> { else { panic!("just expanded a macro, ExpansionSpanMap should be available"); }; - let old_span_map = - mem::replace(&mut self.current_span_map, Some(new_span_map.clone())); + let old_span_map = self.current_span_map.replace(new_span_map.clone()); let id = collector(self, Some(expansion.tree())); self.current_span_map = old_span_map; self.ast_id_map = prev_ast_id_map; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs index 58ac86e8a6050..71fb253c87243 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs @@ -329,26 +329,30 @@ impl GenericParams { params.clone() } else { Arc::new(GenericParams { - type_or_consts: all_type_or_consts_enabled - .then(|| params.type_or_consts.clone()) - .unwrap_or_else(|| { + type_or_consts: if all_type_or_consts_enabled { + params.type_or_consts.clone() + } else { + { params .type_or_consts .iter() .filter(|&(idx, _)| enabled(attr_owner_ct(idx))) .map(|(_, param)| param.clone()) .collect() - }), - lifetimes: all_lifetimes_enabled - .then(|| params.lifetimes.clone()) - .unwrap_or_else(|| { + } + }, + lifetimes: if all_lifetimes_enabled { + params.lifetimes.clone() + } else { + { params .lifetimes .iter() .filter(|&(idx, _)| enabled(attr_owner_lt(idx))) .map(|(_, param)| param.clone()) .collect() - }), + } + }, where_predicates: params.where_predicates.clone(), types_map: params.types_map.clone(), }) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index 862e3c7305f5d..433199746bfa6 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -305,13 +305,12 @@ impl Attr { Some(Box::new(AttrInput::TokenTree(tt::TopSubtree::from_subtree(tree)))) } (Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. }))), _) => { - let input = match input.flat_tokens().get(1) { + match input.flat_tokens().get(1) { Some(tt::TokenTree::Leaf(tt::Leaf::Literal(lit))) => { Some(Box::new(AttrInput::Literal(lit.clone()))) } _ => None, - }; - input + } } _ => None, }; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs index 2ad8cd8377d54..428bed89b5155 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs @@ -1314,15 +1314,15 @@ fn coerce_pointee_expand( } }) }); - let self_for_traits = make::path_from_segments( + + make::path_from_segments( [make::generic_ty_path_segment( make::name_ref(&struct_name.text()), self_params_for_traits, )], false, ) - .clone_for_update(); - self_for_traits + .clone_for_update() }; let mut span_map = span::SpanMap::empty(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index e0975b5aeb40b..a2583b1f5a993 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -144,22 +144,21 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db); let mut result = vec![]; - if fps.is_empty() { - debug!("Unrestricted search for {:?} impls...", trait_); - self.for_trait_impls(trait_, self_ty_fp, |impls| { - result.extend(impls.for_trait(trait_).map(id_to_chalk)); - ControlFlow::Continue(()) - }) - } else { - self.for_trait_impls(trait_, self_ty_fp, |impls| { - result.extend( - fps.iter().flat_map(move |fp| { + _ = + if fps.is_empty() { + debug!("Unrestricted search for {:?} impls...", trait_); + self.for_trait_impls(trait_, self_ty_fp, |impls| { + result.extend(impls.for_trait(trait_).map(id_to_chalk)); + ControlFlow::Continue(()) + }) + } else { + self.for_trait_impls(trait_, self_ty_fp, |impls| { + result.extend(fps.iter().flat_map(move |fp| { impls.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk) - }), - ); - ControlFlow::Continue(()) - }) - }; + })); + ControlFlow::Continue(()) + }) + }; debug!("impls_for_trait returned {} impls", result.len()); result diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs index 1c58485eb97fc..3542f9b74de7e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs @@ -242,7 +242,7 @@ impl<'a> PatCtxt<'a> { ty: &Ty, subpatterns: Vec, ) -> PatKind { - let kind = match self.infer.variant_resolution_for_pat(pat) { + match self.infer.variant_resolution_for_pat(pat) { Some(variant_id) => { if let VariantId::EnumVariantId(enum_variant) = variant_id { let substs = match ty.kind(Interner) { @@ -266,8 +266,7 @@ impl<'a> PatCtxt<'a> { self.errors.push(PatternError::UnresolvedVariant); PatKind::Wild } - }; - kind + } } fn lower_path(&mut self, pat: PatId, _path: &hir_def::path::Path) -> Pat { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs index 5484a39324f93..6bfd9e9f398fe 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs @@ -32,8 +32,8 @@ fn has_destructor(db: &dyn HirDatabase, adt: AdtId) -> bool { }, None => db.trait_impls_in_crate(module.krate()), }; - let result = impls.for_trait_and_self_ty(drop_trait, TyFingerprint::Adt(adt)).next().is_some(); - result + + impls.for_trait_and_self_ty(drop_trait, TyFingerprint::Adt(adt)).next().is_some() } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs index cb186c45ad00e..8d1251e01350e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs @@ -115,7 +115,7 @@ pub fn dyn_compatibility_of_trait_query( trait_: TraitId, ) -> Option { let mut res = None; - dyn_compatibility_of_trait_with_callback(db, trait_, &mut |osv| { + _ = dyn_compatibility_of_trait_with_callback(db, trait_, &mut |osv| { res = Some(osv); ControlFlow::Break(()) }); @@ -592,7 +592,7 @@ fn contains_illegal_impl_trait_in_trait( let ret = sig.skip_binders().ret(); let mut visitor = OpaqueTypeCollector(FxHashSet::default()); - ret.visit_with(visitor.as_dyn(), DebruijnIndex::INNERMOST); + _ = ret.visit_with(visitor.as_dyn(), DebruijnIndex::INNERMOST); // Since we haven't implemented RPITIT in proper way like rustc yet, // just check whether `ret` contains RPIT for now diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs index 3060b610bb694..618fc73770d68 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs @@ -53,7 +53,7 @@ fn check_dyn_compatibility<'a>( continue; }; let mut osvs = FxHashSet::default(); - dyn_compatibility_with_callback(&db, trait_id, &mut |osv| { + _ = dyn_compatibility_with_callback(&db, trait_id, &mut |osv| { osvs.insert(match osv { DynCompatibilityViolation::SizedSelf => SizedSelf, DynCompatibilityViolation::SelfReferential => SelfReferential, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 7388d2ab43cc7..0bd605c18b4ad 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -1143,7 +1143,7 @@ impl<'a> InferenceContext<'a> { non_assocs: FxHashMap::default(), }; for ty in tait_candidates { - ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST); + _ = ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST); } // Non-assoc TAITs can be define-used everywhere as long as they are diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index 731b7f5e0286f..b18e0271bf09d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -517,10 +517,9 @@ impl InferenceContext<'_> { return None; } let hygiene = self.body.expr_or_pat_path_hygiene(id); - let result = self - .resolver - .resolve_path_in_value_ns_fully(self.db.upcast(), path, hygiene) - .and_then(|result| match result { + + self.resolver.resolve_path_in_value_ns_fully(self.db.upcast(), path, hygiene).and_then( + |result| match result { ValueNs::LocalBinding(binding) => { let mir_span = match id { ExprOrPatId::ExprId(id) => MirSpan::ExprId(id), @@ -530,8 +529,8 @@ impl InferenceContext<'_> { Some(HirPlace { local: binding, projections: Vec::new() }) } _ => None, - }); - result + }, + ) } /// Changes `current_capture_span_stack` to contain the stack of spans for this expr. diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 238cbe2b05ded..815a3d1459b87 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -472,8 +472,7 @@ impl InferenceContext<'_> { let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let prev_closure = mem::replace(&mut self.current_closure, id); let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); - let prev_ret_coercion = - mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty))); + let prev_ret_coercion = self.return_coercion.replace(CoerceMany::new(ret_ty)); let prev_resume_yield_tys = mem::replace(&mut self.resume_yield_tys, resume_yield_tys); @@ -1168,8 +1167,7 @@ impl InferenceContext<'_> { let ret_ty = self.table.new_type_var(); let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); - let prev_ret_coercion = - mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty.clone()))); + let prev_ret_coercion = self.return_coercion.replace(CoerceMany::new(ret_ty.clone())); // FIXME: We should handle async blocks like we handle closures let expected = &Expectation::has_type(ret_ty); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 903097ee2f8f7..fe9f76e5bcbd2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -1027,7 +1027,8 @@ mod resolve { .assert_ty_ref(Interner) .clone(); } - let result = if let Some(known_ty) = self.table.var_unification_table.probe_var(var) { + + if let Some(known_ty) = self.table.var_unification_table.probe_var(var) { // known_ty may contain other variables that are known by now self.var_stack.push(var); let result = known_ty.fold_with(self, outer_binder); @@ -1038,8 +1039,7 @@ mod resolve { (self.fallback)(var, VariableKind::Ty(kind), default, outer_binder) .assert_ty_ref(Interner) .clone() - }; - result + } } fn fold_inference_const( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 8292e80c1e197..7ca32c7e6b24f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -1013,7 +1013,7 @@ where T: ?Sized + TypeVisitable, { let mut collector = PlaceholderCollector { db, placeholders: FxHashSet::default() }; - value.visit_with(&mut collector, DebruijnIndex::INNERMOST); + _ = value.visit_with(&mut collector, DebruijnIndex::INNERMOST); collector.placeholders.into_iter().collect() } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index d7c2f0009ceee..1076bc22c358c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -585,7 +585,7 @@ pub(crate) fn iterate_method_candidates( mut callback: impl FnMut(ReceiverAdjustments, AssocItemId, bool) -> Option, ) -> Option { let mut slot = None; - iterate_method_candidates_dyn( + _ = iterate_method_candidates_dyn( ty, db, env, @@ -898,7 +898,10 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool { } }; // - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type. - let is_not_orphan = trait_ref.substitution.type_parameters(Interner).any(|ty| { + + // FIXME: param coverage + // - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti`` (excluding `Ti`) + trait_ref.substitution.type_parameters(Interner).any(|ty| { match unwrap_fundamental(ty).kind(Interner) { &TyKind::Adt(AdtId(id), _) => is_local(id.module(db.upcast()).krate()), TyKind::Error => true, @@ -907,10 +910,7 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool { }), _ => false, } - }); - // FIXME: param coverage - // - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti`` (excluding `Ti`) - is_not_orphan + }) } pub fn iterate_path_candidates( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 95c93b5f3edd8..43d04b68233a8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -1635,10 +1635,12 @@ impl<'ctx> MirLowerCtx<'ctx> { f: impl FnOnce(&mut MirLowerCtx<'_>, BasicBlockId) -> Result<()>, ) -> Result> { let begin = self.new_basic_block(); - let prev = mem::replace( - &mut self.current_loop_blocks, - Some(LoopBlocks { begin, end: None, place, drop_scope_index: self.drop_scopes.len() }), - ); + let prev = self.current_loop_blocks.replace(LoopBlocks { + begin, + end: None, + place, + drop_scope_index: self.drop_scopes.len(), + }); let prev_label = if let Some(label) = label { // We should generate the end now, to make sure that it wouldn't change later. It is // bad as we may emit end (unnecessary unreachable block) for unterminating loop, but diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 7f0382fa93f48..870967e84aa26 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -294,15 +294,13 @@ impl Crate { } fn core(db: &dyn HirDatabase) -> Option { - let result = db - .all_crates() + db.all_crates() .iter() .copied() .find(|&krate| { matches!(krate.data(db).origin, CrateOrigin::Lang(LangCrateOrigin::Core)) }) - .map(Crate::from); - result + .map(Crate::from) } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs index 1212bb770bb1b..54699a9454f09 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs @@ -79,11 +79,11 @@ pub(crate) fn extract_expressions_from_format_string( Some((NodeOrToken::Token(t), rest)) if t.kind() == WHITESPACE => rest, _ => arg, }; - let arg = match arg.split_last() { + + match arg.split_last() { Some((NodeOrToken::Token(t), rest)) if t.kind() == WHITESPACE => rest, _ => arg, - }; - arg + } }); args.collect() diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs index 93e6c5237948f..8332cd0bcb831 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs @@ -64,11 +64,11 @@ pub(crate) fn render_variant_pat( ), None => { let name = local_name.unwrap_or_else(|| variant.name(ctx.db())); - let it = ( + + ( name.as_str().to_smolstr(), name.display(ctx.db(), ctx.completion.edition).to_smolstr(), - ); - it + ) } }; diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs index 0776b8bc5e43a..84a5943b1ce23 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs @@ -629,7 +629,8 @@ impl<'db, 'sema> Matcher<'db, 'sema> { let krate = self.sema.scope(expr.syntax()).map(|it| it.krate()).unwrap_or_else(|| { hir::Crate::from(*self.sema.db.all_crates().last().expect("no crate graph present")) }); - let res = code_type + + code_type .autoderef(self.sema.db) .enumerate() .find(|(_, deref_code_type)| pattern_type == deref_code_type) @@ -642,8 +643,7 @@ impl<'db, 'sema> Matcher<'db, 'sema> { pattern_type.display(self.sema.db, display_target), code_type.display(self.sema.db, display_target) ) - }); - res + }) } fn get_placeholder_for_node(&self, node: &SyntaxNode) -> Option<&Placeholder> { diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs index bf48a6e23227e..a3d1679cd3748 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs @@ -71,7 +71,7 @@ pub(crate) fn goto_type_definition( sema.descend_into_macros_no_opaque(token) .into_iter() .filter_map(|token| { - let ty = sema + sema .token_ancestors_with_macros(token) // When `token` is within a macro call, we can't determine its type. Don't continue // this traversal because otherwise we'll end up returning the type of *that* macro @@ -103,8 +103,7 @@ pub(crate) fn goto_type_definition( }; Some(ty) - }); - ty + }) }) .for_each(process_ty); Some(RangeInfo::new(range, res)) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index 6f518190c6e47..5914a8f79940a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -113,7 +113,8 @@ fn punctuation( ) -> Highlight { let operator_parent = token.parent(); let parent_kind = operator_parent.as_ref().map_or(EOF, SyntaxNode::kind); - let h = match (kind, parent_kind) { + + match (kind, parent_kind) { (T![?], TRY_EXPR) => HlTag::Operator(HlOperator::Other) | HlMod::ControlFlow, (T![&], BIN_EXPR) => HlOperator::Bitwise.into(), (T![&], REF_EXPR | REF_PAT) => HlTag::Operator(HlOperator::Other).into(), @@ -240,8 +241,7 @@ fn punctuation( _ => HlPunct::Other, } .into(), - }; - h + } } fn keyword(token: SyntaxToken, kind: SyntaxKind) -> Highlight { diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs index 7be6686b7337a..27bf751bde81c 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs @@ -62,8 +62,7 @@ impl ProcMacroServerProcess { let mut srv = create_srv()?; tracing::info!("sending proc-macro server version check"); match srv.version_check() { - Ok(v) if v > CURRENT_API_VERSION => Err(io::Error::new( - io::ErrorKind::Other, + Ok(v) if v > CURRENT_API_VERSION => Err(io::Error::other( format!( "The version of the proc-macro server ({v}) in your Rust toolchain is newer than the version supported by your rust-analyzer ({CURRENT_API_VERSION}). This will prevent proc-macro expansion from working. Please consider updating your rust-analyzer to ensure compatibility with your current toolchain." ), @@ -82,7 +81,7 @@ impl ProcMacroServerProcess { Err(e) => { tracing::info!(%e, "proc-macro version check failed"); Err( - io::Error::new(io::ErrorKind::Other, format!("proc-macro server version check failed: {e}")), + io::Error::other(format!("proc-macro server version check failed: {e}")), ) } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs index 81a20eeed703d..0035d941e2c60 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs @@ -166,12 +166,9 @@ impl CommandHandle { if read_at_least_one_message || exit_status.success() { Ok(()) } else { - Err(io::Error::new( - io::ErrorKind::Other, - format!( - "Cargo watcher failed, the command produced no valid metadata (exit code: {exit_status:?}):\n{error}" - ), - )) + Err(io::Error::other(format!( + "Cargo watcher failed, the command produced no valid metadata (exit code: {exit_status:?}):\n{error}" + ))) } } } diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs index 1cfead54f192d..916e00b73bad0 100644 --- a/src/tools/rust-analyzer/crates/tt/src/lib.rs +++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs @@ -363,7 +363,8 @@ impl<'a, S: Copy> TokenTreesView<'a, S> { ) -> impl Iterator> { let mut subtree_iter = self.iter(); let mut need_to_yield_even_if_empty = true; - let result = std::iter::from_fn(move || { + + std::iter::from_fn(move || { if subtree_iter.is_empty() && !need_to_yield_even_if_empty { return None; }; @@ -379,8 +380,7 @@ impl<'a, S: Copy> TokenTreesView<'a, S> { result = subtree_iter.from_savepoint(savepoint); } Some(result) - }); - result + }) } } diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs index 4ca432d1022d3..c558b6c6e7708 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs +++ b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs @@ -40,7 +40,7 @@ pub(crate) fn stdio_transport() -> (Sender, Receiver, IoThread debug!("sending message {:#?}", msg); if let Err(e) = reader_sender.send(msg) { - return Err(io::Error::new(io::ErrorKind::Other, e)); + return Err(io::Error::other(e)); } if is_exit { From 73a3d4ac137d09be94ea954925a8c96db4abd856 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 31 Mar 2025 14:20:14 +0200 Subject: [PATCH 0409/2248] chore: Clean CI a bit --- .../rust-analyzer/.github/workflows/ci.yaml | 80 ++++++++++++------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index 0e023bfe91b12..30ba633e02b51 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -34,7 +34,6 @@ jobs: - 'editors/code/**' proc-macro-srv: - needs: changes if: github.repository == 'rust-lang/rust-analyzer' name: proc-macro-srv runs-on: ubuntu-latest @@ -72,7 +71,7 @@ jobs: name: Rust runs-on: ${{ matrix.os }} env: - RUSTFLAGS: "-D warnings" + RUSTFLAGS: "-Dwarnings" CC: deny_c strategy: @@ -89,7 +88,7 @@ jobs: run: | rustup update --no-self-update stable rustup default stable - rustup component add --toolchain stable rust-src + rustup component add --toolchain stable rust-src clippy # We always use a nightly rustfmt, regardless of channel, because we need # --file-lines. rustup toolchain install nightly --profile minimal --component rustfmt @@ -98,24 +97,24 @@ jobs: if: matrix.os == 'ubuntu-latest' run: echo "::add-matcher::.github/rust.json" + - name: Bump opt-level + if: matrix.os == 'ubuntu-latest' + run: sed -i '/\[profile.dev]/a opt-level=1' Cargo.toml + - name: Cache Dependencies - uses: Swatinem/rust-cache@27b8ea9368cf428f0bfe41b0876b1a7e809d9844 + uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 with: workspaces: | . -> target - crates/proc-macro-srv/proc-macro-test/imp -> target + ./crates/proc-macro-srv/proc-macro-test/imp -> target - uses: taiki-e/install-action@nextest - - name: Bump opt-level - if: matrix.os == 'ubuntu-latest' - run: sed -i '/\[profile.dev]/a opt-level=1' Cargo.toml - - name: Codegen checks (rust-analyzer) run: cargo codegen --check - name: Compile (tests) - run: cargo test --no-run --locked + run: cargo test --no-run # It's faster to `test` before `build` ¯\_(ツ)_/¯ - name: Compile (rust-analyzer) @@ -126,31 +125,53 @@ jobs: if: matrix.os == 'ubuntu-latest' || matrix.os == 'windows-latest' || github.event_name == 'push' run: cargo nextest run --no-fail-fast --hide-progress-bar --status-level fail - - name: Switch to stable toolchain + - name: clippy + if: matrix.os == 'macos-latest' + run: cargo clippy --all-targets -- -D clippy::disallowed_macros -D clippy::dbg_macro -D clippy::todo -D clippy::print_stdout -D clippy::print_stderr + + analysis-stats: + if: github.repository == 'rust-lang/rust-analyzer' + name: miri + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Rust toolchain run: | rustup update --no-self-update stable - rustup component add --toolchain stable rust-src clippy rustup default stable + rustup component add rustfmt - - name: Run analysis-stats on rust-analyzer - if: matrix.os == 'ubuntu-latest' - run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats . + - name: Cache Dependencies + uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 - - name: Run analysis-stats on the rust standard libraries - if: matrix.os == 'ubuntu-latest' + - name: ./rust-analyzer + run: cargo run -p rust-analyzer -- analysis-stats . -q + + - name: sysroot/lib/rustlib/src/rust/library/ env: RUSTC_BOOTSTRAP: 1 - run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats --with-deps --no-sysroot --no-test $(rustc --print sysroot)/lib/rustlib/src/rust/library/ + run: cargo run -p rust-analyzer -- analysis-stats --with-deps --no-sysroot --no-test $(rustc --print sysroot)/lib/rustlib/src/rust/library/ -q - - name: clippy - if: matrix.os == 'macos-latest' - run: cargo clippy --all-targets -- -D clippy::disallowed_macros -D clippy::dbg_macro -D clippy::todo -D clippy::print_stdout -D clippy::print_stderr + rustfmt: + if: github.repository == 'rust-lang/rust-analyzer' + name: miri + runs-on: ubuntu-latest - - name: rustfmt - if: matrix.os == 'ubuntu-latest' - run: cargo fmt -- --check + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Rust toolchain + run: | + rustup update --no-self-update stable + rustup default stable + rustup component add rustfmt + + - run: cargo fmt -- --check - # Weird targets to catch non-portable code miri: if: github.repository == 'rust-lang/rust-analyzer' name: miri @@ -163,12 +184,13 @@ jobs: - name: Install Rust toolchain run: | rustup update --no-self-update nightly - rustup component add miri --toolchain nightly + rustup default nightly + rustup component add miri - name: Cache Dependencies - uses: Swatinem/rust-cache@9bdad043e88c75890e36ad3bbc8d27f0090dd609 + uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 - - run: cargo +nightly miri test -p intern --locked + - run: cargo miri test -p intern # Weird targets to catch non-portable code rust-cross: @@ -193,7 +215,7 @@ jobs: rustup target add ${{ env.targets }} ${{ env.targets_ide }} - name: Cache Dependencies - uses: Swatinem/rust-cache@9bdad043e88c75890e36ad3bbc8d27f0090dd609 + uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 - name: Check run: | From 9172556de8db2ea7041073215936ba27b3395622 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Mon, 31 Mar 2025 12:39:41 +0000 Subject: [PATCH 0410/2248] Suggest `./x test src/tools/clippy --bless` when in `rust-lang/rust` --- tests/compile-test.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 956a05288f358..24dc5c545ef73 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -147,7 +147,11 @@ impl TestContext { .map(|filters| filters.split(',').map(str::to_string).collect()) .unwrap_or_default(), target: None, - bless_command: Some("cargo uibless".into()), + bless_command: Some(if IS_RUSTC_TEST_SUITE { + "./x test src/tools/clippy --bless".into() + } else { + "cargo uibless".into() + }), out_dir: target_dir.join("ui_test"), ..Config::rustc(Path::new("tests").join(test_dir)) }; From 54bb849affcbede09ab1327c6cd996e5c5948cdd Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 28 Mar 2025 22:31:20 +0300 Subject: [PATCH 0411/2248] hygiene: Rename semi-transparent to semi-opaque The former is just too long, see the examples in `hygiene.rs` --- .../src/attributes/transparency.rs | 2 +- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 6 +-- compiler/rustc_span/src/hygiene.rs | 47 +++++++++---------- compiler/rustc_span/src/lib.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + tests/ui/hygiene/rustc-macro-transparency.rs | 12 ++--- .../hygiene/rustc-macro-transparency.stderr | 12 ++--- tests/ui/hygiene/unpretty-debug.stdout | 2 +- tests/ui/proc-macro/meta-macro-hygiene.stdout | 6 +-- .../nonterminal-token-hygiene.stdout | 4 +- 11 files changed, 48 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index ad83a1f7af80c..ce42b0507ed57 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -20,7 +20,7 @@ impl SingleAttributeParser for TransparencyParser { fn convert(cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option { match args.name_value().and_then(|nv| nv.value_as_str()) { Some(sym::transparent) => Some(Transparency::Transparent), - Some(sym::semitransparent) => Some(Transparency::SemiTransparent), + Some(sym::semiopaque | sym::semitransparent) => Some(Transparency::SemiOpaque), Some(sym::opaque) => Some(Transparency::Opaque), Some(other) => { cx.dcx().span_err(cx.attr_span, format!("unknown macro transparency: `{other}`")); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 1e33e2e9393f7..a8f0da736c637 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -752,7 +752,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), rustc_attr!( rustc_macro_transparency, Normal, - template!(NameValueStr: "transparent|semitransparent|opaque"), ErrorFollowing, + template!(NameValueStr: "transparent|semiopaque|opaque"), ErrorFollowing, EncodeCrossCrate::Yes, "used internally for testing macro hygiene", ), rustc_attr!( diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 612e091770f0a..1eac3f848b622 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1998,16 +1998,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { result, result.map(|r| r.expn_data()) ); - // Then find the last semi-transparent mark from the end if it exists. + // Then find the last semi-opaque mark from the end if it exists. for (mark, transparency) in iter { - if transparency == Transparency::SemiTransparent { + if transparency == Transparency::SemiOpaque { result = Some(mark); } else { break; } } debug!( - "resolve_crate_root: found semi-transparent mark {:?} {:?}", + "resolve_crate_root: found semi-opaque mark {:?} {:?}", result, result.map(|r| r.expn_data()) ); diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index e7a8dee27f568..c2e7cb4577553 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -66,10 +66,10 @@ pub struct SyntaxContextData { outer_expn: ExpnId, outer_transparency: Transparency, parent: SyntaxContext, - /// This context, but with all transparent and semi-transparent expansions filtered away. + /// This context, but with all transparent and semi-opaque expansions filtered away. opaque: SyntaxContext, /// This context, but with all transparent expansions filtered away. - opaque_and_semitransparent: SyntaxContext, + opaque_and_semiopaque: SyntaxContext, /// Name of the crate to which `$crate` with this context would resolve. dollar_crate_name: Symbol, } @@ -78,14 +78,14 @@ impl SyntaxContextData { fn new( (parent, outer_expn, outer_transparency): SyntaxContextKey, opaque: SyntaxContext, - opaque_and_semitransparent: SyntaxContext, + opaque_and_semiopaque: SyntaxContext, ) -> SyntaxContextData { SyntaxContextData { outer_expn, outer_transparency, parent, opaque, - opaque_and_semitransparent, + opaque_and_semiopaque, dollar_crate_name: kw::DollarCrate, } } @@ -96,7 +96,7 @@ impl SyntaxContextData { outer_transparency: Transparency::Opaque, parent: SyntaxContext::root(), opaque: SyntaxContext::root(), - opaque_and_semitransparent: SyntaxContext::root(), + opaque_and_semiopaque: SyntaxContext::root(), dollar_crate_name: kw::DollarCrate, } } @@ -207,13 +207,13 @@ pub enum Transparency { /// Identifier produced by a transparent expansion is always resolved at call-site. /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this. Transparent, - /// Identifier produced by a semi-transparent expansion may be resolved + /// Identifier produced by a semi-opaque expansion may be resolved /// either at call-site or at definition-site. /// If it's a local variable, label or `$crate` then it's resolved at def-site. /// Otherwise it's resolved at call-site. /// `macro_rules` macros behave like this, built-in macros currently behave like this too, /// but that's an implementation detail. - SemiTransparent, + SemiOpaque, /// Identifier produced by an opaque expansion is always resolved at definition-site. /// Def-site spans in procedural macros, identifiers from `macro` by default use this. Opaque, @@ -221,7 +221,7 @@ pub enum Transparency { impl Transparency { pub fn fallback(macro_rules: bool) -> Self { - if macro_rules { Transparency::SemiTransparent } else { Transparency::Opaque } + if macro_rules { Transparency::SemiOpaque } else { Transparency::Opaque } } } @@ -469,7 +469,7 @@ impl HygieneData { fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext { debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); - self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent + self.syntax_context_data[ctxt.0 as usize].opaque_and_semiopaque } fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId { @@ -562,7 +562,7 @@ impl HygieneData { } let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt(); - let mut call_site_ctxt = if transparency == Transparency::SemiTransparent { + let mut call_site_ctxt = if transparency == Transparency::SemiOpaque { self.normalize_to_macros_2_0(call_site_ctxt) } else { self.normalize_to_macro_rules(call_site_ctxt) @@ -608,33 +608,32 @@ impl HygieneData { 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 + // Opaque and semi-opaque 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. + // and `parent_opaque_and_semiopaque` == `parent` if the expn contains only (semi-)opaques. 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; + let parent_opaque_and_semiopaque = + self.syntax_context_data[parent.0 as usize].opaque_and_semiopaque; - // 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 => ( + // Evaluate opaque and semi-opaque versions of the new syntax context. + let (opaque, opaque_and_semiopaque) = match transparency { + Transparency::Transparent => (parent_opaque, parent_opaque_and_semiopaque), + Transparency::SemiOpaque => ( 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), + // Will be the same as `ctxt` if the expn chain contains only (semi-)opaques. + self.alloc_ctxt(parent_opaque_and_semiopaque, 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), + // Will be the same as `ctxt` if the expn chain contains only (semi-)opaques. + self.alloc_ctxt(parent_opaque_and_semiopaque, 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); + SyntaxContextData::new(key, opaque, opaque_and_semiopaque); ctxt } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 9e6ba2e1b9ce2..625ece787b909 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1112,7 +1112,7 @@ impl Span { /// Equivalent of `Span::mixed_site` from the proc macro API, /// except that the location is taken from the `self` span. pub fn with_mixed_site_ctxt(self, expn_id: ExpnId) -> Span { - self.with_ctxt_from_mark(expn_id, Transparency::SemiTransparent) + self.with_ctxt_from_mark(expn_id, Transparency::SemiOpaque) } /// Produces a span with the same location as `self` and context produced by a macro with the diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 47dd80c432ead..02f89c527e637 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1871,6 +1871,7 @@ symbols! { select_unpredictable, self_in_typedefs, self_struct_ctor, + semiopaque, semitransparent, sha2, sha3, diff --git a/tests/ui/hygiene/rustc-macro-transparency.rs b/tests/ui/hygiene/rustc-macro-transparency.rs index 5f36993af2f30..1a78a7543cfdc 100644 --- a/tests/ui/hygiene/rustc-macro-transparency.rs +++ b/tests/ui/hygiene/rustc-macro-transparency.rs @@ -6,9 +6,9 @@ macro transparent() { let transparent = 0; } #[rustc_macro_transparency = "semitransparent"] -macro semitransparent() { - struct SemiTransparent; - let semitransparent = 0; +macro semiopaque() { + struct SemiOpaque; + let semiopaque = 0; } #[rustc_macro_transparency = "opaque"] macro opaque() { @@ -18,14 +18,14 @@ macro opaque() { fn main() { transparent!(); - semitransparent!(); + semiopaque!(); opaque!(); Transparent; // OK - SemiTransparent; // OK + SemiOpaque; // OK Opaque; //~ ERROR cannot find value `Opaque` in this scope transparent; // OK - semitransparent; //~ ERROR expected value, found macro `semitransparent` + semiopaque; //~ ERROR expected value, found macro `semiopaque` opaque; //~ ERROR expected value, found macro `opaque` } diff --git a/tests/ui/hygiene/rustc-macro-transparency.stderr b/tests/ui/hygiene/rustc-macro-transparency.stderr index 1d2a1e1249864..1bea8a0ee4f31 100644 --- a/tests/ui/hygiene/rustc-macro-transparency.stderr +++ b/tests/ui/hygiene/rustc-macro-transparency.stderr @@ -4,17 +4,17 @@ error[E0425]: cannot find value `Opaque` in this scope LL | Opaque; | ^^^^^^ not found in this scope -error[E0423]: expected value, found macro `semitransparent` +error[E0423]: expected value, found macro `semiopaque` --> $DIR/rustc-macro-transparency.rs:29:5 | -LL | struct SemiTransparent; - | ----------------------- similarly named unit struct `SemiTransparent` defined here +LL | struct SemiOpaque; + | ------------------ similarly named unit struct `SemiOpaque` defined here ... -LL | semitransparent; - | ^^^^^^^^^^^^^^^ +LL | semiopaque; + | ^^^^^^^^^^ | | | not a value - | help: a unit struct with a similar name exists: `SemiTransparent` + | help: a unit struct with a similar name exists (notice the capitalization): `SemiOpaque` error[E0423]: expected value, found macro `opaque` --> $DIR/rustc-macro-transparency.rs:30:5 diff --git a/tests/ui/hygiene/unpretty-debug.stdout b/tests/ui/hygiene/unpretty-debug.stdout index e475cfac2fc17..f35bd7a7cb2ca 100644 --- a/tests/ui/hygiene/unpretty-debug.stdout +++ b/tests/ui/hygiene/unpretty-debug.stdout @@ -24,5 +24,5 @@ crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: SyntaxContexts: #0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) -#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiTransparent) +#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiOpaque) */ diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout index 1ee7179e84c04..1734b9afe92eb 100644 --- a/tests/ui/proc-macro/meta-macro-hygiene.stdout +++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout @@ -60,11 +60,11 @@ SyntaxContexts: #0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) #1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) #2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) -#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) +#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiOpaque) #4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) #5: parent: #3, outer_mark: (crate0::{{expn3}}, Transparent) -#6: parent: #0, outer_mark: (crate0::{{expn3}}, SemiTransparent) +#6: parent: #0, outer_mark: (crate0::{{expn3}}, SemiOpaque) #7: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) #8: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent) -#9: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent) +#9: parent: #4, outer_mark: (crate0::{{expn4}}, SemiOpaque) */ diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index 6fd6cb474693b..0f1b19ffdeabc 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -82,10 +82,10 @@ SyntaxContexts: #0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) #1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) #2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) -#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) +#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiOpaque) #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: #4, outer_mark: (crate0::{{expn4}}, Transparent) -#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) +#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiOpaque) */ From ce39784f13022efa0f3b7f23c63150ae51c34d44 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Fri, 14 Mar 2025 14:47:03 +0000 Subject: [PATCH 0412/2248] Move `FindPanicUnwrap` to `missing_headers.rs` --- clippy_lints/src/doc/missing_headers.rs | 78 +++++++++++++++++-- clippy_lints/src/doc/mod.rs | 99 ++----------------------- 2 files changed, 79 insertions(+), 98 deletions(-) diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs index e75abf28bace8..65d2ff83c259e 100644 --- a/clippy_lints/src/doc/missing_headers.rs +++ b/clippy_lints/src/doc/missing_headers.rs @@ -1,9 +1,13 @@ use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC}; use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; +use clippy_utils::macros::{is_panic, root_macro_call_first_node}; use clippy_utils::ty::{implements_trait_with_env, is_type_diagnostic_item}; -use clippy_utils::{is_doc_hidden, return_ty}; -use rustc_hir::{BodyId, FnSig, OwnerId, Safety}; +use clippy_utils::visitors::Visitable; +use clippy_utils::{is_doc_hidden, method_chain_args, return_ty}; +use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::{AnonConst, BodyId, Expr, FnSig, OwnerId, Safety}; use rustc_lint::LateContext; +use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::ty; use rustc_span::{Span, sym}; @@ -13,7 +17,6 @@ pub fn check( sig: FnSig<'_>, headers: DocHeaders, body_id: Option, - panic_info: Option<(Span, bool)>, check_private_items: bool, ) { if !check_private_items && !cx.effective_visibilities.is_exported(owner_id.def_id) { @@ -46,13 +49,16 @@ pub fn check( ), _ => (), } - if !headers.panics && panic_info.is_some_and(|el| !el.1) { + if !headers.panics + && let Some(body_id) = body_id + && let Some((panic_span, false)) = FindPanicUnwrap::find_span(cx, body_id) + { span_lint_and_note( cx, MISSING_PANICS_DOC, span, "docs for function which may panic missing `# Panics` section", - panic_info.map(|el| el.0), + Some(panic_span), "first possible panic found here", ); } @@ -89,3 +95,65 @@ pub fn check( } } } + +struct FindPanicUnwrap<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + is_const: bool, + panic_span: Option, + typeck_results: &'tcx ty::TypeckResults<'tcx>, +} + +impl<'a, 'tcx> FindPanicUnwrap<'a, 'tcx> { + pub fn find_span(cx: &'a LateContext<'tcx>, body_id: BodyId) -> Option<(Span, bool)> { + let mut vis = Self { + cx, + is_const: false, + panic_span: None, + typeck_results: cx.tcx.typeck_body(body_id), + }; + cx.tcx.hir_body(body_id).visit(&mut vis); + vis.panic_span.map(|el| (el, vis.is_const)) + } +} + +impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { + type NestedFilter = OnlyBodies; + + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { + if self.panic_span.is_some() { + return; + } + + if let Some(macro_call) = root_macro_call_first_node(self.cx, expr) { + if is_panic(self.cx, macro_call.def_id) + || matches!( + self.cx.tcx.item_name(macro_call.def_id).as_str(), + "assert" | "assert_eq" | "assert_ne" + ) + { + self.is_const = self.cx.tcx.hir_is_inside_const_context(expr.hir_id); + self.panic_span = Some(macro_call.span); + } + } + + // check for `unwrap` and `expect` for both `Option` and `Result` + if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or(method_chain_args(expr, &["expect"])) { + let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); + if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option) + || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result) + { + self.panic_span = Some(expr.span); + } + } + + // and check sub-expressions + intravisit::walk_expr(self, expr); + } + + // Panics in const blocks will cause compilation to fail. + fn visit_anon_const(&mut self, _: &'tcx AnonConst) {} + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.cx.tcx + } +} diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index d0075d01eeaa4..ce0e3cae51c6c 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -3,11 +3,8 @@ use clippy_config::Conf; use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then}; -use clippy_utils::macros::{is_panic, root_macro_call_first_node}; use clippy_utils::source::snippet_opt; -use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::visitors::Visitable; -use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, method_chain_args}; +use clippy_utils::{is_entrypoint_fn, is_trait_impl_item}; use pulldown_cmark::Event::{ Code, DisplayMath, End, FootnoteReference, HardBreak, Html, InlineHtml, InlineMath, Rule, SoftBreak, Start, TaskListMarker, Text, @@ -16,18 +13,15 @@ use pulldown_cmark::Tag::{BlockQuote, CodeBlock, FootnoteDefinition, Heading, It use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options, TagEnd}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{AnonConst, Attribute, Expr, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; +use rustc_hir::{Attribute, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; -use rustc_middle::hir::nested_filter; -use rustc_middle::ty; use rustc_resolve::rustdoc::{ DocFragment, add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range, span_of_fragments, }; use rustc_session::impl_lint_pass; +use rustc_span::Span; use rustc_span::edition::Edition; -use rustc_span::{Span, sym}; use std::ops::Range; use url::Url; @@ -657,20 +651,16 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { self.check_private_items, ); match item.kind { - ItemKind::Fn { sig, body: body_id, .. } => { + ItemKind::Fn { sig, body, .. } => { if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || item.span.in_external_macro(cx.tcx.sess.source_map())) { - let body = cx.tcx.hir_body(body_id); - - let panic_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value); missing_headers::check( cx, item.owner_id, sig, headers, - Some(body_id), - panic_info, + Some(body), self.check_private_items, ); } @@ -697,15 +687,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { if let TraitItemKind::Fn(sig, ..) = trait_item.kind && !trait_item.span.in_external_macro(cx.tcx.sess.source_map()) { - missing_headers::check( - cx, - trait_item.owner_id, - sig, - headers, - None, - None, - self.check_private_items, - ); + missing_headers::check(cx, trait_item.owner_id, sig, headers, None, self.check_private_items); } }, Node::ImplItem(impl_item) => { @@ -713,16 +695,12 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { && !impl_item.span.in_external_macro(cx.tcx.sess.source_map()) && !is_trait_impl_item(cx, impl_item.hir_id()) { - let body = cx.tcx.hir_body(body_id); - - let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(impl_item.owner_id), body.value); missing_headers::check( cx, impl_item.owner_id, sig, headers, Some(body_id), - panic_span, self.check_private_items, ); } @@ -1168,71 +1146,6 @@ fn check_doc<'a, Events: Iterator, Range { - cx: &'a LateContext<'tcx>, - is_const: bool, - panic_span: Option, - typeck_results: &'tcx ty::TypeckResults<'tcx>, -} - -impl<'a, 'tcx> FindPanicUnwrap<'a, 'tcx> { - pub fn find_span( - cx: &'a LateContext<'tcx>, - typeck_results: &'tcx ty::TypeckResults<'tcx>, - body: impl Visitable<'tcx>, - ) -> Option<(Span, bool)> { - let mut vis = Self { - cx, - is_const: false, - panic_span: None, - typeck_results, - }; - body.visit(&mut vis); - vis.panic_span.map(|el| (el, vis.is_const)) - } -} - -impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if self.panic_span.is_some() { - return; - } - - if let Some(macro_call) = root_macro_call_first_node(self.cx, expr) - && (is_panic(self.cx, macro_call.def_id) - || matches!( - self.cx.tcx.item_name(macro_call.def_id).as_str(), - "assert" | "assert_eq" | "assert_ne" - )) - { - self.is_const = self.cx.tcx.hir_is_inside_const_context(expr.hir_id); - self.panic_span = Some(macro_call.span); - } - - // check for `unwrap` and `expect` for both `Option` and `Result` - if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or(method_chain_args(expr, &["expect"])) { - let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); - if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option) - || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result) - { - self.panic_span = Some(expr.span); - } - } - - // and check sub-expressions - intravisit::walk_expr(self, expr); - } - - // Panics in const blocks will cause compilation to fail. - fn visit_anon_const(&mut self, _: &'tcx AnonConst) {} - - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { - self.cx.tcx - } -} - #[expect(clippy::range_plus_one)] // inclusive ranges aren't the same type fn looks_like_refdef(doc: &str, range: Range) -> Option> { if range.end < range.start { From c89368537cc76c83ecc7ea7282423f9a189e02aa Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Fri, 14 Mar 2025 15:02:00 +0000 Subject: [PATCH 0413/2248] Fix partially const bodies not linting `missing_panics_doc` --- clippy_lints/src/doc/missing_headers.rs | 27 +++++++++--------- tests/ui/missing_panics_doc.rs | 10 +++++++ tests/ui/missing_panics_doc.stderr | 38 ++++++++++++++++--------- 3 files changed, 48 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs index 65d2ff83c259e..b07326c524cc4 100644 --- a/clippy_lints/src/doc/missing_headers.rs +++ b/clippy_lints/src/doc/missing_headers.rs @@ -1,7 +1,7 @@ use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC}; use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; -use clippy_utils::ty::{implements_trait_with_env, is_type_diagnostic_item}; +use clippy_utils::ty::{get_type_diagnostic_name, implements_trait_with_env, is_type_diagnostic_item}; use clippy_utils::visitors::Visitable; use clippy_utils::{is_doc_hidden, method_chain_args, return_ty}; use rustc_hir::intravisit::{self, Visitor}; @@ -51,7 +51,7 @@ pub fn check( } if !headers.panics && let Some(body_id) = body_id - && let Some((panic_span, false)) = FindPanicUnwrap::find_span(cx, body_id) + && let Some(panic_span) = FindPanicUnwrap::find_span(cx, body_id) { span_lint_and_note( cx, @@ -98,21 +98,19 @@ pub fn check( struct FindPanicUnwrap<'a, 'tcx> { cx: &'a LateContext<'tcx>, - is_const: bool, panic_span: Option, typeck_results: &'tcx ty::TypeckResults<'tcx>, } impl<'a, 'tcx> FindPanicUnwrap<'a, 'tcx> { - pub fn find_span(cx: &'a LateContext<'tcx>, body_id: BodyId) -> Option<(Span, bool)> { + pub fn find_span(cx: &'a LateContext<'tcx>, body_id: BodyId) -> Option { let mut vis = Self { cx, - is_const: false, panic_span: None, typeck_results: cx.tcx.typeck_body(body_id), }; cx.tcx.hir_body(body_id).visit(&mut vis); - vis.panic_span.map(|el| (el, vis.is_const)) + vis.panic_span } } @@ -125,13 +123,13 @@ impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { } if let Some(macro_call) = root_macro_call_first_node(self.cx, expr) { - if is_panic(self.cx, macro_call.def_id) + if (is_panic(self.cx, macro_call.def_id) || matches!( - self.cx.tcx.item_name(macro_call.def_id).as_str(), - "assert" | "assert_eq" | "assert_ne" - ) + self.cx.tcx.get_diagnostic_name(macro_call.def_id), + Some(sym::assert_macro | sym::assert_eq_macro | sym::assert_ne_macro) + )) + && !self.cx.tcx.hir_is_inside_const_context(expr.hir_id) { - self.is_const = self.cx.tcx.hir_is_inside_const_context(expr.hir_id); self.panic_span = Some(macro_call.span); } } @@ -139,9 +137,10 @@ impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { // check for `unwrap` and `expect` for both `Option` and `Result` if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or(method_chain_args(expr, &["expect"])) { let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); - if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option) - || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result) - { + if matches!( + get_type_diagnostic_name(self.cx, receiver_ty), + Some(sym::Option | sym::Result) + ) { self.panic_span = Some(expr.span); } } diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index 95e361c5d5556..95236d33fd8b3 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -151,6 +151,16 @@ pub fn debug_assertions() { debug_assert_ne!(1, 2); } +pub fn partially_const(n: usize) { + //~^ missing_panics_doc + + const { + assert!(N > 5); + } + + assert!(N > n); +} + // all function must be triggered the lint. // `pub` is required, because the lint does not consider unreachable items pub mod issue10240 { diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr index a83e2fa367dd3..80ab5b064730b 100644 --- a/tests/ui/missing_panics_doc.stderr +++ b/tests/ui/missing_panics_doc.stderr @@ -73,76 +73,88 @@ LL | assert_ne!(x, 0); | ^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:157:5 + --> tests/ui/missing_panics_doc.rs:154:1 + | +LL | pub fn partially_const(n: usize) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> tests/ui/missing_panics_doc.rs:161:5 + | +LL | assert!(N > n); + | ^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> tests/ui/missing_panics_doc.rs:167:5 | LL | pub fn option_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:160:9 + --> tests/ui/missing_panics_doc.rs:170:9 | LL | o.unwrap() | ^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:163:5 + --> tests/ui/missing_panics_doc.rs:173:5 | LL | pub fn option_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:166:9 + --> tests/ui/missing_panics_doc.rs:176:9 | LL | o.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:169:5 + --> tests/ui/missing_panics_doc.rs:179:5 | LL | pub fn result_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:172:9 + --> tests/ui/missing_panics_doc.rs:182:9 | LL | res.unwrap() | ^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:175:5 + --> tests/ui/missing_panics_doc.rs:185:5 | LL | pub fn result_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:178:9 + --> tests/ui/missing_panics_doc.rs:188:9 | LL | res.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:181:5 + --> tests/ui/missing_panics_doc.rs:191:5 | LL | pub fn last_unwrap(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:183:10 + --> tests/ui/missing_panics_doc.rs:193:10 | LL | *v.last().unwrap() | ^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:186:5 + --> tests/ui/missing_panics_doc.rs:196:5 | LL | pub fn last_expect(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:188:10 + --> tests/ui/missing_panics_doc.rs:198:10 | LL | *v.last().expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors From 6ee4f34741877a4070c889f75dffe775f736ab36 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Fri, 14 Mar 2025 15:22:33 +0000 Subject: [PATCH 0414/2248] Abide by `allow`/`expect` in bodies for `missing_panics_doc` --- clippy_lints/src/doc/missing_headers.rs | 6 ++-- clippy_lints/src/doc/mod.rs | 13 +++++++++ tests/ui/missing_panics_doc.rs | 20 +++++++++++++ tests/ui/missing_panics_doc.stderr | 38 ++++++++++++++++--------- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs index b07326c524cc4..dff6fb932b254 100644 --- a/clippy_lints/src/doc/missing_headers.rs +++ b/clippy_lints/src/doc/missing_headers.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; use clippy_utils::ty::{get_type_diagnostic_name, implements_trait_with_env, is_type_diagnostic_item}; use clippy_utils::visitors::Visitable; -use clippy_utils::{is_doc_hidden, method_chain_args, return_ty}; +use clippy_utils::{fulfill_or_allowed, is_doc_hidden, method_chain_args, return_ty}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AnonConst, BodyId, Expr, FnSig, OwnerId, Safety}; use rustc_lint::LateContext; @@ -129,6 +129,7 @@ impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { Some(sym::assert_macro | sym::assert_eq_macro | sym::assert_ne_macro) )) && !self.cx.tcx.hir_is_inside_const_context(expr.hir_id) + && !fulfill_or_allowed(self.cx, MISSING_PANICS_DOC, [expr.hir_id]) { self.panic_span = Some(macro_call.span); } @@ -140,7 +141,8 @@ impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { if matches!( get_type_diagnostic_name(self.cx, receiver_ty), Some(sym::Option | sym::Result) - ) { + ) && !fulfill_or_allowed(self.cx, MISSING_PANICS_DOC, [expr.hir_id]) + { self.panic_span = Some(expr.span); } } diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index ce0e3cae51c6c..ab77edf1147cb 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -188,6 +188,19 @@ declare_clippy_lint! { /// } /// } /// ``` + /// + /// Individual panics within a function can be ignored with `#[expect]` or + /// `#[allow]`: + /// + /// ```no_run + /// # use std::num::NonZeroUsize; + /// pub fn will_not_panic(x: usize) { + /// #[expect(clippy::missing_panics_doc, reason = "infallible")] + /// let y = NonZeroUsize::new(1).unwrap(); + /// + /// // If any panics are added in the future the lint will still catch them + /// } + /// ``` #[clippy::version = "1.51.0"] pub MISSING_PANICS_DOC, pedantic, diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index 95236d33fd8b3..ac6431b5452b4 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -161,6 +161,26 @@ pub fn partially_const(n: usize) { assert!(N > n); } +pub fn expect_allow(i: Option) { + #[expect(clippy::missing_panics_doc)] + i.unwrap(); + + #[allow(clippy::missing_panics_doc)] + i.unwrap(); +} + +pub fn expect_allow_with_error(i: Option) { + //~^ missing_panics_doc + + #[expect(clippy::missing_panics_doc)] + i.unwrap(); + + #[allow(clippy::missing_panics_doc)] + i.unwrap(); + + i.unwrap(); +} + // all function must be triggered the lint. // `pub` is required, because the lint does not consider unreachable items pub mod issue10240 { diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr index 80ab5b064730b..dbacd15865df4 100644 --- a/tests/ui/missing_panics_doc.stderr +++ b/tests/ui/missing_panics_doc.stderr @@ -85,76 +85,88 @@ LL | assert!(N > n); | ^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:167:5 + --> tests/ui/missing_panics_doc.rs:172:1 + | +LL | pub fn expect_allow_with_error(i: Option) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> tests/ui/missing_panics_doc.rs:181:5 + | +LL | i.unwrap(); + | ^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> tests/ui/missing_panics_doc.rs:187:5 | LL | pub fn option_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:170:9 + --> tests/ui/missing_panics_doc.rs:190:9 | LL | o.unwrap() | ^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:173:5 + --> tests/ui/missing_panics_doc.rs:193:5 | LL | pub fn option_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:176:9 + --> tests/ui/missing_panics_doc.rs:196:9 | LL | o.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:179:5 + --> tests/ui/missing_panics_doc.rs:199:5 | LL | pub fn result_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:182:9 + --> tests/ui/missing_panics_doc.rs:202:9 | LL | res.unwrap() | ^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:185:5 + --> tests/ui/missing_panics_doc.rs:205:5 | LL | pub fn result_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:188:9 + --> tests/ui/missing_panics_doc.rs:208:9 | LL | res.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:191:5 + --> tests/ui/missing_panics_doc.rs:211:5 | LL | pub fn last_unwrap(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:193:10 + --> tests/ui/missing_panics_doc.rs:213:10 | LL | *v.last().unwrap() | ^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:196:5 + --> tests/ui/missing_panics_doc.rs:216:5 | LL | pub fn last_expect(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:198:10 + --> tests/ui/missing_panics_doc.rs:218:10 | LL | *v.last().expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 13 previous errors +error: aborting due to 14 previous errors From f894a81654d6fd67137ba0676bfbd295a48cb471 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sat, 22 Mar 2025 16:25:19 +0000 Subject: [PATCH 0415/2248] Fulfill expectations after first `missing-panics-doc` --- clippy_lints/src/doc/missing_headers.rs | 86 +++++++++---------------- tests/ui/missing_panics_doc.rs | 9 +++ tests/ui/missing_panics_doc.stderr | 38 +++++++---- 3 files changed, 63 insertions(+), 70 deletions(-) diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs index dff6fb932b254..039937e0207b0 100644 --- a/clippy_lints/src/doc/missing_headers.rs +++ b/clippy_lints/src/doc/missing_headers.rs @@ -2,14 +2,13 @@ use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_D use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; use clippy_utils::ty::{get_type_diagnostic_name, implements_trait_with_env, is_type_diagnostic_item}; -use clippy_utils::visitors::Visitable; +use clippy_utils::visitors::for_each_expr; use clippy_utils::{fulfill_or_allowed, is_doc_hidden, method_chain_args, return_ty}; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{AnonConst, BodyId, Expr, FnSig, OwnerId, Safety}; +use rustc_hir::{BodyId, FnSig, OwnerId, Safety}; use rustc_lint::LateContext; -use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::ty; use rustc_span::{Span, sym}; +use std::ops::ControlFlow; pub fn check( cx: &LateContext<'_>, @@ -51,7 +50,7 @@ pub fn check( } if !headers.panics && let Some(body_id) = body_id - && let Some(panic_span) = FindPanicUnwrap::find_span(cx, body_id) + && let Some(panic_span) = find_panic(cx, body_id) { span_lint_and_note( cx, @@ -96,65 +95,38 @@ pub fn check( } } -struct FindPanicUnwrap<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - panic_span: Option, - typeck_results: &'tcx ty::TypeckResults<'tcx>, -} - -impl<'a, 'tcx> FindPanicUnwrap<'a, 'tcx> { - pub fn find_span(cx: &'a LateContext<'tcx>, body_id: BodyId) -> Option { - let mut vis = Self { - cx, - panic_span: None, - typeck_results: cx.tcx.typeck_body(body_id), - }; - cx.tcx.hir_body(body_id).visit(&mut vis); - vis.panic_span - } -} - -impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { - type NestedFilter = OnlyBodies; - - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if self.panic_span.is_some() { - return; - } - - if let Some(macro_call) = root_macro_call_first_node(self.cx, expr) { - if (is_panic(self.cx, macro_call.def_id) +fn find_panic(cx: &LateContext<'_>, body_id: BodyId) -> Option { + let mut panic_span = None; + let typeck = cx.tcx.typeck_body(body_id); + for_each_expr(cx, cx.tcx.hir_body(body_id), |expr| { + if let Some(macro_call) = root_macro_call_first_node(cx, expr) + && (is_panic(cx, macro_call.def_id) || matches!( - self.cx.tcx.get_diagnostic_name(macro_call.def_id), + cx.tcx.get_diagnostic_name(macro_call.def_id), Some(sym::assert_macro | sym::assert_eq_macro | sym::assert_ne_macro) )) - && !self.cx.tcx.hir_is_inside_const_context(expr.hir_id) - && !fulfill_or_allowed(self.cx, MISSING_PANICS_DOC, [expr.hir_id]) - { - self.panic_span = Some(macro_call.span); - } + && !cx.tcx.hir_is_inside_const_context(expr.hir_id) + && !fulfill_or_allowed(cx, MISSING_PANICS_DOC, [expr.hir_id]) + && panic_span.is_none() + { + panic_span = Some(macro_call.span); } // check for `unwrap` and `expect` for both `Option` and `Result` - if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or(method_chain_args(expr, &["expect"])) { - let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); - if matches!( - get_type_diagnostic_name(self.cx, receiver_ty), + if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or_else(|| method_chain_args(expr, &["expect"])) + && let receiver_ty = typeck.expr_ty(arglists[0].0).peel_refs() + && matches!( + get_type_diagnostic_name(cx, receiver_ty), Some(sym::Option | sym::Result) - ) && !fulfill_or_allowed(self.cx, MISSING_PANICS_DOC, [expr.hir_id]) - { - self.panic_span = Some(expr.span); - } + ) + && !fulfill_or_allowed(cx, MISSING_PANICS_DOC, [expr.hir_id]) + && panic_span.is_none() + { + panic_span = Some(expr.span); } - // and check sub-expressions - intravisit::walk_expr(self, expr); - } - - // Panics in const blocks will cause compilation to fail. - fn visit_anon_const(&mut self, _: &'tcx AnonConst) {} - - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { - self.cx.tcx - } + // Visit all nodes to fulfill any `#[expect]`s after the first linted panic + ControlFlow::::Continue(()) + }); + panic_span } diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index ac6431b5452b4..ffdae8504f72e 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -181,6 +181,15 @@ pub fn expect_allow_with_error(i: Option) { i.unwrap(); } +pub fn expect_after_error(x: Option, y: Option) { + //~^ missing_panics_doc + + let x = x.unwrap(); + + #[expect(clippy::missing_panics_doc)] + let y = y.unwrap(); +} + // all function must be triggered the lint. // `pub` is required, because the lint does not consider unreachable items pub mod issue10240 { diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr index dbacd15865df4..7f0acf8de9b77 100644 --- a/tests/ui/missing_panics_doc.stderr +++ b/tests/ui/missing_panics_doc.stderr @@ -97,76 +97,88 @@ LL | i.unwrap(); | ^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:187:5 + --> tests/ui/missing_panics_doc.rs:184:1 + | +LL | pub fn expect_after_error(x: Option, y: Option) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> tests/ui/missing_panics_doc.rs:187:13 + | +LL | let x = x.unwrap(); + | ^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> tests/ui/missing_panics_doc.rs:196:5 | LL | pub fn option_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:190:9 + --> tests/ui/missing_panics_doc.rs:199:9 | LL | o.unwrap() | ^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:193:5 + --> tests/ui/missing_panics_doc.rs:202:5 | LL | pub fn option_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:196:9 + --> tests/ui/missing_panics_doc.rs:205:9 | LL | o.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:199:5 + --> tests/ui/missing_panics_doc.rs:208:5 | LL | pub fn result_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:202:9 + --> tests/ui/missing_panics_doc.rs:211:9 | LL | res.unwrap() | ^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:205:5 + --> tests/ui/missing_panics_doc.rs:214:5 | LL | pub fn result_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:208:9 + --> tests/ui/missing_panics_doc.rs:217:9 | LL | res.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:211:5 + --> tests/ui/missing_panics_doc.rs:220:5 | LL | pub fn last_unwrap(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:213:10 + --> tests/ui/missing_panics_doc.rs:222:10 | LL | *v.last().unwrap() | ^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:216:5 + --> tests/ui/missing_panics_doc.rs:225:5 | LL | pub fn last_expect(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:218:10 + --> tests/ui/missing_panics_doc.rs:227:10 | LL | *v.last().expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors From 4e99dca8c35b37fcf097e7bd3c2b00abb7a64dfb Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 31 Mar 2025 15:37:16 +0200 Subject: [PATCH 0416/2248] 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 0417/2248] 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 3e837ec25e14b362c26fcb9fdb9f3e2dcdbde2e5 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Mon, 31 Mar 2025 15:05:45 +0000 Subject: [PATCH 0418/2248] Enable triagebot's merge conflict notifications --- triagebot.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 4b0ad0fb6bbc0..737aaec79a0d7 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -9,6 +9,11 @@ allow-unauthenticated = [ # See https://forge.rust-lang.org/triagebot/shortcuts.html [shortcut] +[merge-conflicts] +add = ['S-waiting-on-author'] +remove = ['S-waiting-on-review'] +unless = ['S-blocked', 'S-final-comment-period'] + # Have rustbot inform users about the *No Merge Policy* [no-merges] exclude_titles = ["Rustup"] # exclude syncs from rust-lang/rust From 1238a20d38d976ccd4ccecf1b9e2cab039ab6d63 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 31 Mar 2025 17:58:05 +0200 Subject: [PATCH 0419/2248] 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 0420/2248] 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 0421/2248] 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 0422/2248] 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 d81559a453d7c9ca0ff9dbd64cf1a9933a54aeab Mon Sep 17 00:00:00 2001 From: Tobias Decking Date: Mon, 31 Mar 2025 19:30:05 +0200 Subject: [PATCH 0423/2248] Refactor `diy_float` --- library/core/src/num/diy_float.rs | 54 ++++--------------- .../core/src/num/flt2dec/strategy/grisu.rs | 8 +-- 2 files changed, 15 insertions(+), 47 deletions(-) diff --git a/library/core/src/num/diy_float.rs b/library/core/src/num/diy_float.rs index ce7f6475d0599..e054e7f3f10a7 100644 --- a/library/core/src/num/diy_float.rs +++ b/library/core/src/num/diy_float.rs @@ -21,61 +21,29 @@ pub struct Fp { impl Fp { /// Returns a correctly rounded product of itself and `other`. - pub fn mul(&self, other: &Fp) -> Fp { - const MASK: u64 = 0xffffffff; - let a = self.f >> 32; - let b = self.f & MASK; - let c = other.f >> 32; - let d = other.f & MASK; - let ac = a * c; - let bc = b * c; - let ad = a * d; - let bd = b * d; - let tmp = (bd >> 32) + (ad & MASK) + (bc & MASK) + (1 << 31) /* round */; - let f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); + pub fn mul(self, other: Self) -> Self { + let (lo, hi) = self.f.widening_mul(other.f); + let f = hi + (lo >> 63) /* round */; let e = self.e + other.e + 64; - Fp { f, e } + Self { f, e } } /// Normalizes itself so that the resulting mantissa is at least `2^63`. - pub fn normalize(&self) -> Fp { - let mut f = self.f; - let mut e = self.e; - if f >> (64 - 32) == 0 { - f <<= 32; - e -= 32; - } - if f >> (64 - 16) == 0 { - f <<= 16; - e -= 16; - } - if f >> (64 - 8) == 0 { - f <<= 8; - e -= 8; - } - if f >> (64 - 4) == 0 { - f <<= 4; - e -= 4; - } - if f >> (64 - 2) == 0 { - f <<= 2; - e -= 2; - } - if f >> (64 - 1) == 0 { - f <<= 1; - e -= 1; - } + pub fn normalize(self) -> Self { + let lz = self.f.leading_zeros(); + let f = self.f << lz; + let e = self.e - lz as i16; debug_assert!(f >= (1 << 63)); - Fp { f, e } + Self { f, e } } /// Normalizes itself to have the shared exponent. /// It can only decrease the exponent (and thus increase the mantissa). - pub fn normalize_to(&self, e: i16) -> Fp { + pub fn normalize_to(self, e: i16) -> Self { let edelta = self.e - e; assert!(edelta >= 0); let edelta = edelta as usize; assert_eq!(self.f << edelta >> edelta, self.f); - Fp { f: self.f << edelta, e } + Self { f: self.f << edelta, e } } } diff --git a/library/core/src/num/flt2dec/strategy/grisu.rs b/library/core/src/num/flt2dec/strategy/grisu.rs index 2816de4c63339..d3bbb0934e0ff 100644 --- a/library/core/src/num/flt2dec/strategy/grisu.rs +++ b/library/core/src/num/flt2dec/strategy/grisu.rs @@ -196,9 +196,9 @@ pub fn format_shortest_opt<'a>( let (minusk, cached) = cached_power(ALPHA - plus.e - 64, GAMMA - plus.e - 64); // scale fps. this gives the maximal error of 1 ulp (proved from Theorem 5.1). - let plus = plus.mul(&cached); - let minus = minus.mul(&cached); - let v = v.mul(&cached); + let plus = plus.mul(cached); + let minus = minus.mul(cached); + let v = v.mul(cached); debug_assert_eq!(plus.e, minus.e); debug_assert_eq!(plus.e, v.e); @@ -480,7 +480,7 @@ pub fn format_exact_opt<'a>( // normalize and scale `v`. let v = Fp { f: d.mant, e: d.exp }.normalize(); let (minusk, cached) = cached_power(ALPHA - v.e - 64, GAMMA - v.e - 64); - let v = v.mul(&cached); + let v = v.mul(cached); // divide `v` into integral and fractional parts. let e = -v.e as usize; From ebca98fa2ff11cf1fc4d753a12db4b1c0bddeda9 Mon Sep 17 00:00:00 2001 From: apiraino Date: Mon, 31 Mar 2025 16:39:25 +0200 Subject: [PATCH 0424/2248] 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 0425/2248] 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 0426/2248] 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 0427/2248] 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 0428/2248] 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 0429/2248] 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 a50fb2248a02368888e18ae6e13410c8617313e2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 22:56:13 +1100 Subject: [PATCH 0430/2248] 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/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index e9db7c9d031a9..76874cc342066 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/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 0431/2248] 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 0432/2248] 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 0433/2248] 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 0434/2248] 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 0435/2248] 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 f8a9c92caea03e25034a78cc3c66d866d475e4d7 Mon Sep 17 00:00:00 2001 From: Ross Delinger Date: Mon, 31 Mar 2025 17:32:02 -0700 Subject: [PATCH 0436/2248] fix: Fix panic in progress due to splitting unicode incorrectly --- .../crates/rust-analyzer/src/cli/progress_report.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/progress_report.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/progress_report.rs index 8b143daf2aea4..c1b1d3f348d8f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/progress_report.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/progress_report.rs @@ -79,8 +79,8 @@ impl<'a> ProgressReport<'a> { // Backtrack to the first differing character let mut output = String::new(); output += &'\x08'.to_string().repeat(self.text.len() - common_prefix_length); - // Output new suffix - output += &text[common_prefix_length..text.len()]; + // Output new suffix, using chars() iter to ensure unicode compatibility + output.extend(text.chars().skip(common_prefix_length)); // If the new text is shorter than the old one: delete overlapping characters if let Some(overlap_count) = self.text.len().checked_sub(text.len()) { From e80a3e22328641b43a5ea66bfafdfe5950686779 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 29 Mar 2025 18:34:44 +1100 Subject: [PATCH 0437/2248] 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 0438/2248] 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 0439/2248] 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 0440/2248] 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 0441/2248] 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 0442/2248] 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 0443/2248] 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 0444/2248] 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 0445/2248] 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 5101c8e87f6e307c618576f76281e011372a65a4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Mar 2025 09:47:43 +1100 Subject: [PATCH 0446/2248] 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`. --- clippy_lints/src/crate_in_macro_def.rs | 2 +- clippy_lints/src/doc/needless_doctest_main.rs | 16 ++-- 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 +- clippy_lints/src/multiple_bound_locations.rs | 2 +- clippy_lints/src/partial_pub_fields.rs | 2 +- .../src/single_component_path_imports.rs | 6 +- clippy_utils/src/ast_utils/mod.rs | 79 +++++++++++++++---- 10 files changed, 89 insertions(+), 43 deletions(-) diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs index 7d86bd3e540a1..c2aac7ca090bb 100644 --- a/clippy_lints/src/crate_in_macro_def.rs +++ b/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/clippy_lints/src/doc/needless_doctest_main.rs b/clippy_lints/src/doc/needless_doctest_main.rs index 3008082c2329d..f6c10da1596b2 100644 --- a/clippy_lints/src/doc/needless_doctest_main.rs +++ b/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/clippy_lints/src/duplicate_mod.rs b/clippy_lints/src/duplicate_mod.rs index 1dac7b971f957..243c99a19ce1b 100644 --- a/clippy_lints/src/duplicate_mod.rs +++ b/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/clippy_lints/src/empty_line_after.rs b/clippy_lints/src/empty_line_after.rs index 80c2b03c41cf4..899b5c5952614 100644 --- a/clippy_lints/src/empty_line_after.rs +++ b/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/clippy_lints/src/empty_with_brackets.rs b/clippy_lints/src/empty_with_brackets.rs index 743ec5b9ea7fb..7d87f04fef9d8 100644 --- a/clippy_lints/src/empty_with_brackets.rs +++ b/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/clippy_lints/src/field_scoped_visibility_modifiers.rs b/clippy_lints/src/field_scoped_visibility_modifiers.rs index ba2b37fbf11a3..aae8291905d37 100644 --- a/clippy_lints/src/field_scoped_visibility_modifiers.rs +++ b/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/clippy_lints/src/multiple_bound_locations.rs b/clippy_lints/src/multiple_bound_locations.rs index 0e1980a6acb61..4b32ba83b325e 100644 --- a/clippy_lints/src/multiple_bound_locations.rs +++ b/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/clippy_lints/src/partial_pub_fields.rs b/clippy_lints/src/partial_pub_fields.rs index 267e2067e101a..cda752d003fa0 100644 --- a/clippy_lints/src/partial_pub_fields.rs +++ b/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/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs index fa08245350429..35f80b2acda68 100644 --- a/clippy_lints/src/single_component_path_imports.rs +++ b/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/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index 6023ae9cc7b16..ff63eb505a5c3 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/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)) From ad7c4cf9b342a26835d577286790348ba8e261ab Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 1 Apr 2025 06:58:21 +0300 Subject: [PATCH 0447/2248] Avoid relying on `block_def_map()` needlessly We can compute the wanted information from the block's interned data. --- src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index e0975b5aeb40b..f8f828276ec2c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -553,7 +553,7 @@ impl ChalkContext<'_> { let block_impls = iter::successors(self.block, |&block_id| { cov_mark::hit!(block_local_impls); - self.db.block_def_map(block_id).parent().and_then(|module| module.containing_block()) + block_id.loc(self.db).module.containing_block() }) .inspect(|&block_id| { // make sure we don't search the same block twice From ec10833609aa63327437aabfaedfbe8a0edcc4d9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Apr 2025 14:49:58 +1100 Subject: [PATCH 0448/2248] 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 3f752b45eb232a2126500e0146d13eb6761dcc74 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Apr 2025 14:49:58 +1100 Subject: [PATCH 0449/2248] Address review comments. --- clippy_lints/src/empty_line_after.rs | 15 ++++++++------- clippy_utils/src/ast_utils/mod.rs | 14 ++++++++++---- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/empty_line_after.rs b/clippy_lints/src/empty_line_after.rs index 899b5c5952614..c67dcd3c82b50 100644 --- a/clippy_lints/src/empty_line_after.rs +++ b/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/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index ff63eb505a5c3..eba576392ebce 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/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)) 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 0450/2248] 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 0451/2248] 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 0452/2248] 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 b0fbec6362cde2ef2587b7a424beef6f2709992e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 1 Apr 2025 08:27:50 +0200 Subject: [PATCH 0453/2248] chore: Disable rust-cache in CI It doesn't actually work with merge groups ... --- .../rust-analyzer/.github/workflows/ci.yaml | 56 ++++++++----------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index 30ba633e02b51..8935c5f57b63b 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -57,9 +57,6 @@ jobs: # We don't cache this job, as it will be invalidated every day due to nightly usage - - name: Bump opt-level - run: sed -i '/\[profile.dev]/a opt-level=1' Cargo.toml - - name: Test run: cargo test --features sysroot-abi -p proc-macro-srv -p proc-macro-srv-cli -p proc-macro-api -- --quiet @@ -97,32 +94,23 @@ jobs: if: matrix.os == 'ubuntu-latest' run: echo "::add-matcher::.github/rust.json" - - name: Bump opt-level - if: matrix.os == 'ubuntu-latest' - run: sed -i '/\[profile.dev]/a opt-level=1' Cargo.toml - - - name: Cache Dependencies - uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 - with: - workspaces: | - . -> target - ./crates/proc-macro-srv/proc-macro-test/imp -> target + # - name: Cache Dependencies + # uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 + # with: + # workspaces: | + # . -> target + # ./crates/proc-macro-srv/proc-macro-test/imp -> target - uses: taiki-e/install-action@nextest - name: Codegen checks (rust-analyzer) + if: matrix.os == 'ubuntu-latest' run: cargo codegen --check - name: Compile (tests) run: cargo test --no-run - # It's faster to `test` before `build` ¯\_(ツ)_/¯ - - name: Compile (rust-analyzer) - if: matrix.os == 'ubuntu-latest' - run: cargo build --quiet - - name: Test - if: matrix.os == 'ubuntu-latest' || matrix.os == 'windows-latest' || github.event_name == 'push' run: cargo nextest run --no-fail-fast --hide-progress-bar --status-level fail - name: clippy @@ -131,8 +119,9 @@ jobs: analysis-stats: if: github.repository == 'rust-lang/rust-analyzer' - name: miri runs-on: ubuntu-latest + env: + RUSTC_BOOTSTRAP: 1 steps: - name: Checkout repository @@ -144,20 +133,22 @@ jobs: rustup default stable rustup component add rustfmt - - name: Cache Dependencies - uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 + # - name: Cache Dependencies + # uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 + + - name: Bump opt-level + run: sed -i '/\[profile.dev]/a opt-level=1' Cargo.toml + + - run: cargo build -p rust-analyzer - name: ./rust-analyzer - run: cargo run -p rust-analyzer -- analysis-stats . -q + run: ./target/debug/rust-analyzer analysis-stats . -q - name: sysroot/lib/rustlib/src/rust/library/ - env: - RUSTC_BOOTSTRAP: 1 - run: cargo run -p rust-analyzer -- analysis-stats --with-deps --no-sysroot --no-test $(rustc --print sysroot)/lib/rustlib/src/rust/library/ -q + run: ./target/debug/rust-analyzer analysis-stats --with-deps --no-sysroot --no-test $(rustc --print sysroot)/lib/rustlib/src/rust/library/ -q rustfmt: if: github.repository == 'rust-lang/rust-analyzer' - name: miri runs-on: ubuntu-latest steps: @@ -174,7 +165,6 @@ jobs: miri: if: github.repository == 'rust-lang/rust-analyzer' - name: miri runs-on: ubuntu-latest steps: @@ -187,8 +177,8 @@ jobs: rustup default nightly rustup component add miri - - name: Cache Dependencies - uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 + # - name: Cache Dependencies + # uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 - run: cargo miri test -p intern @@ -214,8 +204,8 @@ jobs: rustup update --no-self-update stable rustup target add ${{ env.targets }} ${{ env.targets_ide }} - - name: Cache Dependencies - uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 + # - name: Cache Dependencies + # uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 - name: Check run: | @@ -306,7 +296,7 @@ jobs: run: typos conclusion: - needs: [rust, rust-cross, typescript, typo-check, proc-macro-srv, miri] + needs: [rust, rust-cross, typescript, typo-check, proc-macro-srv, miri, rustfmt, analysis-stats] # We need to ensure this job does *not* get skipped if its dependencies fail, # because a skipped job is considered a success by GitHub. So we have to # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run 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 0454/2248] 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 0455/2248] 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 f9ef4563c23d81dff49a3cc4443202358426e3bd Mon Sep 17 00:00:00 2001 From: makai410 Date: Tue, 1 Apr 2025 17:11:53 +0800 Subject: [PATCH 0456/2248] Implement `associated_items` api. --- compiler/rustc_smir/src/rustc_internal/mod.rs | 8 + compiler/rustc_smir/src/rustc_smir/context.rs | 15 ++ .../rustc_smir/src/rustc_smir/convert/ty.rs | 60 ++++++++ compiler/stable_mir/src/compiler_interface.rs | 7 +- compiler/stable_mir/src/crate_def.rs | 16 +- compiler/stable_mir/src/lib.rs | 7 +- compiler/stable_mir/src/mir/pretty.rs | 12 +- compiler/stable_mir/src/ty.rs | 67 +++++++- .../stable-mir/check_assoc_items.rs | 145 ++++++++++++++++++ 9 files changed, 330 insertions(+), 7 deletions(-) create mode 100644 tests/ui-fulldeps/stable-mir/check_assoc_items.rs diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index ad38ea228bf53..30e9b2e72f735 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -147,6 +147,14 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::CoroutineWitnessDef(self.create_def_id(did)) } + pub fn assoc_def(&mut self, did: DefId) -> stable_mir::ty::AssocDef { + stable_mir::ty::AssocDef(self.create_def_id(did)) + } + + pub fn opaque_def(&mut self, did: DefId) -> stable_mir::ty::OpaqueDef { + stable_mir::ty::OpaqueDef(self.create_def_id(did)) + } + pub fn prov(&mut self, aid: AllocId) -> stable_mir::ty::Prov { stable_mir::ty::Prov(self.create_alloc_id(aid)) } diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index aa1921fc8e784..322e86147c19b 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -822,6 +822,21 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let ty = un_op.internal(&mut *tables, tcx).ty(tcx, arg_internal); ty.stable(&mut *tables) } + + fn associated_items(&self, def_id: stable_mir::DefId) -> stable_mir::AssocItems { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let def_id = tables[def_id]; + let assoc_items = if tcx.is_trait_alias(def_id) { + Vec::new() + } else { + tcx.associated_item_def_ids(def_id) + .iter() + .map(|did| tcx.associated_item(*did).stable(&mut *tables)) + .collect() + }; + assoc_items + } } pub(crate) struct TablesWrapper<'tcx>(pub RefCell>); diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index aa0eac628dd0f..8309809d7b51c 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -890,3 +890,63 @@ impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule { } } } + +impl<'tcx> Stable<'tcx> for ty::AssocKind { + type T = stable_mir::ty::AssocKind; + + fn stable(&self, _tables: &mut Tables<'_>) -> Self::T { + use stable_mir::ty::AssocKind; + match self { + ty::AssocKind::Const => AssocKind::Const, + ty::AssocKind::Fn => AssocKind::Fn, + ty::AssocKind::Type => AssocKind::Type, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::AssocItemContainer { + type T = stable_mir::ty::AssocItemContainer; + + fn stable(&self, _tables: &mut Tables<'_>) -> Self::T { + use stable_mir::ty::AssocItemContainer; + match self { + ty::AssocItemContainer::Trait => AssocItemContainer::Trait, + ty::AssocItemContainer::Impl => AssocItemContainer::Impl, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::AssocItem { + type T = stable_mir::ty::AssocItem; + + fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + stable_mir::ty::AssocItem { + def_id: tables.assoc_def(self.def_id), + name: self.name.to_string(), + kind: self.kind.stable(tables), + container: self.container.stable(tables), + trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)), + fn_has_self_parameter: self.fn_has_self_parameter, + opt_rpitit_info: self.opt_rpitit_info.map(|rpitit| rpitit.stable(tables)), + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData { + type T = stable_mir::ty::ImplTraitInTraitData; + + fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + use stable_mir::ty::ImplTraitInTraitData; + match self { + ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => { + ImplTraitInTraitData::Trait { + fn_def_id: tables.fn_def(*fn_def_id), + opaque_def_id: tables.opaque_def(*opaque_def_id), + } + } + ty::ImplTraitInTraitData::Impl { fn_def_id } => { + ImplTraitInTraitData::Impl { fn_def_id: tables.fn_def(*fn_def_id) } + } + } + } +} diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index e82c957c34ea6..46154da36ca07 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -18,8 +18,8 @@ use crate::ty::{ TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, }; use crate::{ - Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind, - Symbol, TraitDecls, mir, + AssocItems, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, + ItemKind, Symbol, TraitDecls, mir, }; /// This trait defines the interface between stable_mir and the Rust compiler. @@ -251,6 +251,9 @@ pub trait Context { /// Get the resulting type of unary operation. fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty; + + /// Get all associated items of a definition. + fn associated_items(&self, def_id: DefId) -> AssocItems; } // A thread local variable that stores a pointer to the tables mapping between TyCtxt diff --git a/compiler/stable_mir/src/crate_def.rs b/compiler/stable_mir/src/crate_def.rs index 2577c281ca4f2..75228135e4cb3 100644 --- a/compiler/stable_mir/src/crate_def.rs +++ b/compiler/stable_mir/src/crate_def.rs @@ -4,7 +4,7 @@ use serde::Serialize; use crate::ty::{GenericArgs, Span, Ty}; -use crate::{Crate, Symbol, with}; +use crate::{AssocItems, Crate, Symbol, with}; /// A unique identification number for each item accessible for the current compilation unit. #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)] @@ -103,6 +103,14 @@ pub trait CrateDefType: CrateDef { } } +/// A trait for retrieving all items from a definition within a crate. +pub trait CrateDefItems: CrateDef { + /// Retrieve all associated items from a definition. + fn associated_items(&self) -> AssocItems { + with(|cx| cx.associated_items(self.def_id())) + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct Attribute { value: String, @@ -158,3 +166,9 @@ macro_rules! crate_def_with_ty { impl CrateDefType for $name {} }; } + +macro_rules! impl_crate_def_items { + ( $name:ident $(;)? ) => { + impl CrateDefItems for $name {} + }; +} diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 70d42dfbfcb9a..df90d3e5a0841 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -23,11 +23,11 @@ use std::{fmt, io}; use serde::Serialize; use crate::compiler_interface::with; -pub use crate::crate_def::{CrateDef, CrateDefType, DefId}; +pub use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType, DefId}; pub use crate::error::*; use crate::mir::mono::StaticDef; use crate::mir::{Body, Mutability}; -use crate::ty::{FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; +use crate::ty::{AssocItem, FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; pub mod abi; #[macro_use] @@ -71,6 +71,9 @@ pub type TraitDecls = Vec; /// A list of impl trait decls. pub type ImplTraitDecls = Vec; +/// A list of associated items. +pub type AssocItems = Vec; + /// Holds information about a crate. #[derive(Clone, PartialEq, Eq, Debug, Serialize)] pub struct Crate { diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 8278afb7a2f17..65d9f20f0a3b1 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -9,7 +9,7 @@ use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, Ter use crate::mir::{ Operand, Place, RawPtrKind, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents, }; -use crate::ty::{AdtKind, IndexedVal, MirConst, Ty, TyConst}; +use crate::ty::{AdtKind, AssocKind, IndexedVal, MirConst, Ty, TyConst}; use crate::{Body, CrateDef, Mutability, with}; impl Display for Ty { @@ -18,6 +18,16 @@ impl Display for Ty { } } +impl Display for AssocKind { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + AssocKind::Fn => write!(f, "method"), + AssocKind::Const => write!(f, "associated const"), + AssocKind::Type => write!(f, "associated type"), + } + } +} + impl Debug for Place { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { with(|ctx| write!(f, "{}", ctx.place_pretty(self))) diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index b857a735b7259..25ec4a440d6ec 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -6,7 +6,7 @@ use serde::Serialize; use super::mir::{Body, Mutability, Safety}; use super::{DefId, Error, Symbol, with}; use crate::abi::{FnAbi, Layout}; -use crate::crate_def::{CrateDef, CrateDefType}; +use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType}; use crate::mir::alloc::{AllocId, read_target_int, read_target_uint}; use crate::mir::mono::StaticDef; use crate::target::MachineInfo; @@ -910,6 +910,10 @@ crate_def! { pub TraitDef; } +impl_crate_def_items! { + TraitDef; +} + impl TraitDef { pub fn declaration(trait_def: &TraitDef) -> TraitDecl { with(|cx| cx.trait_decl(trait_def)) @@ -932,6 +936,10 @@ crate_def! { pub ImplDef; } +impl_crate_def_items! { + ImplDef; +} + impl ImplDef { /// Retrieve information about this implementation. pub fn trait_impl(&self) -> ImplTrait { @@ -1555,3 +1563,60 @@ index_impl!(Span); pub struct VariantIdx(usize); index_impl!(VariantIdx); + +crate_def! { + /// Hold infomation about an Opaque definition, particularly useful in `RPITIT`. + #[derive(Serialize)] + pub OpaqueDef; +} + +crate_def! { + #[derive(Serialize)] + pub AssocDef; +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub struct AssocItem { + pub def_id: AssocDef, + pub name: Symbol, + pub kind: AssocKind, + pub container: AssocItemContainer, + + /// If this is an item in an impl of a trait then this is the `DefId` of + /// the associated item on the trait that this implements. + pub trait_item_def_id: Option, + + /// Whether this is a method with an explicit self + /// as its first parameter, allowing method calls. + pub fn_has_self_parameter: bool, + + /// `Some` if the associated item (an associated type) comes from the + /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData` + /// provides additional information about its source. + pub opt_rpitit_info: Option, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub enum AssocKind { + Const, + Fn, + Type, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub enum AssocItemContainer { + Trait, + Impl, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] +pub enum ImplTraitInTraitData { + Trait { fn_def_id: FnDef, opaque_def_id: OpaqueDef }, + Impl { fn_def_id: FnDef }, +} + +impl AssocItem { + pub fn is_impl_trait_in_trait(&self) -> bool { + self.opt_rpitit_info.is_some() + } +} diff --git a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs new file mode 100644 index 0000000000000..f6f895588f27b --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs @@ -0,0 +1,145 @@ +//@ run-pass +//! Test that users are able to retrieve all associated items from a definition. +//! definition. + +//@ ignore-stage1 +//@ ignore-cross-compile +//@ ignore-remote +//@ edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] + +extern crate rustc_middle; +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate stable_mir; + +use rustc_smir::rustc_internal; +use std::io::Write; +use std::collections::HashSet; +use stable_mir::CrateDef; +use stable_mir::*; +use stable_mir::ty::*; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "crate_assoc_items"; + +/// This function uses the Stable MIR APIs to get information about the test crate. +fn test_assoc_items() -> ControlFlow<()> { + let local_crate = stable_mir::local_crate(); + check_items( + &local_crate.fn_defs(), + &[ + "AStruct::new", + "::assoc_fn_no_self", + "::assoc_fn_has_self", + "ATrait::rpitit", + "ATrait::assoc_fn_has_self", + "ATrait::assoc_fn_no_self", + "::rpitit", + ], + ); + + let local_impls = local_crate.trait_impls(); + let local_traits = local_crate.trait_decls(); + + let trait_assoc_item_defs: Vec = local_traits[0].associated_items() + .iter().map(|assoc_item| assoc_item.def_id).collect(); + check_items( + &trait_assoc_item_defs, + &[ + "ATrait::{synthetic#0}", + "ATrait::rpitit", + "ATrait::Assoc", + "ATrait::assoc_fn_no_self", + "ATrait::assoc_fn_has_self", + ] + ); + + let impl_assoc_item_defs: Vec = local_impls[0].associated_items() + .iter().map(|assoc_item| assoc_item.def_id).collect(); + check_items( + &impl_assoc_item_defs, + &[ + "::{synthetic#0}", + "::rpitit", + "::Assoc", + "::assoc_fn_no_self", + "::assoc_fn_has_self", + ] + ); + + ControlFlow::Continue(()) +} + +/// Check if the list of definitions matches the expected list. +/// Note that order doesn't matter. +fn check_items(items: &[T], expected: &[&str]) { + let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect(); + let item_names: HashSet<_> = items.iter().map(|item| item.name()).collect(); + assert_eq!(item_names, expected); +} + +fn main() { + let path = "assoc_items.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-type=lib".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, test_assoc_items).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + #![allow(dead_code, unused_variables)] + struct AStruct; + + impl AStruct {{ + const ASSOC_CONST: &str = "Nina"; + + fn new() -> Self {{ + AStruct{{}} + }} + }} + + trait ATrait {{ + type Assoc; + + fn assoc_fn_no_self() {{ + }} + + fn assoc_fn_has_self(&self) {{ + }} + + fn rpitit(&self) -> impl std::fmt::Debug {{ + "ciallo" + }} + }} + + impl ATrait for AStruct {{ + type Assoc = u32; + + fn assoc_fn_no_self() {{ + }} + + fn assoc_fn_has_self(&self) {{ + }} + + fn rpitit(&self) -> impl std::fmt::Debug {{ + "ciallo~" + }} + }} + "# + )?; + Ok(()) +} From a7b687c26ef55bfc3481761fef6e46154e5f95ea Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 11:48:06 +0000 Subject: [PATCH 0457/2248] 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 0458/2248] 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 0459/2248] 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 0460/2248] 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 0461/2248] 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 0462/2248] 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 86e6cb5608457f59c90fd1dc3914fa2a6c4adbf0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 11:48:06 +0000 Subject: [PATCH 0463/2248] Decouple trait impls of different traits wrt incremental --- clippy_lints/src/derive.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 2ae35b4005579..fae01026487a0 100644 --- a/clippy_lints/src/derive.rs +++ b/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 03941165cd16464278392248919d1ca457f6eaab Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 1 Apr 2025 13:05:35 +0200 Subject: [PATCH 0464/2248] chore: Replace some `invoke`s with `invoke_actual` in hir-ty --- .../crates/hir-ty/src/chalk_db.rs | 38 +++++++++--------- .../rust-analyzer/crates/hir-ty/src/db.rs | 34 ++++++++-------- .../crates/hir-ty/src/dyn_compatibility.rs | 5 +-- .../crates/hir-ty/src/infer/closure.rs | 5 ++- .../rust-analyzer/crates/hir-ty/src/lower.rs | 39 ++++++++++++------- .../crates/hir-ty/src/mir/borrowck.rs | 2 +- .../crates/hir-ty/src/mir/eval.rs | 2 +- .../crates/hir-ty/src/mir/lower.rs | 20 +++++----- .../crates/hir-ty/src/mir/monomorphization.rs | 8 ++-- .../crates/hir-ty/src/mir/pretty.rs | 2 +- 10 files changed, 81 insertions(+), 74 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 1ce5e6f432f6e..6aec56b3de4a5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -21,7 +21,7 @@ use hir_def::{ }; use crate::{ - AliasEq, AliasTy, BoundVar, DebruijnIndex, FnDefId, Interner, ProjectionTy, ProjectionTyExt, + AliasEq, AliasTy, BoundVar, DebruijnIndex, Interner, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause, db::{HirDatabase, InternedCoroutine}, @@ -53,7 +53,7 @@ pub(crate) type Variances = chalk_ir::Variances; impl chalk_solve::RustIrDatabase for ChalkContext<'_> { fn associated_ty_data(&self, id: AssocTypeId) -> Arc { - self.db.associated_ty_data(id) + self.db.associated_ty_data(from_assoc_type_id(id)) } fn trait_datum(&self, trait_id: TraitId) -> Arc { self.db.trait_datum(self.krate, trait_id) @@ -105,7 +105,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { &self, fn_def_id: chalk_ir::FnDefId, ) -> Arc> { - self.db.fn_def_datum(fn_def_id) + self.db.fn_def_datum(from_chalk(self.db, fn_def_id)) } fn impls_for_trait( @@ -447,7 +447,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { Arc::new(rust_ir::AdtSizeAlign::from_one_zst(false)) } fn assoc_type_name(&self, assoc_ty_id: chalk_ir::AssocTypeId) -> String { - let id = self.db.associated_ty_data(assoc_ty_id).name; + let id = self.db.associated_ty_data(from_assoc_type_id(assoc_ty_id)).name; self.db.type_alias_data(id).name.display(self.db.upcast(), self.edition()).to_string() } fn opaque_type_name(&self, opaque_ty_id: chalk_ir::OpaqueTyId) -> String { @@ -583,11 +583,11 @@ impl chalk_ir::UnificationDatabase for &dyn HirDatabase { &self, fn_def_id: chalk_ir::FnDefId, ) -> chalk_ir::Variances { - HirDatabase::fn_def_variance(*self, fn_def_id) + HirDatabase::fn_def_variance(*self, from_chalk(*self, fn_def_id)) } fn adt_variance(&self, adt_id: chalk_ir::AdtId) -> chalk_ir::Variances { - HirDatabase::adt_variance(*self, adt_id) + HirDatabase::adt_variance(*self, adt_id.0) } } @@ -602,10 +602,9 @@ pub(crate) fn program_clauses_for_chalk_env_query( pub(crate) fn associated_ty_data_query( db: &dyn HirDatabase, - id: AssocTypeId, + type_alias: TypeAliasId, ) -> Arc { - debug!("associated_ty_data {:?}", id); - let type_alias: TypeAliasId = from_assoc_type_id(id); + debug!("associated_ty_data {:?}", type_alias); let trait_ = match type_alias.lookup(db.upcast()).container { ItemContainerId::TraitId(t) => t, _ => panic!("associated type not in trait"), @@ -656,7 +655,7 @@ pub(crate) fn associated_ty_data_query( let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses: vec![] }; let datum = AssociatedTyDatum { trait_id: to_chalk_trait_id(trait_), - id, + id: to_assoc_type_id(type_alias), name: type_alias, binders: make_binders(db, &generic_params, bound_data), }; @@ -923,8 +922,10 @@ fn type_alias_associated_ty_value( Arc::new(value) } -pub(crate) fn fn_def_datum_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Arc { - let callable_def: CallableDefId = from_chalk(db, fn_def_id); +pub(crate) fn fn_def_datum_query( + db: &dyn HirDatabase, + callable_def: CallableDefId, +) -> Arc { let generic_def = GenericDefId::from_callable(db.upcast(), callable_def); let generic_params = generics(db.upcast(), generic_def); let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders(); @@ -943,7 +944,7 @@ pub(crate) fn fn_def_datum_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Ar where_clauses, }; let datum = FnDefDatum { - id: fn_def_id, + id: callable_def.to_chalk(db), sig: chalk_ir::FnSig { abi: sig.abi, safety: chalk_ir::Safety::Safe, @@ -954,8 +955,10 @@ pub(crate) fn fn_def_datum_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Ar Arc::new(datum) } -pub(crate) fn fn_def_variance_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Variances { - let callable_def: CallableDefId = from_chalk(db, fn_def_id); +pub(crate) fn fn_def_variance_query( + db: &dyn HirDatabase, + callable_def: CallableDefId, +) -> Variances { Variances::from_iter( Interner, db.variances_of(GenericDefId::from_callable(db.upcast(), callable_def)) @@ -971,10 +974,7 @@ pub(crate) fn fn_def_variance_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> ) } -pub(crate) fn adt_variance_query( - db: &dyn HirDatabase, - chalk_ir::AdtId(adt_id): AdtId, -) -> Variances { +pub(crate) fn adt_variance_query(db: &dyn HirDatabase, adt_id: hir_def::AdtId) -> Variances { Variances::from_iter( Interner, db.variances_of(adt_id.into()).as_deref().unwrap_or_default().iter().map(|v| match v { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index 6c619794753b0..1bbffc3ff1a92 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -17,8 +17,8 @@ use smallvec::SmallVec; use triomphe::Arc; use crate::{ - Binders, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, Interner, - PolyFnSig, Substitution, TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId, chalk_db, + Binders, Const, ImplTraitId, ImplTraits, InferenceResult, Interner, PolyFnSig, Substitution, + TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId, chalk_db, consteval::ConstEvalError, drop::DropGlue, dyn_compatibility::DynCompatibilityViolation, @@ -39,8 +39,8 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { #[salsa::cycle(crate::mir::mir_body_recover)] fn mir_body(&self, def: DefWithBodyId) -> Result, MirLowerError>; - #[salsa::invoke(crate::mir::mir_body_for_closure_query)] - fn mir_body_for_closure(&self, def: ClosureId) -> Result, MirLowerError>; + #[salsa::invoke_actual(crate::mir::mir_body_for_closure_query)] + fn mir_body_for_closure(&self, def: InternedClosureId) -> Result, MirLowerError>; #[salsa::invoke(crate::mir::monomorphized_mir_body_query)] #[salsa::cycle(crate::mir::monomorphized_mir_body_recover)] @@ -54,12 +54,12 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { #[salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)] fn monomorphized_mir_body_for_closure( &self, - def: ClosureId, + def: InternedClosureId, subst: Substitution, env: Arc, ) -> Result, MirLowerError>; - #[salsa::invoke(crate::mir::borrowck_query)] + #[salsa::invoke_actual(crate::mir::borrowck_query)] #[salsa::lru(2024)] fn borrowck(&self, def: DefWithBodyId) -> Result, MirLowerError>; @@ -110,9 +110,10 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option; #[salsa::invoke(crate::lower::ty_query)] - #[salsa::cycle(crate::lower::ty_recover)] + #[salsa::transparent] fn ty(&self, def: TyDefId) -> Binders; + #[salsa::cycle(crate::lower::type_for_type_alias_with_diagnostics_query_recover)] #[salsa::invoke_actual(crate::lower::type_for_type_alias_with_diagnostics_query)] fn type_for_type_alias_with_diagnostics(&self, def: TypeAliasId) -> (Binders, Diagnostics); @@ -244,11 +245,8 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { #[salsa::interned] fn intern_coroutine(&self, id: InternedCoroutine) -> InternedCoroutineId; - #[salsa::invoke(chalk_db::associated_ty_data_query)] - fn associated_ty_data( - &self, - id: chalk_db::AssocTypeId, - ) -> sync::Arc; + #[salsa::invoke_actual(chalk_db::associated_ty_data_query)] + fn associated_ty_data(&self, id: TypeAliasId) -> sync::Arc; #[salsa::invoke(chalk_db::trait_datum_query)] fn trait_datum( @@ -264,14 +262,14 @@ pub trait HirDatabase: DefDatabase + Upcast + std::fmt::Debug { fn impl_datum(&self, krate: Crate, impl_id: chalk_db::ImplId) -> sync::Arc; - #[salsa::invoke(chalk_db::fn_def_datum_query)] - fn fn_def_datum(&self, fn_def_id: FnDefId) -> sync::Arc; + #[salsa::invoke_actual(chalk_db::fn_def_datum_query)] + fn fn_def_datum(&self, fn_def_id: CallableDefId) -> sync::Arc; - #[salsa::invoke(chalk_db::fn_def_variance_query)] - fn fn_def_variance(&self, fn_def_id: FnDefId) -> chalk_db::Variances; + #[salsa::invoke_actual(chalk_db::fn_def_variance_query)] + fn fn_def_variance(&self, fn_def_id: CallableDefId) -> chalk_db::Variances; - #[salsa::invoke(chalk_db::adt_variance_query)] - fn adt_variance(&self, adt_id: chalk_db::AdtId) -> chalk_db::Variances; + #[salsa::invoke_actual(chalk_db::adt_variance_query)] + fn adt_variance(&self, adt_id: AdtId) -> chalk_db::Variances; #[salsa::invoke_actual(crate::variance::variances_of)] #[salsa::cycle(crate::variance::variances_of_cycle)] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs index 8d1251e01350e..d4cb76b7d2cb5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs @@ -22,7 +22,7 @@ use crate::{ from_assoc_type_id, from_chalk_trait_id, generics::{generics, trait_self_param_idx}, lower::callable_item_sig, - to_assoc_type_id, to_chalk_trait_id, + to_chalk_trait_id, utils::elaborate_clause_supertraits, }; @@ -171,8 +171,7 @@ fn bounds_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool { .iter() .filter_map(|(_, it)| match *it { AssocItemId::TypeAliasId(id) => { - let assoc_ty_id = to_assoc_type_id(id); - let assoc_ty_data = db.associated_ty_data(assoc_ty_id); + let assoc_ty_data = db.associated_ty_data(id); Some(assoc_ty_data) } _ => None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index b18e0271bf09d..201f85f7d3405 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -31,7 +31,7 @@ use crate::{ DynTyExt, FnAbi, FnPointer, FnSig, Interner, OpaqueTy, ProjectionTyExt, Substitution, Ty, TyExt, WhereClause, db::{HirDatabase, InternedClosure}, - error_lifetime, from_chalk_trait_id, from_placeholder_idx, + error_lifetime, from_assoc_type_id, from_chalk_trait_id, from_placeholder_idx, generics::Generics, infer::coerce::CoerceNever, make_binders, @@ -153,7 +153,8 @@ impl InferenceContext<'_> { if let WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection), ty }) = bound.skip_binders() { - let assoc_data = self.db.associated_ty_data(projection.associated_ty_id); + let assoc_data = + self.db.associated_ty_data(from_assoc_type_id(projection.associated_ty_id)); if !fn_traits.contains(&assoc_data.trait_id) { return None; } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 355a4031e9f24..5238a65510c67 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -1560,6 +1560,20 @@ fn type_for_enum_variant_constructor( } } +#[salsa::tracked(recovery_fn = type_for_adt_recovery)] +fn type_for_adt_tracked(db: &dyn HirDatabase, adt: AdtId) -> Binders { + type_for_adt(db, adt) +} + +pub(crate) fn type_for_adt_recovery( + db: &dyn HirDatabase, + _cycle: &salsa::Cycle, + adt: AdtId, +) -> Binders { + let generics = generics(db.upcast(), adt.into()); + make_binders(db, &generics, TyKind::Error.intern(Interner)) +} + fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders { let generics = generics(db.upcast(), adt.into()); let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); @@ -1589,6 +1603,15 @@ pub(crate) fn type_for_type_alias_with_diagnostics_query( (make_binders(db, &generics, inner), create_diagnostics(ctx.diagnostics)) } +pub(crate) fn type_for_type_alias_with_diagnostics_query_recover( + db: &dyn HirDatabase, + _cycle: &salsa::Cycle, + adt: TypeAliasId, +) -> (Binders, Diagnostics) { + let generics = generics(db.upcast(), adt.into()); + (make_binders(db, &generics, TyKind::Error.intern(Interner)), None) +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum TyDefId { BuiltinType(BuiltinType), @@ -1628,25 +1651,11 @@ impl ValueTyDefId { pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders { match def { TyDefId::BuiltinType(it) => Binders::empty(Interner, TyBuilder::builtin(it)), - TyDefId::AdtId(it) => type_for_adt(db, it), + TyDefId::AdtId(it) => type_for_adt_tracked(db, it), TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0, } } -pub(crate) fn ty_recover( - db: &dyn HirDatabase, - _cycle: &salsa::Cycle, - _: HirDatabaseData, - def: TyDefId, -) -> Binders { - let generics = match def { - TyDefId::BuiltinType(_) => return Binders::empty(Interner, TyKind::Error.intern(Interner)), - TyDefId::AdtId(it) => generics(db.upcast(), it.into()), - TyDefId::TypeAliasId(it) => generics(db.upcast(), it.into()), - }; - make_binders(db, &generics, TyKind::Error.intern(Interner)) -} - pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Option> { match def { ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs index d9938fc60cd76..85bf850566fb6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs @@ -71,7 +71,7 @@ fn all_mir_bodies( c: ClosureId, cb: &mut impl FnMut(Arc), ) -> Result<(), MirLowerError> { - match db.mir_body_for_closure(c) { + match db.mir_body_for_closure(c.into()) { Ok(body) => { cb(body.clone()); body.closures.iter().try_for_each(|&it| for_closure(db, it, cb)) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 498d707bdafe5..a2e6093355f2c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -2452,7 +2452,7 @@ impl Evaluator<'_> { let mir_body = self .db .monomorphized_mir_body_for_closure( - closure, + closure.into(), generic_args.clone(), self.trait_env.clone(), ) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 43d04b68233a8..03456fe423d06 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -29,7 +29,7 @@ use triomphe::Arc; use crate::{ Adjust, Adjustment, AutoBorrow, CallableDefId, TyBuilder, TyExt, consteval::ConstEvalError, - db::{HirDatabase, InternedClosure}, + db::{HirDatabase, InternedClosure, InternedClosureId}, display::{DisplayTarget, HirDisplay, hir_display_with_types_map}, error_lifetime, generics::generics, @@ -38,12 +38,12 @@ use crate::{ layout::LayoutError, mapping::ToChalk, mir::{ - AggregateKind, Arena, BasicBlock, BasicBlockId, BinOp, BorrowKind, CastKind, ClosureId, - ConstScalar, Either, Expr, FieldId, Idx, InferenceResult, Interner, Local, LocalId, - MemoryMap, MirBody, MirSpan, Mutability, Operand, Place, PlaceElem, PointerCast, - ProjectionElem, ProjectionStore, RawIdx, Rvalue, Statement, StatementKind, Substitution, - SwitchTargets, Terminator, TerminatorKind, TupleFieldId, Ty, UnOp, VariantId, - intern_const_scalar, return_slot, + AggregateKind, Arena, BasicBlock, BasicBlockId, BinOp, BorrowKind, CastKind, ConstScalar, + Either, Expr, FieldId, Idx, InferenceResult, Interner, Local, LocalId, MemoryMap, MirBody, + MirSpan, Mutability, Operand, Place, PlaceElem, PointerCast, ProjectionElem, + ProjectionStore, RawIdx, Rvalue, Statement, StatementKind, Substitution, SwitchTargets, + Terminator, TerminatorKind, TupleFieldId, Ty, UnOp, VariantId, intern_const_scalar, + return_slot, }, static_lifetime, traits::FnTrait, @@ -2017,9 +2017,9 @@ fn cast_kind(table: &mut InferenceTable<'_>, source_ty: &Ty, target_ty: &Ty) -> pub fn mir_body_for_closure_query( db: &dyn HirDatabase, - closure: ClosureId, + closure: InternedClosureId, ) -> Result> { - let InternedClosure(owner, expr) = db.lookup_intern_closure(closure.into()); + let InternedClosure(owner, expr) = db.lookup_intern_closure(closure); let body = db.body(owner); let infer = db.infer(owner); let Expr::Closure { args, body: root, .. } = &body[expr] else { @@ -2028,7 +2028,7 @@ pub fn mir_body_for_closure_query( let TyKind::Closure(_, substs) = &infer[expr].kind(Interner) else { implementation_error!("closure expression is not closure"); }; - let (captures, kind) = infer.closure_info(&closure); + let (captures, kind) = infer.closure_info(&closure.into()); let mut ctx = MirLowerCtx::new(db, owner, &body, &infer); // 0 is return local ctx.result.locals.alloc(Local { ty: infer[*root].clone() }); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs index c733c7ed845a4..ee7e4ce9de37b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs @@ -17,9 +17,9 @@ use hir_def::DefWithBodyId; use triomphe::Arc; use crate::{ - ClosureId, Const, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, TyKind, + Const, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, TyKind, consteval::{intern_const_scalar, unknown_const}, - db::{HirDatabase, HirDatabaseData, InternedClosure}, + db::{HirDatabase, HirDatabaseData, InternedClosure, InternedClosureId}, from_placeholder_idx, generics::{Generics, generics}, infer::normalize, @@ -326,11 +326,11 @@ pub(crate) fn monomorphized_mir_body_recover( pub fn monomorphized_mir_body_for_closure_query( db: &dyn HirDatabase, - closure: ClosureId, + closure: InternedClosureId, subst: Substitution, trait_env: Arc, ) -> Result, MirLowerError> { - let InternedClosure(owner, _) = db.lookup_intern_closure(closure.into()); + let InternedClosure(owner, _) = db.lookup_intern_closure(closure); let generics = owner.as_generic_def_id(db.upcast()).map(|g_def| generics(db.upcast(), g_def)); let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner }; let body = db.mir_body_for_closure(closure)?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs index d9c0000fffd01..30fe45b207f15 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs @@ -154,7 +154,7 @@ impl<'a> MirPrettyCtx<'a> { } fn for_closure(&mut self, closure: ClosureId) { - let body = match self.db.mir_body_for_closure(closure) { + let body = match self.db.mir_body_for_closure(closure.into()) { Ok(it) => it, Err(e) => { wln!(self, "// error in {closure:?}: {e:?}"); From 6e8a96ea986e49f9b7dffdc30818fca242d6d618 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 1 Apr 2025 09:17:23 +0200 Subject: [PATCH 0465/2248] chore: Remove unnecessary `Arc` clones --- .../rust-analyzer/crates/base-db/src/lib.rs | 30 +++++++++---------- .../src/handlers/type_mismatch.rs | 13 -------- .../crates/ide-diagnostics/src/lib.rs | 4 +-- .../crates/ide/src/inlay_hints/bind_pat.rs | 22 -------------- 4 files changed, 16 insertions(+), 53 deletions(-) diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index e6059e9e79058..83857cf2dd028 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -64,8 +64,7 @@ impl Files { } pub fn set_file_text(&self, db: &mut dyn SourceDatabase, file_id: vfs::FileId, text: &str) { - let files = Arc::clone(&self.files); - match files.entry(file_id) { + match self.files.entry(file_id) { Entry::Occupied(mut occupied) => { occupied.get_mut().set_text(db).to(Arc::from(text)); } @@ -83,8 +82,7 @@ impl Files { text: &str, durability: Durability, ) { - let files = Arc::clone(&self.files); - match files.entry(file_id) { + match self.files.entry(file_id) { Entry::Occupied(mut occupied) => { occupied.get_mut().set_text(db).with_durability(durability).to(Arc::from(text)); } @@ -113,8 +111,7 @@ impl Files { source_root: Arc, durability: Durability, ) { - let source_roots = Arc::clone(&self.source_roots); - match source_roots.entry(source_root_id) { + match self.source_roots.entry(source_root_id) { Entry::Occupied(mut occupied) => { occupied.get_mut().set_source_root(db).with_durability(durability).to(source_root); } @@ -141,9 +138,7 @@ impl Files { source_root_id: SourceRootId, durability: Durability, ) { - let file_source_roots = Arc::clone(&self.file_source_roots); - // let db = self; - match file_source_roots.entry(id) { + match self.file_source_roots.entry(id) { Entry::Occupied(mut occupied) => { occupied .get_mut() @@ -203,7 +198,8 @@ pub trait RootQueryDb: SourceDatabase + salsa::Database { fn parse(&self, file_id: EditionedFileId) -> Parse; /// Returns the set of errors obtained from parsing the file including validation errors. - fn parse_errors(&self, file_id: EditionedFileId) -> Option>; + #[salsa::transparent] + fn parse_errors(&self, file_id: EditionedFileId) -> Option<&[SyntaxError]>; #[salsa::transparent] fn toolchain_channel(&self, krate: Crate) -> Option; @@ -318,12 +314,16 @@ fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse Option> { - let errors = db.parse(file_id).errors(); - match &*errors { - [] => None, - [..] => Some(errors.into()), +fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option<&[SyntaxError]> { + #[salsa::tracked(return_ref)] + fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option> { + let errors = db.parse(file_id).errors(); + match &*errors { + [] => None, + [..] => Some(errors.into()), + } } + parse_errors(db, file_id).as_ref().map(|it| &**it) } fn source_root_crates(db: &dyn RootQueryDb, id: SourceRootId) -> Arc<[Crate]> { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 4ec8c741da5e6..e1124c9ff25bd 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -1041,19 +1041,6 @@ fn test() -> String { ); } - #[test] - fn closure_mismatch_show_different_type() { - check_diagnostics( - r#" -fn f() { - let mut x = (|| 1, 2); - x = (|| 3, 4); - //^^^^ error: expected {closure#23552}, found {closure#23553} -} - "#, - ); - } - #[test] fn type_mismatch_range_adjustment() { cov_mark::check!(type_mismatch_range_adjustment); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index a8d9b67b4ea3c..e667d484befb9 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -332,7 +332,6 @@ pub fn syntax_diagnostics( // [#3434] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily. db.parse_errors(editioned_file_id_wrapper) - .as_deref() .into_iter() .flatten() .take(128) @@ -409,8 +408,7 @@ pub fn semantic_diagnostics( // A bunch of parse errors in a file indicate some bigger structural parse changes in the // file, so we skip semantic diagnostics so we can show these faster. Some(m) => { - if db.parse_errors(editioned_file_id_wrapper).as_deref().is_none_or(|es| es.len() < 16) - { + if db.parse_errors(editioned_file_id_wrapper).is_none_or(|es| es.len() < 16) { m.diagnostics(db, &mut diags, config.style_lints); } } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs index 632893a0252d9..0718e5ac646b2 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs @@ -855,28 +855,6 @@ fn main() { //^ |i32| -> () let p = (y, z); //^ (|i32| -> i32, |i32| -> ()) -} - "#, - ); - check_with_config( - InlayHintsConfig { - type_hints: true, - closure_style: ClosureStyle::ClosureWithId, - ..DISABLED_CONFIG - }, - r#" -//- minicore: fn -fn main() { - let x = || 2; - //^ {closure#25600} - let y = |t: i32| x() + t; - //^ {closure#25601} - let mut t = 5; - //^ i32 - let z = |k: i32| { t += k; }; - //^ {closure#25602} - let p = (y, z); - //^ ({closure#25601}, {closure#25602}) } "#, ); From ff37c7d3954ce9d1c9265e7c82a0bb7b6eba6fee Mon Sep 17 00:00:00 2001 From: joboet Date: Tue, 1 Apr 2025 13:35:16 +0200 Subject: [PATCH 0466/2248] std: use the address of `errno` to identify threads in `unique_thread_exit` Getting the address of `errno` should be just as cheap as `pthread_self()` and avoids having to use the expensive `Mutex` logic because it always results in a pointer. --- library/std/src/sys/exit_guard.rs | 43 ++++++++++++++---------------- library/std/src/sys/pal/unix/os.rs | 2 +- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/library/std/src/sys/exit_guard.rs b/library/std/src/sys/exit_guard.rs index 5a090f506661d..bd70d1782440f 100644 --- a/library/std/src/sys/exit_guard.rs +++ b/library/std/src/sys/exit_guard.rs @@ -1,14 +1,5 @@ cfg_if::cfg_if! { if #[cfg(target_os = "linux")] { - /// pthread_t is a pointer on some platforms, - /// so we wrap it in this to impl Send + Sync. - #[derive(Clone, Copy)] - #[repr(transparent)] - struct PThread(libc::pthread_t); - // Safety: pthread_t is safe to send between threads - unsafe impl Send for PThread {} - // Safety: pthread_t is safe to share between threads - unsafe impl Sync for PThread {} /// Mitigation for /// /// On glibc, `libc::exit` has been observed to not always be thread-safe. @@ -30,28 +21,34 @@ cfg_if::cfg_if! { /// (waiting for the process to exit). #[cfg_attr(any(test, doctest), allow(dead_code))] pub(crate) fn unique_thread_exit() { - let this_thread_id = unsafe { libc::pthread_self() }; - use crate::sync::{Mutex, PoisonError}; - static EXITING_THREAD_ID: Mutex> = Mutex::new(None); - let mut exiting_thread_id = - EXITING_THREAD_ID.lock().unwrap_or_else(PoisonError::into_inner); - match *exiting_thread_id { - None => { + use crate::ffi::c_int; + use crate::ptr; + use crate::sync::atomic::AtomicPtr; + use crate::sync::atomic::Ordering::{Acquire, Relaxed}; + + static EXITING_THREAD_ID: AtomicPtr = AtomicPtr::new(ptr::null_mut()); + + // We use the address of `errno` as a cheap and safe way to identify + // threads. As the C standard mandates that `errno` must have thread + // storage duration, we can rely on its address not changing over the + // lifetime of the thread. Additionally, accesses to `errno` are + // async-signal-safe, so this function is available in all imaginable + // circumstances. + let this_thread_id = crate::sys::os::errno_location(); + match EXITING_THREAD_ID.compare_exchange(ptr::null_mut(), this_thread_id, Acquire, Relaxed) { + Ok(_) => { // This is the first thread to call `unique_thread_exit`, - // and this is the first time it is called. - // Set EXITING_THREAD_ID to this thread's ID and return. - *exiting_thread_id = Some(PThread(this_thread_id)); - }, - Some(exiting_thread_id) if exiting_thread_id.0 == this_thread_id => { + // and this is the first time it is called. Continue exiting. + } + Err(exiting_thread_id) if exiting_thread_id == this_thread_id => { // This is the first thread to call `unique_thread_exit`, // but this is the second time it is called. // Abort the process. core::panicking::panic_nounwind("std::process::exit called re-entrantly") } - Some(_) => { + Err(_) => { // This is not the first thread to call `unique_thread_exit`. // Pause until the process exits. - drop(exiting_thread_id); loop { // Safety: libc::pause is safe to call. unsafe { libc::pause(); } diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index f47421c67051b..3b712f316cd00 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -61,7 +61,7 @@ unsafe extern "C" { #[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; + pub safe fn errno_location() -> *mut c_int; } /// Returns the platform-specific value of errno From 2dc650b97b240c0bd279704b01916970c2031c4b Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Fri, 28 Mar 2025 18:12:29 +0530 Subject: [PATCH 0467/2248] 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 0468/2248] 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 0469/2248] 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 0470/2248] 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 0471/2248] 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 88c46eaf04a0abfdc68b78ff900dc3043af1b914 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 1 Apr 2025 16:06:28 +0200 Subject: [PATCH 0472/2248] Install cmake to restore lintcheck run --- .github/workflows/lintcheck.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/lintcheck.yml b/.github/workflows/lintcheck.yml index 70c805903d36e..4490f872b18d4 100644 --- a/.github/workflows/lintcheck.yml +++ b/.github/workflows/lintcheck.yml @@ -49,6 +49,10 @@ jobs: path: target/debug/lintcheck key: lintcheck-bin-${{ hashfiles('lintcheck/**') }} + # Install cmake to build aws-lc-sys to build tokio-rustls + - name: Install cmake + run: sudo apt-get install -y cmake + - name: Build lintcheck if: steps.cache-lintcheck-bin.outputs.cache-hit != 'true' run: cargo build --manifest-path=lintcheck/Cargo.toml @@ -92,6 +96,10 @@ jobs: path: target/debug/lintcheck key: lintcheck-bin-${{ hashfiles('lintcheck/**') }} + # Install cmake to build aws-lc-sys to build tokio-rustls + - name: Install cmake + run: sudo apt-get install -y cmake + - name: Build lintcheck if: steps.cache-lintcheck-bin.outputs.cache-hit != 'true' run: cargo build --manifest-path=lintcheck/Cargo.toml From 87ff60c0b476f28c22df2f886233477dab27e034 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 1 Apr 2025 16:31:22 +0200 Subject: [PATCH 0473/2248] check_struct_for_power_alignment: simplify code --- compiler/rustc_lint/src/types.rs | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index d98b439ba89fe..d81136192a131 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1623,15 +1623,13 @@ impl ImproperCTypesDefinitions { cx: &LateContext<'tcx>, ty: Ty<'tcx>, ) -> bool { + assert!(cx.tcx.sess.target.os == "aix"); // Structs (under repr(C)) follow the power alignment rule if: // - the first field of the struct is a floating-point type that // is greater than 4-bytes, or // - the first field of the struct is an aggregate whose // recursively first field is a floating-point type greater than // 4 bytes. - if cx.tcx.sess.target.os != "aix" { - return false; - } if ty.is_floating_point() && ty.primitive_size(cx.tcx).bytes() > 4 { return true; } else if let Adt(adt_def, _) = ty.kind() @@ -1663,21 +1661,14 @@ impl ImproperCTypesDefinitions { && !adt_def.all_fields().next().is_none() { let struct_variant_data = item.expect_struct().1; - for (index, ..) in struct_variant_data.fields().iter().enumerate() { + for field_def in struct_variant_data.fields().iter().skip(1) { // Struct fields (after the first field) are checked for the // power alignment rule, as fields after the first are likely // to be the fields that are misaligned. - if index != 0 { - let first_field_def = struct_variant_data.fields()[index]; - let def_id = first_field_def.def_id; - let ty = cx.tcx.type_of(def_id).instantiate_identity(); - if self.check_arg_for_power_alignment(cx, ty) { - cx.emit_span_lint( - USES_POWER_ALIGNMENT, - first_field_def.span, - UsesPowerAlignment, - ); - } + let def_id = field_def.def_id; + let ty = cx.tcx.type_of(def_id).instantiate_identity(); + if self.check_arg_for_power_alignment(cx, ty) { + cx.emit_span_lint(USES_POWER_ALIGNMENT, field_def.span, UsesPowerAlignment); } } } 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 0474/2248] 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 0475/2248] 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 0476/2248] 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 0477/2248] 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 54994b2d4b89a8af8c5a04799e7fa224c7103ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 1 Apr 2025 18:20:41 +0200 Subject: [PATCH 0478/2248] Fix the primary span of redundant_pub_crate when flagging nameless items --- clippy_lints/src/redundant_pub_crate.rs | 11 ++++------- tests/ui/redundant_pub_crate.fixed | 8 ++++++++ tests/ui/redundant_pub_crate.rs | 8 ++++++++ tests/ui/redundant_pub_crate.stderr | 18 +++++++++++++++++- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/redundant_pub_crate.rs b/clippy_lints/src/redundant_pub_crate.rs index f2fdac5a8afaf..7b381fac5f118 100644 --- a/clippy_lints/src/redundant_pub_crate.rs +++ b/clippy_lints/src/redundant_pub_crate.rs @@ -52,13 +52,10 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { && is_not_macro_export(item) && !item.span.in_external_macro(cx.sess().source_map()) { - // FIXME: `DUMMY_SP` isn't right here, because it causes the - // resulting span to begin at the start of the file. - let span = item.span.with_hi( - item.kind - .ident() - .map_or(rustc_span::DUMMY_SP.hi(), |ident| ident.span.hi()), - ); + let span = item + .kind + .ident() + .map_or(item.span, |ident| item.span.with_hi(ident.span.hi())); let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id()); span_lint_and_then( cx, diff --git a/tests/ui/redundant_pub_crate.fixed b/tests/ui/redundant_pub_crate.fixed index a6450123f4c9d..8a30fedede4a4 100644 --- a/tests/ui/redundant_pub_crate.fixed +++ b/tests/ui/redundant_pub_crate.fixed @@ -131,6 +131,14 @@ mod m4 { } } +mod m5 { + pub mod m5_1 {} + // Test that the primary span isn't butchered for item kinds that don't have an ident. + pub use m5_1::*; //~ redundant_pub_crate + #[rustfmt::skip] + pub use m5_1::{*}; //~ redundant_pub_crate +} + pub use m4::*; mod issue_8732 { diff --git a/tests/ui/redundant_pub_crate.rs b/tests/ui/redundant_pub_crate.rs index 7415d34d50cc7..45ba13a63b2e2 100644 --- a/tests/ui/redundant_pub_crate.rs +++ b/tests/ui/redundant_pub_crate.rs @@ -131,6 +131,14 @@ mod m4 { } } +mod m5 { + pub mod m5_1 {} + // Test that the primary span isn't butchered for item kinds that don't have an ident. + pub(crate) use m5_1::*; //~ redundant_pub_crate + #[rustfmt::skip] + pub(crate) use m5_1::{*}; //~ redundant_pub_crate +} + pub use m4::*; mod issue_8732 { diff --git a/tests/ui/redundant_pub_crate.stderr b/tests/ui/redundant_pub_crate.stderr index 95909ea8b0663..4a47a321028d1 100644 --- a/tests/ui/redundant_pub_crate.stderr +++ b/tests/ui/redundant_pub_crate.stderr @@ -129,5 +129,21 @@ LL | pub(crate) fn g() {} // private due to m4_2 | | | help: consider using: `pub` -error: aborting due to 16 previous errors +error: pub(crate) import inside private module + --> tests/ui/redundant_pub_crate.rs:137:5 + | +LL | pub(crate) use m5_1::*; + | ----------^^^^^^^^^^^^^ + | | + | help: consider using: `pub` + +error: pub(crate) import inside private module + --> tests/ui/redundant_pub_crate.rs:139:27 + | +LL | pub(crate) use m5_1::{*}; + | ---------- ^ + | | + | help: consider using: `pub` + +error: aborting due to 18 previous errors From df18de57a540cc9ae2309fd53e49c9a627f7d849 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 30 Mar 2025 15:56:41 +0200 Subject: [PATCH 0479/2248] 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 d81396b7d0b7e196d729b506b31550f504d54f6f Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 1 Apr 2025 19:33:30 +0200 Subject: [PATCH 0480/2248] Do not build `tokio-rustls` in the CI for the time being A discrepancy between the `cmake` version available on the runners and the one required by the `aws-lc-sys` dependency prevents the crate from buiding. --- .github/workflows/lintcheck.yml | 8 -------- lintcheck/ci_crates.toml | 3 ++- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/lintcheck.yml b/.github/workflows/lintcheck.yml index 4490f872b18d4..70c805903d36e 100644 --- a/.github/workflows/lintcheck.yml +++ b/.github/workflows/lintcheck.yml @@ -49,10 +49,6 @@ jobs: path: target/debug/lintcheck key: lintcheck-bin-${{ hashfiles('lintcheck/**') }} - # Install cmake to build aws-lc-sys to build tokio-rustls - - name: Install cmake - run: sudo apt-get install -y cmake - - name: Build lintcheck if: steps.cache-lintcheck-bin.outputs.cache-hit != 'true' run: cargo build --manifest-path=lintcheck/Cargo.toml @@ -96,10 +92,6 @@ jobs: path: target/debug/lintcheck key: lintcheck-bin-${{ hashfiles('lintcheck/**') }} - # Install cmake to build aws-lc-sys to build tokio-rustls - - name: Install cmake - run: sudo apt-get install -y cmake - - name: Build lintcheck if: steps.cache-lintcheck-bin.outputs.cache-hit != 'true' run: cargo build --manifest-path=lintcheck/Cargo.toml diff --git a/lintcheck/ci_crates.toml b/lintcheck/ci_crates.toml index 6299823451d01..55d99ebada358 100644 --- a/lintcheck/ci_crates.toml +++ b/lintcheck/ci_crates.toml @@ -122,7 +122,8 @@ winnow = { name = 'winnow', version = '0.6.13' } cpufeatures = { name = 'cpufeatures', version = '0.2.12' } nix = { name = 'nix', version = '0.29.0' } fnv = { name = 'fnv', version = '1.0.7' } -tokio-rustls = { name = 'tokio-rustls', version = '0.26.0' } +# As of 2025-04-01, one dependency doesn't build because of cmake version discrepancy +# tokio-rustls = { name = 'tokio-rustls', version = '0.26.0' } iana-time-zone = { name = 'iana-time-zone', version = '0.1.60' } rustls-webpki = { name = 'rustls-webpki', version = '0.102.5' } crc32fast = { name = 'crc32fast', version = '1.4.2' } From 6bb090438559e1b0ff3717036d81f8ed40bb15d5 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 1 Apr 2025 19:21:01 +0300 Subject: [PATCH 0481/2248] Fix a bug in MBE expansion that arose from incorrect fixing of an older bug in MBE Specifically, #18744 was the PR that was supposed to fix the old bug, but it fixed it incorrectly (and didn't add a test!) The underlying reason was that we marked metavariables in expansions as joint if they were joint in the macro call, which is incorrect. This wrong fix causes other bug, #19497, which this PR fixes by removing the old (incorrect) fix. --- .../hir-def/src/macro_expansion_tests/mbe.rs | 48 +++++++++++++++++++ .../macro_expansion_tests/mbe/regression.rs | 4 +- .../crates/ide/src/expand_macro.rs | 22 +++++++++ .../crates/mbe/src/expander/transcriber.rs | 11 +++-- .../rust-analyzer/crates/mbe/src/parser.rs | 9 ++-- src/tools/rust-analyzer/crates/tt/src/iter.rs | 5 +- src/tools/rust-analyzer/crates/tt/src/lib.rs | 19 ++++++++ 7 files changed, 107 insertions(+), 11 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs index ddf1a213d7bd3..f99030950dd33 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -1979,3 +1979,51 @@ fn f() { "#]], ); } + +#[test] +fn semicolon_does_not_glue() { + check( + r#" +macro_rules! bug { + ($id: expr) => { + true + }; + ($id: expr; $($attr: ident),*) => { + true + }; + ($id: expr; $($attr: ident),*; $norm: expr) => { + true + }; + ($id: expr; $($attr: ident),*;; $print: expr) => { + true + }; + ($id: expr; $($attr: ident),*; $norm: expr; $print: expr) => { + true + }; +} + +let _ = bug!(a;;;test); + "#, + expect![[r#" +macro_rules! bug { + ($id: expr) => { + true + }; + ($id: expr; $($attr: ident),*) => { + true + }; + ($id: expr; $($attr: ident),*; $norm: expr) => { + true + }; + ($id: expr; $($attr: ident),*;; $print: expr) => { + true + }; + ($id: expr; $($attr: ident),*; $norm: expr; $print: expr) => { + true + }; +} + +let _ = true; + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs index 1bbed01443de8..cb4fcd887d8a5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs @@ -582,8 +582,8 @@ macro_rules! arbitrary { } impl $crate::arbitrary::Arbitrary for Vec { - type Parameters = RangedParams1; - type Strategy = VecStrategy; + type Parameters = RangedParams1 ; + type Strategy = VecStrategy ; fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { { let product_unpack![range, a] = args; vec(any_with::(a), range) diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index 4811f1f691c8c..77668973ea14c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -677,4 +677,26 @@ crate::Foo; crate::Foo;"#]], ); } + + #[test] + fn semi_glueing() { + check( + r#" +macro_rules! __log_value { + ($key:ident :$capture:tt =) => {}; +} + +macro_rules! __log { + ($key:tt $(:$capture:tt)? $(= $value:expr)?; $($arg:tt)+) => { + __log_value!($key $(:$capture)* = $($value)*); + }; +} + +__log!(written:%; "Test"$0); + "#, + expect![[r#" + __log! + "#]], + ); + } } diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs index b1f542eac7cef..f3f9f2990c225 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs @@ -389,8 +389,13 @@ fn expand_var( match ctx.bindings.get_fragment(v, id, &mut ctx.nesting, marker) { Ok(fragment) => { match fragment { - Fragment::Tokens(tt) => builder.extend_with_tt(tt.strip_invisible()), - Fragment::TokensOwned(tt) => builder.extend_with_tt(tt.view().strip_invisible()), + // rustc spacing is not like ours. Ours is like proc macros', it dictates how puncts will actually be joined. + // rustc uses them mostly for pretty printing. So we have to deviate a bit from what rustc does here. + // Basically, a metavariable can never be joined with whatever after it. + Fragment::Tokens(tt) => builder.extend_with_tt_alone(tt.strip_invisible()), + Fragment::TokensOwned(tt) => { + builder.extend_with_tt_alone(tt.view().strip_invisible()) + } Fragment::Expr(sub) => { let sub = sub.strip_invisible(); let mut span = id; @@ -402,7 +407,7 @@ fn expand_var( if wrap_in_parens { builder.open(tt::DelimiterKind::Parenthesis, span); } - builder.extend_with_tt(sub); + builder.extend_with_tt_alone(sub); if wrap_in_parens { builder.close(span); } diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs index 7be49cbc7e112..8a2f124213948 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs @@ -6,7 +6,10 @@ use std::sync::Arc; use arrayvec::ArrayVec; use intern::{Symbol, sym}; use span::{Edition, Span, SyntaxContext}; -use tt::iter::{TtElement, TtIter}; +use tt::{ + MAX_GLUED_PUNCT_LEN, + iter::{TtElement, TtIter}, +}; use crate::ParseError; @@ -96,7 +99,7 @@ pub(crate) enum Op { delimiter: tt::Delimiter, }, Literal(tt::Literal), - Punct(Box, 3>>), + Punct(Box, MAX_GLUED_PUNCT_LEN>>), Ident(tt::Ident), } @@ -151,7 +154,7 @@ pub(crate) enum MetaVarKind { pub(crate) enum Separator { Literal(tt::Literal), Ident(tt::Ident), - Puncts(ArrayVec, 3>), + Puncts(ArrayVec, MAX_GLUED_PUNCT_LEN>), } // Note that when we compare a Separator, we just care about its textual value. diff --git a/src/tools/rust-analyzer/crates/tt/src/iter.rs b/src/tools/rust-analyzer/crates/tt/src/iter.rs index 1d88218810de6..0418c00174bdb 100644 --- a/src/tools/rust-analyzer/crates/tt/src/iter.rs +++ b/src/tools/rust-analyzer/crates/tt/src/iter.rs @@ -6,7 +6,7 @@ use std::fmt; use arrayvec::ArrayVec; use intern::sym; -use crate::{Ident, Leaf, Punct, Spacing, Subtree, TokenTree, TokenTreesView}; +use crate::{Ident, Leaf, MAX_GLUED_PUNCT_LEN, Punct, Spacing, Subtree, TokenTree, TokenTreesView}; #[derive(Clone)] pub struct TtIter<'a, S> { @@ -111,7 +111,7 @@ impl<'a, S: Copy> TtIter<'a, S> { /// /// This method currently may return a single quotation, which is part of lifetime ident and /// conceptually not a punct in the context of mbe. Callers should handle this. - pub fn expect_glued_punct(&mut self) -> Result, 3>, ()> { + pub fn expect_glued_punct(&mut self) -> Result, MAX_GLUED_PUNCT_LEN>, ()> { let TtElement::Leaf(&Leaf::Punct(first)) = self.next().ok_or(())? else { return Err(()); }; @@ -145,7 +145,6 @@ impl<'a, S: Copy> TtIter<'a, S> { } ('-' | '!' | '*' | '/' | '&' | '%' | '^' | '+' | '<' | '=' | '>' | '|', '=', _) | ('-' | '=' | '>', '>', _) - | (_, _, Some(';')) | ('<', '-', _) | (':', ':', _) | ('.', '.', _) diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs index 916e00b73bad0..36ccb67f3b8df 100644 --- a/src/tools/rust-analyzer/crates/tt/src/lib.rs +++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs @@ -22,6 +22,8 @@ use stdx::{impl_from, itertools::Itertools as _}; pub use text_size::{TextRange, TextSize}; +pub const MAX_GLUED_PUNCT_LEN: usize = 3; + #[derive(Clone, PartialEq, Debug)] pub struct Lit { pub kind: LitKind, @@ -243,6 +245,23 @@ impl TopSubtreeBuilder { self.token_trees.extend(tt.0.iter().cloned()); } + /// Like [`Self::extend_with_tt()`], but makes sure the new tokens will never be + /// joint with whatever comes after them. + pub fn extend_with_tt_alone(&mut self, tt: TokenTreesView<'_, S>) { + if let Some((last, before_last)) = tt.0.split_last() { + self.token_trees.reserve(tt.0.len()); + self.token_trees.extend(before_last.iter().cloned()); + let last = if let TokenTree::Leaf(Leaf::Punct(last)) = last { + let mut last = *last; + last.spacing = Spacing::Alone; + TokenTree::Leaf(Leaf::Punct(last)) + } else { + last.clone() + }; + self.token_trees.push(last); + } + } + pub fn expected_delimiters(&self) -> impl Iterator> { self.unclosed_subtree_indices.iter().rev().map(|&subtree_idx| { let TokenTree::Subtree(subtree) = &self.token_trees[subtree_idx] else { From dc7d9ec35c7c729baac22830016f0b1ef862100f Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Tue, 11 Mar 2025 20:40:39 -0400 Subject: [PATCH 0482/2248] Validate paths in `disallowed_*` configurations --- clippy.toml | 3 + clippy_config/src/conf.rs | 90 +++++++++++--- clippy_config/src/lib.rs | 1 + clippy_config/src/types.rs | 114 ++++++++++++++++-- clippy_lints/src/await_holding_invalid.rs | 11 +- clippy_lints/src/disallowed_macros.rs | 10 +- clippy_lints/src/disallowed_methods.rs | 23 ++-- clippy_lints/src/disallowed_types.rs | 34 +++--- .../await_holding_invalid_type.stderr | 9 +- tests/ui-toml/toml_invalid_path/clippy.toml | 14 +++ .../toml_invalid_path/conf_invalid_path.rs | 5 + .../conf_invalid_path.stderr | 23 ++++ 12 files changed, 273 insertions(+), 64 deletions(-) create mode 100644 tests/ui-toml/toml_invalid_path/clippy.toml create mode 100644 tests/ui-toml/toml_invalid_path/conf_invalid_path.rs create mode 100644 tests/ui-toml/toml_invalid_path/conf_invalid_path.stderr diff --git a/clippy.toml b/clippy.toml index 77573105d86a3..0a7724bbe4e61 100644 --- a/clippy.toml +++ b/clippy.toml @@ -7,11 +7,14 @@ lint-commented-code = true [[disallowed-methods]] path = "rustc_lint::context::LintContext::lint" reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead" +allow-invalid = true [[disallowed-methods]] path = "rustc_lint::context::LintContext::span_lint" reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead" +allow-invalid = true [[disallowed-methods]] path = "rustc_middle::ty::context::TyCtxt::node_span_lint" reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead" +allow-invalid = true diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index bd20ee1fda4a1..34c62318aad3d 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -120,12 +120,7 @@ impl ConfError { Self { message: message.into(), suggestion, - span: Span::new( - file.start_pos + BytePos::from_usize(span.start), - file.start_pos + BytePos::from_usize(span.end), - SyntaxContext::root(), - None, - ), + span: span_from_toml_range(file, span), } } } @@ -176,11 +171,61 @@ macro_rules! default_text { }; } +macro_rules! deserialize { + ($map:expr, $ty:ty, $errors:expr, $file:expr) => {{ + let raw_value = $map.next_value::>()?; + let value_span = raw_value.span(); + let value = match <$ty>::deserialize(raw_value.into_inner()) { + Err(e) => { + $errors.push(ConfError::spanned( + $file, + e.to_string().replace('\n', " ").trim(), + None, + value_span, + )); + continue; + }, + Ok(value) => value, + }; + (value, value_span) + }}; + + ($map:expr, $ty:ty, $errors:expr, $file:expr, $replacements_allowed:expr) => {{ + let array = $map.next_value::>>()?; + let mut disallowed_paths_span = Range { + start: usize::MAX, + end: usize::MIN, + }; + let mut disallowed_paths = Vec::new(); + for raw_value in array { + let value_span = raw_value.span(); + let mut disallowed_path = match DisallowedPath::<$replacements_allowed>::deserialize(raw_value.into_inner()) + { + Err(e) => { + $errors.push(ConfError::spanned( + $file, + e.to_string().replace('\n', " ").trim(), + None, + value_span, + )); + continue; + }, + Ok(disallowed_path) => disallowed_path, + }; + disallowed_paths_span = union(&disallowed_paths_span, &value_span); + disallowed_path.set_span(span_from_toml_range($file, value_span)); + disallowed_paths.push(disallowed_path); + } + (disallowed_paths, disallowed_paths_span) + }}; +} + macro_rules! define_Conf { ($( $(#[doc = $doc:literal])+ $(#[conf_deprecated($dep:literal, $new_conf:ident)])? $(#[default_text = $default_text:expr])? + $(#[disallowed_paths_allow_replacements = $replacements_allowed:expr])? $(#[lints($($for_lints:ident),* $(,)?)])? $name:ident: $ty:ty = $default:expr, )*) => { @@ -219,7 +264,7 @@ macro_rules! define_Conf { let mut errors = Vec::new(); let mut warnings = Vec::new(); - // Declare a local variable for each field field available to a configuration file. + // Declare a local variable for each field available to a configuration file. $(let mut $name = None;)* // could get `Field` here directly, but get `String` first for diagnostics @@ -237,15 +282,8 @@ macro_rules! define_Conf { $(Field::$name => { // Is this a deprecated field, i.e., is `$dep` set? If so, push a warning. $(warnings.push(ConfError::spanned(self.0, format!("deprecated field `{}`. {}", name.get_ref(), $dep), None, name.span()));)? - let raw_value = map.next_value::>()?; - let value_span = raw_value.span(); - let value = match <$ty>::deserialize(raw_value.into_inner()) { - Err(e) => { - errors.push(ConfError::spanned(self.0, e.to_string().replace('\n', " ").trim(), None, value_span)); - continue; - } - Ok(value) => value - }; + let (value, value_span) = + deserialize!(map, $ty, errors, self.0 $(, $replacements_allowed)?); // Was this field set previously? if $name.is_some() { errors.push(ConfError::spanned(self.0, format!("duplicate field `{}`", name.get_ref()), None, name.span())); @@ -286,6 +324,22 @@ macro_rules! define_Conf { }; } +fn union(x: &Range, y: &Range) -> Range { + Range { + start: cmp::min(x.start, y.start), + end: cmp::max(x.end, y.end), + } +} + +fn span_from_toml_range(file: &SourceFile, span: Range) -> Span { + Span::new( + file.start_pos + BytePos::from_usize(span.start), + file.start_pos + BytePos::from_usize(span.end), + SyntaxContext::root(), + None, + ) +} + define_Conf! { /// Which crates to allow absolute paths from #[lints(absolute_paths)] @@ -472,6 +526,7 @@ define_Conf! { )] avoid_breaking_exported_api: bool = true, /// The list of types which may not be held across an await point. + #[disallowed_paths_allow_replacements = false] #[lints(await_holding_invalid_type)] await_holding_invalid_types: Vec = Vec::new(), /// DEPRECATED LINT: BLACKLISTED_NAME. @@ -517,9 +572,11 @@ define_Conf! { #[conf_deprecated("Please use `cognitive-complexity-threshold` instead", cognitive_complexity_threshold)] cyclomatic_complexity_threshold: u64 = 25, /// The list of disallowed macros, written as fully qualified paths. + #[disallowed_paths_allow_replacements = true] #[lints(disallowed_macros)] disallowed_macros: Vec = Vec::new(), /// The list of disallowed methods, written as fully qualified paths. + #[disallowed_paths_allow_replacements = true] #[lints(disallowed_methods)] disallowed_methods: Vec = Vec::new(), /// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value @@ -528,6 +585,7 @@ define_Conf! { #[lints(disallowed_names)] disallowed_names: Vec = DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect(), /// The list of disallowed types, written as fully qualified paths. + #[disallowed_paths_allow_replacements = true] #[lints(disallowed_types)] disallowed_types: Vec = Vec::new(), /// The list of words this lint should not consider as identifiers needing ticks. The value diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs index 5d6e8b875166c..c227b8900b74a 100644 --- a/clippy_config/src/lib.rs +++ b/clippy_config/src/lib.rs @@ -13,6 +13,7 @@ rustc::untranslatable_diagnostic )] +extern crate rustc_data_structures; extern crate rustc_errors; extern crate rustc_hir; extern crate rustc_middle; diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs index 8faac9ecffea4..5949eaca7bc1d 100644 --- a/clippy_config/src/types.rs +++ b/clippy_config/src/types.rs @@ -1,5 +1,7 @@ -use clippy_utils::def_path_def_ids; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, Diag}; +use rustc_hir::PrimTy; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefIdMap; use rustc_middle::ty::TyCtxt; use rustc_span::Span; @@ -21,6 +23,17 @@ pub struct DisallowedPath { path: String, reason: Option, replacement: Option, + /// Setting `allow_invalid` to true suppresses a warning if `path` does not refer to an existing + /// definition. + /// + /// This could be useful when conditional compilation is used, or when a clippy.toml file is + /// shared among multiple projects. + allow_invalid: bool, + /// The span of the `DisallowedPath`. + /// + /// Used for diagnostics. + #[serde(skip_serializing)] + span: Span, } impl<'de, const REPLACEMENT_ALLOWED: bool> Deserialize<'de> for DisallowedPath { @@ -36,6 +49,8 @@ impl<'de, const REPLACEMENT_ALLOWED: bool> Deserialize<'de> for DisallowedPath, replacement: Option, + #[serde(rename = "allow-invalid")] + allow_invalid: Option, }, } @@ -58,7 +75,7 @@ impl DisallowedPath { &self.path } - pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) + use<'_, REPLACEMENT_ALLOWED> { + pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) { move |diag| { if let Some(replacement) = &self.replacement { diag.span_suggestion( @@ -72,6 +89,14 @@ impl DisallowedPath { } } } + + pub fn span(&self) -> Span { + self.span + } + + pub fn set_span(&mut self, span: Span) { + self.span = span; + } } impl DisallowedPathEnum { @@ -94,20 +119,87 @@ impl DisallowedPathEnum { Self::Simple(_) => None, } } + + fn allow_invalid(&self) -> bool { + match &self { + Self::WithReason { allow_invalid, .. } => allow_invalid.unwrap_or_default(), + Self::Simple(_) => false, + } + } } /// Creates a map of disallowed items to the reason they were disallowed. +#[allow(clippy::type_complexity)] pub fn create_disallowed_map( tcx: TyCtxt<'_>, - disallowed: &'static [DisallowedPath], -) -> DefIdMap<(&'static str, &'static DisallowedPath)> { - disallowed - .iter() - .map(|x| (x.path(), x.path().split("::").collect::>(), x)) - .flat_map(|(name, path, disallowed_path)| { - def_path_def_ids(tcx, &path).map(move |id| (id, (name, disallowed_path))) - }) - .collect() + disallowed_paths: &'static [DisallowedPath], + def_kind_predicate: impl Fn(DefKind) -> bool, + predicate_description: &str, + allow_prim_tys: bool, +) -> ( + DefIdMap<(&'static str, &'static DisallowedPath)>, + FxHashMap)>, +) { + let mut def_ids: DefIdMap<(&'static str, &'static DisallowedPath)> = DefIdMap::default(); + let mut prim_tys: FxHashMap)> = + FxHashMap::default(); + for disallowed_path in disallowed_paths { + let path = disallowed_path.path(); + let mut resolutions = clippy_utils::def_path_res(tcx, &path.split("::").collect::>()); + + let mut found_def_id = None; + let mut found_prim_ty = false; + resolutions.retain(|res| match res { + Res::Def(def_kind, def_id) => { + found_def_id = Some(*def_id); + def_kind_predicate(*def_kind) + }, + Res::PrimTy(_) => { + found_prim_ty = true; + allow_prim_tys + }, + _ => false, + }); + + if resolutions.is_empty() { + let span = disallowed_path.span(); + + if let Some(def_id) = found_def_id { + tcx.sess.dcx().span_warn( + span, + format!( + "expected a {predicate_description}, found {} {}", + tcx.def_descr_article(def_id), + tcx.def_descr(def_id) + ), + ); + } else if found_prim_ty { + tcx.sess.dcx().span_warn( + span, + format!("expected a {predicate_description}, found a primitive type",), + ); + } else if !disallowed_path.allow_invalid { + tcx.sess.dcx().span_warn( + span, + format!("`{path}` does not refer to an existing {predicate_description}"), + ); + } + } + + for res in resolutions { + match res { + Res::Def(_, def_id) => { + def_ids.insert(def_id, (path, disallowed_path)); + }, + Res::PrimTy(ty) => { + prim_tys.insert(ty, (path, disallowed_path)); + }, + _ => unreachable!(), + } + } + } + + (def_ids, prim_tys) } #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)] diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs index d600aec8c9d65..52d1d5b4c67a1 100644 --- a/clippy_lints/src/await_holding_invalid.rs +++ b/clippy_lints/src/await_holding_invalid.rs @@ -179,9 +179,14 @@ pub struct AwaitHolding { impl AwaitHolding { pub(crate) fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { - Self { - def_ids: create_disallowed_map(tcx, &conf.await_holding_invalid_types), - } + let (def_ids, _) = create_disallowed_map( + tcx, + &conf.await_holding_invalid_types, + crate::disallowed_types::def_kind_predicate, + "type", + false, + ); + Self { def_ids } } } diff --git a/clippy_lints/src/disallowed_macros.rs b/clippy_lints/src/disallowed_macros.rs index 22310bc0798f4..fa33fef230622 100644 --- a/clippy_lints/src/disallowed_macros.rs +++ b/clippy_lints/src/disallowed_macros.rs @@ -3,6 +3,7 @@ use clippy_config::types::{DisallowedPath, create_disallowed_map}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::macros::macro_backtrace; use rustc_data_structures::fx::FxHashSet; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefIdMap; use rustc_hir::{ AmbigArg, Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty, @@ -71,8 +72,15 @@ pub struct DisallowedMacros { impl DisallowedMacros { pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf, earlies: AttrStorage) -> Self { + let (disallowed, _) = create_disallowed_map( + tcx, + &conf.disallowed_macros, + |def_kind| matches!(def_kind, DefKind::Macro(_)), + "macro", + false, + ); Self { - disallowed: create_disallowed_map(tcx, &conf.disallowed_macros), + disallowed, seen: FxHashSet::default(), derive_src: None, earlies, diff --git a/clippy_lints/src/disallowed_methods.rs b/clippy_lints/src/disallowed_methods.rs index 149cf1cf2def1..1382dafa931e4 100644 --- a/clippy_lints/src/disallowed_methods.rs +++ b/clippy_lints/src/disallowed_methods.rs @@ -63,9 +63,19 @@ pub struct DisallowedMethods { impl DisallowedMethods { pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { - Self { - disallowed: create_disallowed_map(tcx, &conf.disallowed_methods), - } + let (disallowed, _) = create_disallowed_map( + tcx, + &conf.disallowed_methods, + |def_kind| { + matches!( + def_kind, + DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::AssocFn + ) + }, + "function", + false, + ); + Self { disallowed } } } @@ -74,12 +84,7 @@ impl_lint_pass!(DisallowedMethods => [DISALLOWED_METHODS]); impl<'tcx> LateLintPass<'tcx> for DisallowedMethods { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let (id, span) = match &expr.kind { - ExprKind::Path(path) - if let Res::Def(DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::AssocFn, id) = - cx.qpath_res(path, expr.hir_id) => - { - (id, expr.span) - }, + ExprKind::Path(path) if let Res::Def(_, id) = cx.qpath_res(path, expr.hir_id) => (id, expr.span), ExprKind::MethodCall(name, ..) if let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) => { (id, name.ident.span) }, diff --git a/clippy_lints/src/disallowed_types.rs b/clippy_lints/src/disallowed_types.rs index 38903596414cf..2bae82648ac76 100644 --- a/clippy_lints/src/disallowed_types.rs +++ b/clippy_lints/src/disallowed_types.rs @@ -1,8 +1,8 @@ use clippy_config::Conf; -use clippy_config::types::DisallowedPath; +use clippy_config::types::{DisallowedPath, create_disallowed_map}; use clippy_utils::diagnostics::span_lint_and_then; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def::Res; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefIdMap; use rustc_hir::{AmbigArg, Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -60,22 +60,7 @@ pub struct DisallowedTypes { impl DisallowedTypes { pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { - let mut def_ids = DefIdMap::default(); - let mut prim_tys = FxHashMap::default(); - for disallowed_path in &conf.disallowed_types { - let path: Vec<_> = disallowed_path.path().split("::").collect::>(); - for res in clippy_utils::def_path_res(tcx, &path) { - match res { - Res::Def(_, id) => { - def_ids.insert(id, (disallowed_path.path(), disallowed_path)); - }, - Res::PrimTy(ty) => { - prim_tys.insert(ty, (disallowed_path.path(), disallowed_path)); - }, - _ => {}, - } - } - } + let (def_ids, prim_tys) = create_disallowed_map(tcx, &conf.disallowed_types, def_kind_predicate, "type", true); Self { def_ids, prim_tys } } @@ -95,6 +80,19 @@ impl DisallowedTypes { } } +pub fn def_kind_predicate(def_kind: DefKind) -> bool { + matches!( + def_kind, + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::AssocTy + ) +} + impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]); impl<'tcx> LateLintPass<'tcx> for DisallowedTypes { diff --git a/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr b/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr index 86e30409af068..d0fce3614a145 100644 --- a/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr +++ b/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr @@ -1,11 +1,8 @@ error: error reading Clippy's configuration file: replacement not allowed for this configuration - --> $DIR/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml:1:31 + --> $DIR/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml:2:5 | -LL | await-holding-invalid-types = [ - | _______________________________^ -LL | | { path = "std::string::String", replacement = "std::net::Ipv4Addr" }, -LL | | ] - | |_^ +LL | { path = "std::string::String", replacement = "std::net::Ipv4Addr" }, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui-toml/toml_invalid_path/clippy.toml b/tests/ui-toml/toml_invalid_path/clippy.toml new file mode 100644 index 0000000000000..6d0d732a92237 --- /dev/null +++ b/tests/ui-toml/toml_invalid_path/clippy.toml @@ -0,0 +1,14 @@ +[[disallowed-types]] +path = "std::result::Result::Err" + +[[disallowed-macros]] +path = "bool" + +[[disallowed-methods]] +path = "std::process::current_exe" + +# negative test + +[[disallowed-methods]] +path = "std::current_exe" +allow-invalid = true diff --git a/tests/ui-toml/toml_invalid_path/conf_invalid_path.rs b/tests/ui-toml/toml_invalid_path/conf_invalid_path.rs new file mode 100644 index 0000000000000..c152038270348 --- /dev/null +++ b/tests/ui-toml/toml_invalid_path/conf_invalid_path.rs @@ -0,0 +1,5 @@ +//@error-in-other-file: expected a macro, found a primitive type +//@error-in-other-file: `std::process::current_exe` does not refer to an existing function +//@error-in-other-file: expected a type, found a tuple variant + +fn main() {} diff --git a/tests/ui-toml/toml_invalid_path/conf_invalid_path.stderr b/tests/ui-toml/toml_invalid_path/conf_invalid_path.stderr new file mode 100644 index 0000000000000..82550108eba53 --- /dev/null +++ b/tests/ui-toml/toml_invalid_path/conf_invalid_path.stderr @@ -0,0 +1,23 @@ +warning: expected a macro, found a primitive type + --> $DIR/tests/ui-toml/toml_invalid_path/clippy.toml:4:1 + | +LL | / [[disallowed-macros]] +LL | | path = "bool" + | |_____________^ + +warning: `std::process::current_exe` does not refer to an existing function + --> $DIR/tests/ui-toml/toml_invalid_path/clippy.toml:7:1 + | +LL | / [[disallowed-methods]] +LL | | path = "std::process::current_exe" + | |__________________________________^ + +warning: expected a type, found a tuple variant + --> $DIR/tests/ui-toml/toml_invalid_path/clippy.toml:1:1 + | +LL | / [[disallowed-types]] +LL | | path = "std::result::Result::Err" + | |_________________________________^ + +warning: 3 warnings emitted + From 6ce74f78f002d40b98138ee2ba00bbb21af2630d Mon Sep 17 00:00:00 2001 From: Jane Losare-Lusby Date: Tue, 25 Mar 2025 11:56:55 -0700 Subject: [PATCH 0483/2248] replace extra_filename with strict version hash in metrics file names --- compiler/rustc_driver_impl/src/lib.rs | 13 +++++-------- compiler/rustc_middle/src/ty/context.rs | 5 +++++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 6ea14d15c1440..981cdf1d1d6e3 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -60,6 +60,7 @@ use rustc_session::lint::{Lint, LintId}; use rustc_session::output::collect_crate_types; use rustc_session::{EarlyDiagCtxt, Session, config, filesearch}; use rustc_span::FileName; +use rustc_span::def_id::LOCAL_CRATE; use rustc_target::json::ToJson; use rustc_target::spec::{Target, TargetTuple}; use time::OffsetDateTime; @@ -383,14 +384,10 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) } fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &Path) { - let output_filenames = tcxt.output_filenames(()); - let mut metrics_file_name = std::ffi::OsString::from("unstable_feature_usage_metrics-"); - let mut metrics_path = output_filenames.with_directory_and_extension(metrics_dir, "json"); - let metrics_file_stem = - metrics_path.file_name().expect("there should be a valid default output filename"); - metrics_file_name.push(metrics_file_stem); - metrics_path.pop(); - metrics_path.push(metrics_file_name); + let hash = tcxt.crate_hash(LOCAL_CRATE); + let crate_name = tcxt.crate_name(LOCAL_CRATE); + let metrics_file_name = format!("unstable_feature_usage_metrics-{crate_name}-{hash}.json"); + let metrics_path = metrics_dir.join(metrics_file_name); if let Err(error) = tcxt.features().dump_feature_usage_metrics(metrics_path) { // FIXME(yaahc): once metrics can be enabled by default we will want "failure to emit // default metrics" to only produce a warning when metrics are enabled by default and emit diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 86248b495cdc3..8b6b2bc2493e6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1738,10 +1738,15 @@ impl<'tcx> TyCtxt<'tcx> { // - needs_metadata: for putting into crate metadata. // - instrument_coverage: for putting into coverage data (see // `hash_mir_source`). + // - metrics_dir: metrics use the strict version hash in the filenames + // for dumped metrics files to prevent overwriting distinct metrics + // for similar source builds (may change in the future, this is part + // of the proof of concept impl for the metrics initiative project goal) cfg!(debug_assertions) || self.sess.opts.incremental.is_some() || self.needs_metadata() || self.sess.instrument_coverage() + || self.sess.opts.unstable_opts.metrics_dir.is_some() } #[inline] From 49ed25b5d2d5dc88f9fa3e268d9bd210acc875de Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Apr 2024 21:31:17 +1000 Subject: [PATCH 0484/2248] 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 0485/2248] 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