From fbaa7fc85e1462b9fd8ca6c091327f765a9f4821 Mon Sep 17 00:00:00 2001 From: WiktorPrzetacznik Date: Tue, 18 Jul 2023 17:42:28 +0200 Subject: [PATCH 001/246] std::error::Error -> Trait Implementations: lifetimes consistency improvement --- library/alloc/src/boxed.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 8697a77db3bc8..bd341976cd4f8 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2276,7 +2276,7 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box for Box { +impl<'a> From for Box { /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// # Examples @@ -2291,7 +2291,7 @@ impl From for Box { /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` #[inline] - fn from(err: String) -> Box { + fn from(err: String) -> Box { struct StringError(String); impl Error for StringError { @@ -2320,7 +2320,7 @@ impl From for Box { #[cfg(not(no_global_oom_handling))] #[stable(feature = "string_box_error", since = "1.6.0")] -impl From for Box { +impl<'a> From for Box { /// Converts a [`String`] into a box of dyn [`Error`]. /// /// # Examples @@ -2333,7 +2333,7 @@ impl From for Box { /// let a_boxed_error = Box::::from(a_string_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` - fn from(str_err: String) -> Box { + fn from(str_err: String) -> Box { let err1: Box = From::from(str_err); let err2: Box = err1; err2 @@ -2366,7 +2366,7 @@ impl<'a> From<&str> for Box { #[cfg(not(no_global_oom_handling))] #[stable(feature = "string_box_error", since = "1.6.0")] -impl From<&str> for Box { +impl<'a> From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`]. /// /// [`str`]: prim@str @@ -2381,7 +2381,7 @@ impl From<&str> for Box { /// let a_boxed_error = Box::::from(a_str_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` - fn from(err: &str) -> Box { + fn from(err: &str) -> Box { From::from(String::from(err)) } } @@ -2410,7 +2410,7 @@ impl<'a, 'b> From> for Box { #[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a> From> for Box { +impl<'a, 'b> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`]. /// /// # Examples @@ -2424,7 +2424,7 @@ impl<'a> From> for Box { /// let a_boxed_error = Box::::from(a_cow_str_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` - fn from(err: Cow<'a, str>) -> Box { + fn from(err: Cow<'b, str>) -> Box { From::from(String::from(err)) } } From 3f1ad47b88f973a660dfc99d6f51e77e4e4e4d5e Mon Sep 17 00:00:00 2001 From: Wiktor Przetacznik <85874198+WiktorPrzetacznik@users.noreply.github.com> Date: Tue, 29 Aug 2023 14:09:41 +0200 Subject: [PATCH 002/246] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8a6c559b0b312..59592341d088a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +PR #113833 - https://github.com/rust-lang/rust/pull/113833 + # The Rust Programming Language [![Rust Community](https://img.shields.io/badge/Rust_Community%20-Join_us-brightgreen?style=plastic&logo=rust)](https://www.rust-lang.org/community) From 1da87ee4b31fd1238fe73a42179e5460120d5e2e Mon Sep 17 00:00:00 2001 From: Wiktor Przetacznik Date: Tue, 29 Aug 2023 14:49:09 +0200 Subject: [PATCH 003/246] Revert "Update README.md" This reverts commit 3f1ad47b88f973a660dfc99d6f51e77e4e4e4d5e. --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 59592341d088a..8a6c559b0b312 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -PR #113833 - https://github.com/rust-lang/rust/pull/113833 - # The Rust Programming Language [![Rust Community](https://img.shields.io/badge/Rust_Community%20-Join_us-brightgreen?style=plastic&logo=rust)](https://www.rust-lang.org/community) From a63880c4d3a7e7620f25283999eb4a27516f4816 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 20 Nov 2023 21:55:17 +0100 Subject: [PATCH 004/246] PartialEq: handle longer transitive chains --- library/core/src/cmp.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index bffd3b2af971a..ba7950a709771 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -61,11 +61,13 @@ use self::Ordering::*; /// The equality relation `==` must satisfy the following conditions /// (for all `a`, `b`, `c` of type `A`, `B`, `C`): /// -/// - **Symmetric**: if `A: PartialEq` and `B: PartialEq`, then **`a == b` +/// - **Symmetry**: if `A: PartialEq` and `B: PartialEq`, then **`a == b` /// implies `b == a`**; and /// -/// - **Transitive**: if `A: PartialEq` and `B: PartialEq` and `A: +/// - **Transitivity**: if `A: PartialEq` and `B: PartialEq` and `A: /// PartialEq`, then **`a == b` and `b == c` implies `a == c`**. +/// This must also work for longer chains, such as when `A: PartialEq`, `B: PartialEq`, +/// `C: PartialEq`, and `A: PartialEq` all exist. /// /// Note that the `B: PartialEq` (symmetric) and `A: PartialEq` /// (transitive) impls are not forced to exist, but these requirements apply From 3e389ef6d50c2cae6b561a04adb9224e666eb964 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 20 Nov 2023 21:45:51 +0100 Subject: [PATCH 005/246] PartialOrd: transitivity and duality are required only if the corresponding impls exist --- library/core/src/cmp.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index ba7950a709771..e95410ba648b5 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -921,14 +921,18 @@ pub macro Ord($item:item) { /// easy to accidentally make them disagree by deriving some of the traits and manually /// implementing others. /// -/// The comparison must satisfy, for all `a`, `b` and `c`: +/// The comparison relations must satisfy the following conditions +/// (for all `a`, `b`, `c` of type `A`, `B`, `C`): /// -/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. -/// - duality: `a < b` if and only if `b > a`. +/// - **Transitivity**: if `A: PartialOrd` and `B: PartialOrd` and `A: +/// PartialOrd`, then `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. +/// This must also work for longer chains, such as when `A: PartialOrd`, `B: PartialOrd`, +/// `C: PartialOrd`, and `A: PartialOrd` all exist. +/// - **Duality**: if `A: PartialOrd` and `B: PartialOrd`, then `a < b` if and only if `b > a`. /// -/// Note that these requirements mean that the trait itself must be implemented symmetrically and -/// transitively: if `T: PartialOrd` and `U: PartialOrd` then `U: PartialOrd` and `T: -/// PartialOrd`. +/// Note that the `B: PartialOrd` (dual) and `A: PartialOrd` +/// (transitive) impls are not forced to exist, but these requirements apply +/// whenever they do exist. /// /// Violating these requirements is a logic error. The behavior resulting from a logic error is not /// specified, but users of the trait must ensure that such logic errors do *not* result in From baaf6d706ac3cb8b306ebede165706b7a0038415 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 26 Dec 2023 19:52:20 +0100 Subject: [PATCH 006/246] explain what crates should do when adding comparison with foreign types --- library/core/src/cmp.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index e95410ba648b5..9c18d5573e627 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -78,6 +78,25 @@ use self::Ordering::*; /// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these /// methods. /// +/// ## Cross-crate considerations +/// +/// Upholding the requirements stated above can become tricky when one crate implements `PartialEq` +/// for a type of another crate (i.e., to allow comparing one of its own types with a type from the +/// standard library). The recommendation is to never implement this trait for a foreign type. In +/// other words, such a crate should do `impl PartialEq for LocalType`, but it should +/// *not* do `impl PartialEq for ForeignType`. +/// +/// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local +/// types `T`, you may assue that no other crate will add `impl`s that allow comparing `T == U`. In +/// other words, if other crates add `impl`s that allow building longer transitive chains `U1 == ... +/// == T == V1 == ...`, then all the types that appear to the right of `T` must be types that the +/// crate defining `T` already knows about. This rules out transitive chains where downstream crates +/// can add new `impl`s that "stitch together" comparisons of foreign types in ways that violate +/// transitivity. +/// +/// Not having such foreign `impl`s also avoids forward compatibility issues where one crate adding +/// more `PartialEq` implementations can cause build failures in downstream crates. +/// /// ## Derivable /// /// This trait can be used with `#[derive]`. When `derive`d on structs, two @@ -939,6 +958,25 @@ pub macro Ord($item:item) { /// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these /// methods. /// +/// ## Cross-crate considerations +/// +/// Upholding the requirements stated above can become tricky when one crate implements `PartialOrd` +/// for a type of another crate (i.e., to allow comparing one of its own types with a type from the +/// standard library). The recommendation is to never implement this trait for a foreign type. In +/// other words, such a crate should do `impl PartialOrd for LocalType`, but it should +/// *not* do `impl PartialOrd for ForeignType`. +/// +/// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local +/// types `T`, you may assue that no other crate will add `impl`s that allow comparing `T < U`. In +/// other words, if other crates add `impl`s that allow building longer transitive chains `U1 < ... +/// < T < V1 < ...`, then all the types that appear to the right of `T` must be types that the crate +/// defining `T` already knows about. This rules out transitive chains where downstream crates can +/// add new `impl`s that "stitch together" comparisons of foreign types in ways that violate +/// transitivity. +/// +/// Not having such foreign `impl`s also avoids forward compatibility issues where one crate adding +/// more `PartialOrd` implementations can cause build failures in downstream crates. +/// /// ## Corollaries /// /// The following corollaries follow from the above requirements: From 7ac4515dde285decf97985107f154bf9e08b4a7e Mon Sep 17 00:00:00 2001 From: Brian Romanowski Date: Sun, 31 Dec 2023 15:09:32 -0600 Subject: [PATCH 007/246] Clarify ambiguity in select_nth_unstable docs --- library/core/src/slice/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b14d9712794bc..7882ddcdc3064 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3047,7 +3047,7 @@ impl [T] { sort::quicksort(self, |a, b| f(a).lt(&f(b))); } - /// Reorder the slice such that the element at `index` is at its final sorted position. + /// Reorder the slice such that the element at `index` after the reordering is at its final sorted position. /// /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index`. Additionally, this reordering is @@ -3075,7 +3075,7 @@ impl [T] { /// # Examples /// /// ``` - /// let mut v = [-5i32, 4, 1, -3, 2]; + /// let mut v = [-5i32, 4, 2, -3, 1]; /// /// // Find the median /// v.select_nth_unstable(2); @@ -3096,8 +3096,8 @@ impl [T] { select::partition_at_index(self, index, T::lt) } - /// Reorder the slice with a comparator function such that the element at `index` is at its - /// final sorted position. + /// Reorder the slice with a comparator function such that the element at `index` after the reordering is at + /// its final sorted position. /// /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index` using the comparator function. @@ -3126,7 +3126,7 @@ impl [T] { /// # Examples /// /// ``` - /// let mut v = [-5i32, 4, 1, -3, 2]; + /// let mut v = [-5i32, 4, 2, -3, 1]; /// /// // Find the median as if the slice were sorted in descending order. /// v.select_nth_unstable_by(2, |a, b| b.cmp(a)); @@ -3151,8 +3151,8 @@ impl [T] { select::partition_at_index(self, index, |a: &T, b: &T| compare(a, b) == Less) } - /// Reorder the slice with a key extraction function such that the element at `index` is at its - /// final sorted position. + /// Reorder the slice with a key extraction function such that the element at `index` after the reordering is + /// at its final sorted position. /// /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index` using the key extraction function. From 16e117cf964064f8f70ab2e55f24ed37e1e9a4ee Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Fri, 5 Jan 2024 02:52:37 +0000 Subject: [PATCH 008/246] Remove outdated references to `librustc_middle`. --- compiler/rustc_const_eval/src/const_eval/error.rs | 4 +--- compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_error_codes/src/error_codes/E0264.md | 2 +- compiler/rustc_errors/src/lib.rs | 3 ++- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/tests.rs | 4 ++-- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index ef39d13d78ab4..c5f6aff24d34a 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -50,9 +50,7 @@ impl MachineStopType for ConstEvalErrKind { } } -// The errors become `MachineStop` with plain strings when being raised. -// `ConstEvalErr` (in `librustc_middle/mir/interpret/error.rs`) knows to -// handle these. +/// The errors become [`InterpError::MachineStop`] when being raised. impl<'tcx> Into> for ConstEvalErrKind { fn into(self) -> InterpErrorInfo<'tcx> { err_machine_stop!(self).into() diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 93b4032c31089..f7d1352f38701 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -147,7 +147,7 @@ pub fn make_display(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl Printer { f } } -// See comments in src/librustc_middle/lib.rs +// See comments in compiler/rustc_middle/src/tests.rs #[doc(hidden)] pub fn __noop_fix_for_27438() {} diff --git a/compiler/rustc_error_codes/src/error_codes/E0264.md b/compiler/rustc_error_codes/src/error_codes/E0264.md index d790607622992..33ddf3405acca 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0264.md +++ b/compiler/rustc_error_codes/src/error_codes/E0264.md @@ -13,7 +13,7 @@ extern "C" { ``` A list of available external lang items is available in -`src/librustc_middle/middle/weak_lang_items.rs`. Example: +`compiler/rustc_hir/src/weak_lang_items.rs`. Example: ``` #![feature(lang_items)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 6707e17e90f4a..7a85f3be74e0b 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -639,7 +639,8 @@ impl DiagCtxt { } // This is here to not allow mutation of flags; - // as of this writing it's only used in tests in librustc_middle. + // as of this writing it's used in Session::consider_optimizing and + // in tests in rustc_interface. pub fn can_emit_warnings(&self) -> bool { self.inner.borrow_mut().flags.can_emit_warnings } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8d2f2aaca5574..9e10c036b4531 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -72,7 +72,7 @@ use crate::nonstandard_style::{method_context, MethodLateContext}; use std::fmt::Write; -// hardwired lints from librustc_middle +// hardwired lints from rustc_lint_defs pub use rustc_session::lint::builtin::*; declare_lint! { diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 52fd494a10db0..f3172cb2bc804 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -94,7 +94,7 @@ macro_rules! arena_types { // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena - // (during lowering) and the `librustc_middle` arena (for decoding MIR) + // (during lowering) and the `rustc_middle` arena (for decoding MIR) [decode] asm_template: rustc_ast::InlineAsmTemplatePiece, [decode] used_trait_imports: rustc_data_structures::unord::UnordSet, [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet, diff --git a/compiler/rustc_middle/src/tests.rs b/compiler/rustc_middle/src/tests.rs index 757e0bd3bfbf9..49960cc0bb2a2 100644 --- a/compiler/rustc_middle/src/tests.rs +++ b/compiler/rustc_middle/src/tests.rs @@ -1,7 +1,7 @@ use super::*; -// FIXME(#27438): right now the unit tests of librustc_middle don't refer to any actual -// functions generated in librustc_data_structures (all +// FIXME(#27438): right now the unit tests of rustc_middle don't refer to any actual +// functions generated in rustc_data_structures (all // references are through generic functions), but statics are // referenced from time to time. Due to this bug we won't // actually correctly link in the statics unless we also From 1eaeaaf08b7135fd8d41339b90fdb6d189c89d69 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sun, 7 Jan 2024 21:16:22 -0800 Subject: [PATCH 009/246] Add FileCheck for array_index.rs, boolean_identities.rs and cast.rs --- tests/mir-opt/dataflow-const-prop/array_index.rs | 12 +++++++++++- .../dataflow-const-prop/boolean_identities.rs | 5 ++++- tests/mir-opt/dataflow-const-prop/cast.rs | 8 +++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs index 3d420f930076d..42c99df969e37 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/array_index.rs @@ -1,9 +1,19 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR array_index.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main() -> () { fn main() { + // CHECK: let mut [[array_lit:_.*]]: [u32; 4]; + // CHECK: debug x => [[x:_.*]]; + let x: u32 = [0, 1, 2, 3][2]; + // CHECK: bb{{[0-9]+}}: { + // CHECK: [[array_lit]] = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; + // CHECK: [[index:_.*]] = const 2_usize; + // CHECK: bb{{[0-9]+}}: { + // CHECK-NOT: [[x]] = [[array_lit]][[[index]]]; + // CHECK: [[x]] = [[array_lit]][2 of 3]; } diff --git a/tests/mir-opt/dataflow-const-prop/boolean_identities.rs b/tests/mir-opt/dataflow-const-prop/boolean_identities.rs index 2605c7019e6f4..93e9b8d52fc2e 100644 --- a/tests/mir-opt/dataflow-const-prop/boolean_identities.rs +++ b/tests/mir-opt/dataflow-const-prop/boolean_identities.rs @@ -1,11 +1,14 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR boolean_identities.test.DataflowConstProp.diff + +// CHECK-LABEL: fn test( pub fn test(x: bool, y: bool) -> bool { (y | true) & (x & false) + // CHECK: _0 = const false; } +// CHECK-LABEL: fn main( fn main() { test(true, false); } diff --git a/tests/mir-opt/dataflow-const-prop/cast.rs b/tests/mir-opt/dataflow-const-prop/cast.rs index c87872609dcf7..298ff49803936 100644 --- a/tests/mir-opt/dataflow-const-prop/cast.rs +++ b/tests/mir-opt/dataflow-const-prop/cast.rs @@ -1,8 +1,14 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR cast.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + + // CHECK: [[a]] = const 257_i32; let a = 257; + // CHECK: [[b]] = const 2_u8; let b = a as u8 + 1; } From e05c779ee30fc7d2bdbb41ae95dd7e5b7d404621 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sun, 7 Jan 2024 21:16:55 -0800 Subject: [PATCH 010/246] Add FileCheck for checked.rs and default_boxed_slice.rs. --- tests/mir-opt/dataflow-const-prop/checked.rs | 17 ++++++++++++++++- .../dataflow-const-prop/default_boxed_slice.rs | 13 ++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs index f7fac8890a057..7350e5fb3d83a 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.rs +++ b/tests/mir-opt/dataflow-const-prop/checked.rs @@ -1,15 +1,30 @@ -// skip-filecheck // unit-test: DataflowConstProp // compile-flags: -Coverflow-checks=on // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR checked.main.DataflowConstProp.diff #[allow(arithmetic_overflow)] + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: debug d => [[d:_.*]]; + // CHECK: debug e => [[e:_.*]]; + + // CHECK: [[a]] = const 1_i32; let a = 1; + + // CHECK: [[b]] = const 2_i32; let b = 2; + + // CHECK: [[c]] = const 3_i32; let c = a + b; + // CHECK: [[d]] = const _; let d = i32::MAX; + + // CHECK: [[e]] = const i32::MIN; let e = d + 1; } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs index 8006bd510e150..5917403450356 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // compile-flags: -Zmir-enable-passes=+GVN,+Inline // ignore-debug assertions change the output MIR @@ -11,8 +10,20 @@ struct A { // EMIT_MIR default_boxed_slice.main.GVN.diff // EMIT_MIR default_boxed_slice.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { // ConstProp will create a constant of type `Box<[bool]>`. // Verify that `DataflowConstProp` does not ICE trying to dereference it directly. + + // CHECK: debug a => [[a:_.*]]; + // CHECK: scope {{[0-9]+}} (inlined as Default>::default) { + // CHECK: scope {{[0-9]+}} (inlined Unique::<[bool; 0]>::dangling) { + // CHECK: scope {{[0-9]+}} (inlined NonNull::<[bool; 0]>::dangling) { + // We may check other inlined functions as well... + + // CHECK: bb{{[0-9]+}}: { + // CHECK: [[box_obj:_.*]] = Box::<[bool]>(_3, const std::alloc::Global); + // CHECK: [[a]] = A { foo: move [[box_obj]] }; let a: A = A { foo: Box::default() }; } From 33e5d851a923ab46544d2cda70f80a59e4c1398c Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sun, 7 Jan 2024 22:03:42 -0800 Subject: [PATCH 011/246] Add FileCheck for enum.rs --- ...enum.constant.DataflowConstProp.64bit.diff | 4 +- ...enum.multiple.DataflowConstProp.32bit.diff | 2 +- ...enum.multiple.DataflowConstProp.64bit.diff | 2 +- tests/mir-opt/dataflow-const-prop/enum.rs | 72 ++++++++++++++++--- .../enum.simple.DataflowConstProp.32bit.diff | 4 +- .../enum.simple.DataflowConstProp.64bit.diff | 4 +- .../enum.statics.DataflowConstProp.32bit.diff | 16 ++--- .../enum.statics.DataflowConstProp.64bit.diff | 16 ++--- 8 files changed, 86 insertions(+), 34 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff index 07ac5b72e244c..f50a763ef9a05 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff index 775325c4d0626..6bf702b856815 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff @@ -14,7 +14,7 @@ let _6: u8; let _8: u8; scope 2 { - debug x => _6; + debug x2 => _6; let _9: u8; scope 4 { debug y => _9; diff --git a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff index 775325c4d0626..6bf702b856815 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff @@ -14,7 +14,7 @@ let _6: u8; let _8: u8; scope 2 { - debug x => _6; + debug x2 => _6; let _9: u8; scope 4 { debug y => _9; diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index e35c0e6e85bed..f33e424034440 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH @@ -13,27 +12,66 @@ enum E { } // EMIT_MIR enum.simple.DataflowConstProp.diff + +// CHECK-LABEL: fn simple( fn simple() { + // CHECK: debug e => [[e:_.*]]; + // CHECK: debug x => [[x:_.*]]; + // CHECK: [[e]] = const E::V1(0_i32); let e = E::V1(0); - let x = match e { E::V1(x) => x, E::V2(x) => x }; + + // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb:[0-9]+]], 1: bb1, otherwise: bb2]; + // CHECK: bb[[target_bb]]: { + // CHECK: [[x]] = const 0_i32; + let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; } // EMIT_MIR enum.constant.DataflowConstProp.diff + +// CHECK-LABEL: fn constant( fn constant() { + // CHECK: debug e => [[e:_.*]]; + // CHECK: debug x => [[x:_.*]]; const C: E = E::V1(0); + + // CHECK: [[e]] = const _; let e = C; - let x = match e { E::V1(x) => x, E::V2(x) => x }; + // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb:[0-9]+]], 1: bb1, otherwise: bb2]; + // CHECK: bb[[target_bb]]: { + // CHECK: [[x]] = const 0_i32; + let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; } // EMIT_MIR enum.statics.DataflowConstProp.diff + +// CHECK-LABEL: fn statics( fn statics() { + // CHECK: debug e1 => [[e1:_.*]]; + // CHECK: debug x1 => [[x1:_.*]]; + // CHECK: debug e2 => [[e2:_.*]]; + // CHECK: debug x2 => [[x2:_.*]]; + static C: E = E::V1(0); - let e = C; - let x = match e { E::V1(x) => x, E::V2(x) => x }; + + // CHECK: [[e1]] = const E::V1(0_i32); + let e1 = C; + // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb1:[0-9]+]], 1: bb1, otherwise: bb2]; + // CHECK: bb[[target_bb]]: { + // CHECK: [[x1]] = const 0_i32; + let x1 = match e1 { E::V1(x11) => x11, E::V2(x12) => x12 }; static RC: &E = &E::V2(4); - let e = RC; - let x = match e { E::V1(x) => x, E::V2(x) => x }; + + // CHECK: [[t:_.*]] = const {alloc2: &&E}; + // CHECK: [[e2]] = (*[[t]]); + let e2 = RC; + // CHECK: switchInt(move _{{[0-9]+}}) -> [0: bb{{[0-9]+}}, 1: bb{{[0-9]+}}, otherwise: bb{{[0-9]+}}]; + // FIXME: add checks for x2. Currently, their MIRs are not symmetric in the two + // switch branches. + // One is `_9 = &(*_12) and another is `_9 = _11`. It is different from what we can + // get by printing MIR directly. It is better to check if there are any bugs in the + // MIR passes around this stage. + let x2 = match e2 { E::V1(x21) => x21, E::V2(x22) => x22 }; } #[rustc_layout_scalar_valid_range_start(1)] @@ -41,6 +79,8 @@ fn statics() { struct NonZeroUsize(usize); // EMIT_MIR enum.mutate_discriminant.DataflowConstProp.diff + +// CHECK-LABEL: fn mutate_discriminant( #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn mutate_discriminant() -> u8 { mir!( @@ -50,7 +90,11 @@ fn mutate_discriminant() -> u8 { // This assignment overwrites the niche in which the discriminant is stored. place!(Field(Field(Variant(x, 1), 0), 0)) = 0_usize; // So we cannot know the value of this discriminant. + + // CHECK: [[a:_.*]] = discriminant(_{{[0-9]*}}); let a = Discriminant(x); + + // CHECK: switchInt([[a]]) -> [0: bb{{[0-9]+}}, otherwise: bb{{[0-9]+}}]; match a { 0 => bb1, _ => bad, @@ -68,18 +112,26 @@ fn mutate_discriminant() -> u8 { } // EMIT_MIR enum.multiple.DataflowConstProp.diff +// CHECK-LABEL: fn multiple( fn multiple(x: bool, i: u8) { + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug e => [[e:_.*]]; + // CHECK: debug x2 => [[x2:_.*]]; let e = if x { + // CHECK: [[e]] = Option::::Some(move _{{[0-9]+}}); Some(i) } else { + // CHECK: [[e]] = Option::::None; None }; // The dataflow state must have: // discriminant(e) => Top // (e as Some).0 => Top - let x = match e { Some(i) => i, None => 0 }; - // Therefore, `x` should be `Top` here, and no replacement shall happen. - let y = x; + // CHECK: [[x2]] = const 0_u8; + // CHECK: [[x2]] = _{{[0-9]+}} + let x2 = match e { Some(i) => i, None => 0 }; + // Therefore, `x2` should be `Top` here, and no replacement shall happen. + let y = x2; } fn main() { diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff index 798b0c041b4ec..b31f98460e45b 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff index 798b0c041b4ec..b31f98460e45b 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index 053981abea3ec..44e8d39cca333 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -9,34 +9,34 @@ let mut _8: &&E; let mut _10: isize; scope 1 { - debug e => _1; + debug e1 => _1; let _3: i32; let _5: i32; let _6: i32; scope 2 { - debug x => _3; + debug x1 => _3; let _7: &E; scope 5 { - debug e => _7; + debug e2 => _7; let _9: &i32; let _11: &i32; let _12: &i32; scope 6 { - debug x => _9; + debug x2 => _9; } scope 7 { - debug x => _11; + debug x21 => _11; } scope 8 { - debug x => _12; + debug x22 => _12; } } } scope 3 { - debug x => _5; + debug x11 => _5; } scope 4 { - debug x => _6; + debug x12 => _6; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index d862bd93ff577..ac4ca086d0fed 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -9,34 +9,34 @@ let mut _8: &&E; let mut _10: isize; scope 1 { - debug e => _1; + debug e1 => _1; let _3: i32; let _5: i32; let _6: i32; scope 2 { - debug x => _3; + debug x1 => _3; let _7: &E; scope 5 { - debug e => _7; + debug e2 => _7; let _9: &i32; let _11: &i32; let _12: &i32; scope 6 { - debug x => _9; + debug x2 => _9; } scope 7 { - debug x => _11; + debug x21 => _11; } scope 8 { - debug x => _12; + debug x22 => _12; } } } scope 3 { - debug x => _5; + debug x11 => _5; } scope 4 { - debug x => _6; + debug x12 => _6; } } From 24aefa0e5d134526c8e29c5603dcb4d42637968a Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Mon, 8 Jan 2024 16:58:58 -0800 Subject: [PATCH 012/246] Add FileCheck for if.rs, inherit_overflow.rs, issue_81605.rs --- tests/mir-opt/dataflow-const-prop/if.rs | 18 +++++++++++++++++- .../dataflow-const-prop/inherit_overflow.rs | 5 ++++- .../mir-opt/dataflow-const-prop/issue_81605.rs | 5 ++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/if.rs b/tests/mir-opt/dataflow-const-prop/if.rs index 72aabbccf56c8..28e0ee9c622f5 100644 --- a/tests/mir-opt/dataflow-const-prop/if.rs +++ b/tests/mir-opt/dataflow-const-prop/if.rs @@ -1,12 +1,28 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR if.main.DataflowConstProp.diff +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: debug d => [[d:_.*]]; + // CHECK: debug e => [[e:_.*]]; + let a = 1; + + // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: [[bb_first_true:bb[0-9]+]]]; + // CHECK: [[bb_first_true]]: { + // CHECK: [[b]] = const 2_i32; let b = if a == 1 { 2 } else { 3 }; + + // CHECK: [[c]] = const 3_i32; let c = b + 1; + // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: [[bb_second_true:bb[0-9]+]]]; + // CHECK: [[bb_second_true]]: { + // CHECK: [[d]] = const 1_i32; let d = if a == 1 { a } else { a + 1 }; + + // CHECK: [[e]] = const 2_i32; let e = d + 1; } diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs index 664cbcb2c259f..0a2774c782009 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs @@ -1,11 +1,14 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp // compile-flags: -Zmir-enable-passes=+Inline // EMIT_MIR inherit_overflow.main.DataflowConstProp.diff +// CHECK-LABEL: fn main( fn main() { // After inlining, this will contain a `CheckedBinaryOp`. // Propagating the overflow is ok as codegen will just skip emitting the panic. + + // CHECK: {{_.*}} = const (0_u8, true); + // CHECK-LABEL: assert(!const true, let _ = ::add(255, 1); } diff --git a/tests/mir-opt/dataflow-const-prop/issue_81605.rs b/tests/mir-opt/dataflow-const-prop/issue_81605.rs index 7c5eceb8a2b68..e8a00c72eb66b 100644 --- a/tests/mir-opt/dataflow-const-prop/issue_81605.rs +++ b/tests/mir-opt/dataflow-const-prop/issue_81605.rs @@ -1,9 +1,12 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR issue_81605.f.DataflowConstProp.diff + +// CHECK-LABEL: fn f fn f() -> usize { + // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: {{bb[0-9]+}}]; 1 + if true { 1 } else { 2 } + // CHECK: _0 = const 2_usize; } fn main() { From 9452d7ed1acd62c44dbec775d42f41b508c572bf Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Mon, 8 Jan 2024 20:18:59 -0800 Subject: [PATCH 013/246] Add FileCheck to 3 tests: large_array_index, mult_by_zero, and offset_of --- .../dataflow-const-prop/large_array_index.rs | 10 ++++++- .../dataflow-const-prop/mult_by_zero.rs | 3 +- .../mir-opt/dataflow-const-prop/offset_of.rs | 29 ++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.rs b/tests/mir-opt/dataflow-const-prop/large_array_index.rs index d611a54ba71a2..6b8a0248d19bc 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.rs @@ -1,10 +1,18 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR large_array_index.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { // check that we don't propagate this, because it's too large + + // CHECK: debug x => [[x:_.*]]; + // CHECK: [[array_lit:_.*]] = [const 0_u8; 5000]; + // CHECK: {{_.*}} = const 5000_usize; + // CHECK: {{_.*}} = const true; + // CHECK-LABEL: assert(const true + // CHECK: [[x]] = [[array_lit]][2 of 3]; let x: u8 = [0_u8; 5000][2]; } diff --git a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs index 16a45c8e9fb59..c7e05579e4005 100644 --- a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs +++ b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs @@ -1,9 +1,10 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR mult_by_zero.test.DataflowConstProp.diff +// CHECK-LABEL: fn test fn test(x : i32) -> i32 { x * 0 + // CHECK: _0 = const 0_i32; } fn main() { diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs index e71b3f59ecab3..a2032ea996edd 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.rs +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY @@ -29,18 +28,46 @@ struct Delta { } // EMIT_MIR offset_of.concrete.DataflowConstProp.diff + +// CHECK-LABEL: fn concrete fn concrete() { + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: debug z0 => [[z0:_.*]]; + // CHECK: debug z1 => [[z1:_.*]]; + + // CHECK: [[x]] = must_use::(const 4_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let x = offset_of!(Alpha, x); + + // CHECK: [[y]] = must_use::(const 0_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let y = offset_of!(Alpha, y); + + // CHECK: [[z0]] = must_use::(const 2_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let z0 = offset_of!(Alpha, z.0); + + // CHECK: [[z1]] = must_use::(const 3_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let z1 = offset_of!(Alpha, z.1); } // EMIT_MIR offset_of.generic.DataflowConstProp.diff + +// CHECK-LABEL: generic fn generic() { + // CHECK: debug gx => [[gx:_.*]]; + // CHECK: debug gy => [[gy:_.*]]; + // CHECK: debug dx => [[dx:_.*]]; + // CHECK: debug dy => [[dy:_.*]]; + + // CHECK: [[gx]] = must_use::(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; let gx = offset_of!(Gamma, x); + + // CHECK: [[gy]] = must_use::(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; let gy = offset_of!(Gamma, y); + + // CHECK: [[dx]] = must_use::(const 0_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let dx = offset_of!(Delta, x); + + // CHECK: [[dy]] = must_use::(const 2_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let dy = offset_of!(Delta, y); } From e9152e2b6c95aad0f3c89af8b0f98a0cbf4f45c7 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Mon, 8 Jan 2024 20:19:59 -0800 Subject: [PATCH 014/246] Add FileCheck to 3 tests: ref_without_sb, repeat, repr_transparent --- tests/mir-opt/dataflow-const-prop/ref_without_sb.rs | 11 ++++++++++- tests/mir-opt/dataflow-const-prop/repeat.rs | 10 +++++++++- tests/mir-opt/dataflow-const-prop/repr_transparent.rs | 9 ++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs index 2851c0590ad5f..fb66cda38ddbd 100644 --- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs +++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp @@ -9,11 +8,21 @@ fn escape(x: &T) {} fn some_function() {} // EMIT_MIR ref_without_sb.main.DataflowConstProp.diff +// CHECK-LABEL: fn main fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + let mut a = 0; + + // CHECK: {{_[0-9]+}} = escape::(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; escape(&a); a = 1; + + // CHECK: {{_[0-9]+}} = some_function() -> [return: {{bb[0-9]+}}, unwind continue]; some_function(); // This should currently not be propagated. + + // CHECK: [[b]] = [[a]]; let b = a; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.rs b/tests/mir-opt/dataflow-const-prop/repeat.rs index b824481948116..5d1c1a3edb695 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.rs +++ b/tests/mir-opt/dataflow-const-prop/repeat.rs @@ -1,9 +1,17 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR repeat.main.DataflowConstProp.diff +// CHECK-LABEL: fn main fn main() { + // CHECK: debug x => [[x:_.*]]; + + // CHECK: {{_[0-9]+}} = const 8_usize; + // CHECK: {{_[0-9]+}} = const true; + // CHECK-LABEL: assert(const true + + // CHECK: {{_[0-9]+}} = {{_[0-9]+}}[2 of 3]; + // CHECK: [[x]] = Add(move {{_[0-9]+}}, const 0_u32); let x: u32 = [42; 8][2] + 0; } diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.rs b/tests/mir-opt/dataflow-const-prop/repr_transparent.rs index 8cbed6fbb624d..d007301e568b1 100644 --- a/tests/mir-opt/dataflow-const-prop/repr_transparent.rs +++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // The struct has scalar ABI, but is not a scalar type. @@ -7,7 +6,15 @@ struct I32(i32); // EMIT_MIR repr_transparent.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + + // CHECK: [[x]] = const I32(0_i32); let x = I32(0); + + // CHECK: [[y]] = const I32(0_i32); let y = I32(x.0 + x.0); } From 3ab1d5d4506924b6d020c8edf539d2be6b7bb9e9 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Mon, 8 Jan 2024 20:20:27 -0800 Subject: [PATCH 015/246] Add FileCheck to 3 tests: self_assign_add, self_assign, and sibling_ptr --- tests/mir-opt/dataflow-const-prop/self_assign.rs | 15 ++++++++++++++- .../dataflow-const-prop/self_assign_add.rs | 8 +++++++- tests/mir-opt/dataflow-const-prop/sibling_ptr.rs | 7 ++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/self_assign.rs b/tests/mir-opt/dataflow-const-prop/self_assign.rs index c5866c4a9fd98..7d58b972d655b 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign.rs +++ b/tests/mir-opt/dataflow-const-prop/self_assign.rs @@ -1,13 +1,26 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR self_assign.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + let mut a = 0; + + // CHECK: [[a]] = Add(move {{_[0-9]+}}, const 1_i32); a = a + 1; + + // CHECK: [[a]] = move {{_[0-9]+}}; a = a; + // CHECK: [[b]] = &[[a]]; let mut b = &a; + + // CHECK: [[b]] = move {{_[0-9]+}}; b = b; + + // CHECK: [[a]] = move {{_[0-9]+}}; a = *b; } diff --git a/tests/mir-opt/dataflow-const-prop/self_assign_add.rs b/tests/mir-opt/dataflow-const-prop/self_assign_add.rs index cfe1458e44be7..09be3865d60b3 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign_add.rs +++ b/tests/mir-opt/dataflow-const-prop/self_assign_add.rs @@ -1,9 +1,15 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR self_assign_add.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug a => [[a:_.*]]; let mut a = 0; + + // CHECK: [[a]] = const 1_i32; a += 1; + + // CHECK: [[a]] = const 2_i32; a += 1; } diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs index 68aff528695d5..6e39e39839410 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // This attempts to modify `x.1` via a pointer derived from `addr_of_mut!(x.0)`. // According to Miri, that is UB. However, T-opsem has not finalized that @@ -10,11 +9,17 @@ // unit-test: DataflowConstProp // EMIT_MIR sibling_ptr.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug x1 => [[x1:_[0-9]+]]; + let mut x: (u8, u8) = (0, 0); unsafe { let p = std::ptr::addr_of_mut!(x.0); *p.add(1) = 1; } + + // CHECK: [[x1]] = ({{_[0-9]+}}.1: u8); let x1 = x.1; // should not be propagated } From d765e3ae1faf4786b56da542c9dc5fbfc18162d8 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Mon, 8 Jan 2024 20:20:53 -0800 Subject: [PATCH 016/246] Add FileCheck to slice_len.rs --- tests/mir-opt/dataflow-const-prop/slice_len.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs index 86266ef5d4e60..cd63980949638 100644 --- a/tests/mir-opt/dataflow-const-prop/slice_len.rs +++ b/tests/mir-opt/dataflow-const-prop/slice_len.rs @@ -1,13 +1,23 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp // compile-flags: -Zmir-enable-passes=+InstSimplify // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR slice_len.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug local => [[local:_[0-9]+]]; + // CHECK: debug constant => [[constant:_[0-9]+]]; + + // CHECK: {{_[0-9]+}} = const 3_usize; + // CHECK: {{_[0-9]+}} = const true; + + // CHECK: [[local]] = (*{{_[0-9]+}})[1 of 2]; let local = (&[1u32, 2, 3] as &[u32])[1]; const SLICE: &[u32] = &[1, 2, 3]; + + // CHECK: [[constant]] = (*{{_[0-9]+}})[1 of 2]; let constant = SLICE[1]; } From 732f6a1303c4e3f9a354221e76e065571b2f1e37 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Mon, 8 Jan 2024 20:21:06 -0800 Subject: [PATCH 017/246] Add FileCheck to struct.rs --- .../struct.main.DataflowConstProp.32bit.diff | 24 ++++---- .../struct.main.DataflowConstProp.64bit.diff | 24 ++++---- tests/mir-opt/dataflow-const-prop/struct.rs | 55 ++++++++++++++++--- 3 files changed, 72 insertions(+), 31 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 0f461f515fdd0..c486281d6f8d7 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -37,16 +37,16 @@ let _8: std::option::Option; let _9: &[f32]; scope 4 { - debug a => _7; - debug b => _8; - debug c => _9; + debug a1 => _7; + debug b1 => _8; + debug c1 => _9; let _11: f32; let _12: std::option::Option; let _13: &[f32]; scope 5 { - debug a => _11; - debug b => _12; - debug c => _13; + debug a2 => _11; + debug b2 => _12; + debug c2 => _13; let _15: SmallStruct; scope 6 { debug ss => _15; @@ -54,16 +54,16 @@ let _20: std::option::Option; let _21: &[f32]; scope 7 { - debug a => _19; - debug b => _20; - debug c => _21; + debug a3 => _19; + debug b3 => _20; + debug c3 => _21; let _23: f32; let _24: std::option::Option; let _25: &[f32]; scope 8 { - debug a => _23; - debug b => _24; - debug c => _25; + debug a4 => _23; + debug b4 => _24; + debug c4 => _25; let _27: BigStruct; scope 9 { debug bs => _27; diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index 3c40ec8bfb450..7ea53d157334d 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -37,16 +37,16 @@ let _8: std::option::Option; let _9: &[f32]; scope 4 { - debug a => _7; - debug b => _8; - debug c => _9; + debug a1 => _7; + debug b1 => _8; + debug c1 => _9; let _11: f32; let _12: std::option::Option; let _13: &[f32]; scope 5 { - debug a => _11; - debug b => _12; - debug c => _13; + debug a2 => _11; + debug b2 => _12; + debug c2 => _13; let _15: SmallStruct; scope 6 { debug ss => _15; @@ -54,16 +54,16 @@ let _20: std::option::Option; let _21: &[f32]; scope 7 { - debug a => _19; - debug b => _20; - debug c => _21; + debug a3 => _19; + debug b3 => _20; + debug c3 => _21; let _23: f32; let _24: std::option::Option; let _25: &[f32]; scope 8 { - debug a => _23; - debug b => _24; - debug c => _25; + debug a4 => _23; + debug b4 => _24; + debug c4 => _25; let _27: BigStruct; scope 9 { debug bs => _27; diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index 043981a295484..4eec15a7f1630 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH @@ -12,27 +11,69 @@ struct SmallStruct(f32, Option, &'static [f32]); struct BigStruct(f32, Option, &'static [f32]); // EMIT_MIR struct.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug s => [[s:_[0-9]+]]; + // CHECK: debug a => [[a:_[0-9]+]]; + // CHECK: debug b => [[b:_[0-9]+]]; + // CHECK: debug a1 => [[a1:_[0-9]+]]; + // CHECK: debug b1 => [[b1:_[0-9]+]]; + // CHECK: debug c1 => [[c1:_[0-9]+]]; + // CHECK: debug a2 => [[a2:_[0-9]+]]; + // CHECK: debug b2 => [[b2:_[0-9]+]]; + // CHECK: debug c2 => [[c2:_[0-9]+]]; + // CHECK: debug ss => [[ss:_[0-9]+]]; + // CHECK: debug a3 => [[a3:_[0-9]+]]; + // CHECK: debug b3 => [[b3:_[0-9]+]]; + // CHECK: debug c3 => [[c3:_[0-9]+]]; + // CHECK: debug a4 => [[a4:_[0-9]+]]; + // CHECK: debug b4 => [[b4:_[0-9]+]]; + // CHECK: debug c4 => [[c4:_[0-9]+]]; + // CHECK: debug bs => [[bs:_[0-9]+]]; + + // CHECK: [[s]] = const S(1_i32); let mut s = S(1); + + // CHECK: [[a]] = const 3_i32; let a = s.0 + 2; s.0 = 3; + + // CHECK: [[b]] = const 6_i32; let b = a + s.0; const SMALL_VAL: SmallStruct = SmallStruct(4., Some(S(1)), &[]); - let SmallStruct(a, b, c) = SMALL_VAL; + + // CHECK: [[a1]] = const 4f32; + // CHECK: [[b1]] = const Option::::Some(S(1_i32)); + // CHECK: [[c1]] = ({{_[0-9]+}}.2: &[f32]); + let SmallStruct(a1, b1, c1) = SMALL_VAL; static SMALL_STAT: &SmallStruct = &SmallStruct(9., None, &[13.]); - let SmallStruct(a, b, c) = *SMALL_STAT; - let ss = SmallStruct(a, b, c); + // CHECK: [[a2]] = const 9f32; + // CHECK: [[b2]] = ((*{{_[0-9]+}}).1: std::option::Option); + // CHECK: [[c2]] = ((*{{_[0-9]+}}).2: &[f32]); + let SmallStruct(a2, b2, c2) = *SMALL_STAT; + + // CHECK: [[ss]] = SmallStruct(const 9f32, move {{_[0-9]+}}, move {{_[0-9]+}}); + let ss = SmallStruct(a2, b2, c2); const BIG_VAL: BigStruct = BigStruct(25., None, &[]); - let BigStruct(a, b, c) = BIG_VAL; + + // CHECK: [[a3]] = const 25f32; + // CHECK: [[b3]] = ({{_[0-9]+}}.1: std::option::Option); + // CHECK: [[c3]] = ({{_[0-9]+}}.2: &[f32]); + let BigStruct(a3, b3, c3) = BIG_VAL; static BIG_STAT: &BigStruct = &BigStruct(82., Some(S(35)), &[45., 72.]); - let BigStruct(a, b, c) = *BIG_STAT; + // CHECK: [[a4]] = const 82f32; + // CHECK: [[b4]] = const Option::::Some(S(35_i32)); + // CHECK: [[c4]] = ((*{{_[0-9]+}}).2: &[f32]); + let BigStruct(a4, b4, c4) = *BIG_STAT; // We arbitrarily limit the size of synthetized values to 4 pointers. // `BigStruct` can be read, but we will keep a MIR aggregate for this. - let bs = BigStruct(a, b, c); + // CHECK: [[bs]] = BigStruct(const 82f32, const Option::::Some(S(35_i32)), move {{_[0-9]+}}); + let bs = BigStruct(a4, b4, c4); } From 1adda9a170085823f43672e60c19be29a4deb18f Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Mon, 8 Jan 2024 20:21:23 -0800 Subject: [PATCH 018/246] Add FileCheck to terminator.rs and tuple.rs --- tests/mir-opt/dataflow-const-prop/terminator.rs | 4 +++- tests/mir-opt/dataflow-const-prop/tuple.rs | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/terminator.rs b/tests/mir-opt/dataflow-const-prop/terminator.rs index 92a42f22c218f..985eddad26440 100644 --- a/tests/mir-opt/dataflow-const-prop/terminator.rs +++ b/tests/mir-opt/dataflow-const-prop/terminator.rs @@ -1,12 +1,14 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp fn foo(n: i32) {} // EMIT_MIR terminator.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { let a = 1; // Checks that we propagate into terminators. + // CHECK: {{_[0-9]+}} = foo(const 2_i32) -> [return: {{bb[0-9]+}}, unwind continue]; foo(a + 1); } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.rs b/tests/mir-opt/dataflow-const-prop/tuple.rs index bb706eafe8885..bd5adeda8b3dc 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.rs +++ b/tests/mir-opt/dataflow-const-prop/tuple.rs @@ -1,13 +1,27 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR tuple.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug a => [[a:_[0-9]+]]; + // CHECK: debug b => [[b:_[0-9]+]]; + // CHECK: debug c => [[c:_[0-9]+]]; + // CHECK: debug d => [[d:_[0-9]+]]; + + // CHECK: [[a]] = const (1_i32, 2_i32); let mut a = (1, 2); + + // CHECK: [[b]] = const 6_i32; let b = a.0 + a.1 + 3; + + // CHECK: [[a]] = const (2_i32, 3_i32); a = (2, 3); + + // CHECK: [[c]] = const 11_i32; let c = a.0 + a.1 + b; + // CHECK: [[d]] = (const 6_i32, const (2_i32, 3_i32), const 11_i32); let d = (b, a, c); } From 7135168d0874ee5e0485bb31d89ab69966a48337 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sun, 7 Jan 2024 22:03:42 -0800 Subject: [PATCH 019/246] Add FileCheck for enum.rs --- .../enum.constant.DataflowConstProp.32bit.diff | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff index 07ac5b72e244c..f50a763ef9a05 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } From 6001c50cac411d7a889c4dfd176d6dda8b4b181f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 7 Dec 2023 09:53:08 +1100 Subject: [PATCH 020/246] Detect `NulInCStr` error earlier. By making it an `EscapeError` instead of a `LitError`. This makes it like the other errors produced when checking string literals contents, e.g. for invalid escape sequences or bare CR chars. NOTE: this means these errors are issued earlier, before expansion, which changes behaviour. It will be possible to move the check back to the later point if desired. If that happens, it's likely that all the string literal contents checks will be delayed together. One nice thing about this: the old approach had some code in `report_lit_error` to calculate the span of the nul char from a range. This code used a hardwired `+2` to account for the `c"` at the start of a C string literal, but this should have changed to a `+3` for raw C string literals to account for the `cr"`, which meant that the caret in `cr"` nul error messages was one short of where it should have been. The new approach doesn't need any of this and avoids the off-by-one error. --- crates/parser/src/lexed_str.rs | 1 + crates/syntax/src/validation.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index b9e7566fdf9bc..3753a1beb7a8e 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -371,6 +371,7 @@ fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str { "non-ASCII character in byte string literal" } EscapeError::NonAsciiCharInByte => "non-ASCII character in raw byte string literal", + EscapeError::NulInCStr => "null character in C string literal", EscapeError::UnskippedWhitespaceWarning => "", EscapeError::MultipleSkippedLinesWarning => "", } diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index eabbda2c3983c..0504f67c9dc7e 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -106,6 +106,9 @@ fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> (&'static str, EE::NonAsciiCharInByte => { "Byte literals must not contain non-ASCII characters" } + EE::NulInCStr => { + "C strings literals must not contain null characters" + } EE::UnskippedWhitespaceWarning => "Whitespace after this escape is not skipped", EE::MultipleSkippedLinesWarning => "Multiple lines are skipped by this escape", From d63f10b7addc4f5c5528b76cedb41433a275eed3 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Thu, 11 Jan 2024 23:22:33 -0800 Subject: [PATCH 021/246] resolve code reviews --- .../dataflow-const-prop/array_index.rs | 7 +-- .../dataflow-const-prop/boolean_identities.rs | 4 ++ tests/mir-opt/dataflow-const-prop/checked.rs | 2 + .../default_boxed_slice.rs | 5 +- tests/mir-opt/dataflow-const-prop/enum.rs | 23 ++++---- tests/mir-opt/dataflow-const-prop/if.rs | 6 +-- .../dataflow-const-prop/issue_81605.rs | 10 +++- .../dataflow-const-prop/large_array_index.rs | 2 +- .../dataflow-const-prop/mult_by_zero.rs | 2 +- .../mir-opt/dataflow-const-prop/offset_of.rs | 20 +++---- .../dataflow-const-prop/ref_without_sb.rs | 8 +-- tests/mir-opt/dataflow-const-prop/repeat.rs | 14 +++-- .../dataflow-const-prop/repr_transparent.rs | 2 +- .../dataflow-const-prop/self_assign.rs | 10 ++-- .../dataflow-const-prop/self_assign_add.rs | 2 +- .../dataflow-const-prop/sibling_ptr.rs | 6 +-- .../mir-opt/dataflow-const-prop/slice_len.rs | 25 ++++++--- tests/mir-opt/dataflow-const-prop/struct.rs | 52 +++++++++---------- .../mir-opt/dataflow-const-prop/terminator.rs | 4 +- tests/mir-opt/dataflow-const-prop/tuple.rs | 10 ++-- 20 files changed, 118 insertions(+), 96 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs index 42c99df969e37..4b070e1d6d6f6 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/array_index.rs @@ -10,10 +10,7 @@ fn main() { // CHECK: debug x => [[x:_.*]]; let x: u32 = [0, 1, 2, 3][2]; - // CHECK: bb{{[0-9]+}}: { - // CHECK: [[array_lit]] = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; - // CHECK: [[index:_.*]] = const 2_usize; - // CHECK: bb{{[0-9]+}}: { - // CHECK-NOT: [[x]] = [[array_lit]][[[index]]]; + // CHECK: [[array_lit]] = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; + // CHECK-LABEL: assert(const true, // CHECK: [[x]] = [[array_lit]][2 of 3]; } diff --git a/tests/mir-opt/dataflow-const-prop/boolean_identities.rs b/tests/mir-opt/dataflow-const-prop/boolean_identities.rs index 93e9b8d52fc2e..c9be1d65b0302 100644 --- a/tests/mir-opt/dataflow-const-prop/boolean_identities.rs +++ b/tests/mir-opt/dataflow-const-prop/boolean_identities.rs @@ -4,8 +4,12 @@ // CHECK-LABEL: fn test( pub fn test(x: bool, y: bool) -> bool { + // CHECK-NOT: BitAnd( + // CHECK-NOT: BitOr( (y | true) & (x & false) // CHECK: _0 = const false; + // CHECK-NOT: BitAnd( + // CHECK-NOT: BitOr( } // CHECK-LABEL: fn main( diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs index 7350e5fb3d83a..45331f91323e4 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.rs +++ b/tests/mir-opt/dataflow-const-prop/checked.rs @@ -19,12 +19,14 @@ fn main() { // CHECK: [[b]] = const 2_i32; let b = 2; + // CHECK-LABEL: assert(!const false, // CHECK: [[c]] = const 3_i32; let c = a + b; // CHECK: [[d]] = const _; let d = i32::MAX; + // CHECK-LABEL: assert(!const true, // CHECK: [[e]] = const i32::MIN; let e = d + 1; } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs index 5917403450356..b15809f2510ff 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -17,13 +17,10 @@ fn main() { // Verify that `DataflowConstProp` does not ICE trying to dereference it directly. // CHECK: debug a => [[a:_.*]]; - // CHECK: scope {{[0-9]+}} (inlined as Default>::default) { - // CHECK: scope {{[0-9]+}} (inlined Unique::<[bool; 0]>::dangling) { - // CHECK: scope {{[0-9]+}} (inlined NonNull::<[bool; 0]>::dangling) { // We may check other inlined functions as well... - // CHECK: bb{{[0-9]+}}: { // CHECK: [[box_obj:_.*]] = Box::<[bool]>(_3, const std::alloc::Global); // CHECK: [[a]] = A { foo: move [[box_obj]] }; + // FIXME: we do not have `const Box::<[bool]>` after constprop right now. let a: A = A { foo: Box::default() }; } diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index f33e424034440..26fdda2664a95 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -20,8 +20,8 @@ fn simple() { // CHECK: [[e]] = const E::V1(0_i32); let e = E::V1(0); - // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb:[0-9]+]], 1: bb1, otherwise: bb2]; - // CHECK: bb[[target_bb]]: { + // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb1, otherwise: bb2]; + // CHECK: [[target_bb]]: { // CHECK: [[x]] = const 0_i32; let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; } @@ -36,8 +36,8 @@ fn constant() { // CHECK: [[e]] = const _; let e = C; - // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb:[0-9]+]], 1: bb1, otherwise: bb2]; - // CHECK: bb[[target_bb]]: { + // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb1, otherwise: bb2]; + // CHECK: [[target_bb]]: { // CHECK: [[x]] = const 0_i32; let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; } @@ -55,8 +55,8 @@ fn statics() { // CHECK: [[e1]] = const E::V1(0_i32); let e1 = C; - // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb1:[0-9]+]], 1: bb1, otherwise: bb2]; - // CHECK: bb[[target_bb]]: { + // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb1, otherwise: bb2]; + // CHECK: [[target_bb]]: { // CHECK: [[x1]] = const 0_i32; let x1 = match e1 { E::V1(x11) => x11, E::V2(x12) => x12 }; @@ -65,7 +65,8 @@ fn statics() { // CHECK: [[t:_.*]] = const {alloc2: &&E}; // CHECK: [[e2]] = (*[[t]]); let e2 = RC; - // CHECK: switchInt(move _{{[0-9]+}}) -> [0: bb{{[0-9]+}}, 1: bb{{[0-9]+}}, otherwise: bb{{[0-9]+}}]; + + // CHECK: switchInt({{move _.*}}) -> {{.*}} // FIXME: add checks for x2. Currently, their MIRs are not symmetric in the two // switch branches. // One is `_9 = &(*_12) and another is `_9 = _11`. It is different from what we can @@ -91,10 +92,10 @@ fn mutate_discriminant() -> u8 { place!(Field(Field(Variant(x, 1), 0), 0)) = 0_usize; // So we cannot know the value of this discriminant. - // CHECK: [[a:_.*]] = discriminant(_{{[0-9]*}}); + // CHECK: [[a:_.*]] = discriminant({{_.*}}); let a = Discriminant(x); - // CHECK: switchInt([[a]]) -> [0: bb{{[0-9]+}}, otherwise: bb{{[0-9]+}}]; + // CHECK: switchInt([[a]]) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; match a { 0 => bb1, _ => bad, @@ -118,7 +119,7 @@ fn multiple(x: bool, i: u8) { // CHECK: debug e => [[e:_.*]]; // CHECK: debug x2 => [[x2:_.*]]; let e = if x { - // CHECK: [[e]] = Option::::Some(move _{{[0-9]+}}); + // CHECK: [[e]] = Option::::Some(move {{_.*}}); Some(i) } else { // CHECK: [[e]] = Option::::None; @@ -128,7 +129,7 @@ fn multiple(x: bool, i: u8) { // discriminant(e) => Top // (e as Some).0 => Top // CHECK: [[x2]] = const 0_u8; - // CHECK: [[x2]] = _{{[0-9]+}} + // CHECK: [[x2]] = {{_.*}}; let x2 = match e { Some(i) => i, None => 0 }; // Therefore, `x2` should be `Top` here, and no replacement shall happen. let y = x2; diff --git a/tests/mir-opt/dataflow-const-prop/if.rs b/tests/mir-opt/dataflow-const-prop/if.rs index 28e0ee9c622f5..3400068baba2a 100644 --- a/tests/mir-opt/dataflow-const-prop/if.rs +++ b/tests/mir-opt/dataflow-const-prop/if.rs @@ -10,16 +10,14 @@ fn main() { let a = 1; - // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: [[bb_first_true:bb[0-9]+]]]; - // CHECK: [[bb_first_true]]: { + // CHECK: switchInt(const true) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; // CHECK: [[b]] = const 2_i32; let b = if a == 1 { 2 } else { 3 }; // CHECK: [[c]] = const 3_i32; let c = b + 1; - // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: [[bb_second_true:bb[0-9]+]]]; - // CHECK: [[bb_second_true]]: { + // CHECK: switchInt(const true) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; // CHECK: [[d]] = const 1_i32; let d = if a == 1 { a } else { a + 1 }; diff --git a/tests/mir-opt/dataflow-const-prop/issue_81605.rs b/tests/mir-opt/dataflow-const-prop/issue_81605.rs index e8a00c72eb66b..f13c364279d41 100644 --- a/tests/mir-opt/dataflow-const-prop/issue_81605.rs +++ b/tests/mir-opt/dataflow-const-prop/issue_81605.rs @@ -2,9 +2,15 @@ // EMIT_MIR issue_81605.f.DataflowConstProp.diff -// CHECK-LABEL: fn f +// Plese find the original issue [here](https://github.com/rust-lang/rust/issues/81605). +// This test program comes directly from the issue. Prior to this issue, +// the compiler cannot simplify the return value of `f` into 2. This was +// solved by adding a new MIR constant propagation based on dataflow +// analysis in [#101168](https://github.com/rust-lang/rust/pull/101168). + +// CHECK-LABEL: fn f( fn f() -> usize { - // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: {{bb[0-9]+}}]; + // CHECK: switchInt(const true) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; 1 + if true { 1 } else { 2 } // CHECK: _0 = const 2_usize; } diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.rs b/tests/mir-opt/dataflow-const-prop/large_array_index.rs index 6b8a0248d19bc..fbca411e204d1 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.rs @@ -4,7 +4,7 @@ // EMIT_MIR large_array_index.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // check that we don't propagate this, because it's too large diff --git a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs index c7e05579e4005..be8ce7310564c 100644 --- a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs +++ b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs @@ -1,7 +1,7 @@ // unit-test: DataflowConstProp // EMIT_MIR mult_by_zero.test.DataflowConstProp.diff -// CHECK-LABEL: fn test +// CHECK-LABEL: fn test( fn test(x : i32) -> i32 { x * 0 // CHECK: _0 = const 0_i32; diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs index a2032ea996edd..ff9fe7f2fbd25 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.rs +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -29,45 +29,45 @@ struct Delta { // EMIT_MIR offset_of.concrete.DataflowConstProp.diff -// CHECK-LABEL: fn concrete +// CHECK-LABEL: fn concrete( fn concrete() { // CHECK: debug x => [[x:_.*]]; // CHECK: debug y => [[y:_.*]]; // CHECK: debug z0 => [[z0:_.*]]; // CHECK: debug z1 => [[z1:_.*]]; - // CHECK: [[x]] = must_use::(const 4_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[x]] = must_use::(const 4_usize) -> {{.*}} let x = offset_of!(Alpha, x); - // CHECK: [[y]] = must_use::(const 0_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[y]] = must_use::(const 0_usize) -> {{.*}} let y = offset_of!(Alpha, y); - // CHECK: [[z0]] = must_use::(const 2_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[z0]] = must_use::(const 2_usize) -> {{.*}} let z0 = offset_of!(Alpha, z.0); - // CHECK: [[z1]] = must_use::(const 3_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[z1]] = must_use::(const 3_usize) -> {{.*}} let z1 = offset_of!(Alpha, z.1); } // EMIT_MIR offset_of.generic.DataflowConstProp.diff -// CHECK-LABEL: generic +// CHECK-LABEL: fn generic( fn generic() { // CHECK: debug gx => [[gx:_.*]]; // CHECK: debug gy => [[gy:_.*]]; // CHECK: debug dx => [[dx:_.*]]; // CHECK: debug dy => [[dy:_.*]]; - // CHECK: [[gx]] = must_use::(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[gx]] = must_use::(move {{_.*}}) -> {{.*}} let gx = offset_of!(Gamma, x); - // CHECK: [[gy]] = must_use::(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[gy]] = must_use::(move {{_.*}}) -> {{.*}} let gy = offset_of!(Gamma, y); - // CHECK: [[dx]] = must_use::(const 0_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[dx]] = must_use::(const 0_usize) -> {{.*}} let dx = offset_of!(Delta, x); - // CHECK: [[dy]] = must_use::(const 2_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[dy]] = must_use::(const 2_usize) -> {{.*}} let dy = offset_of!(Delta, y); } diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs index fb66cda38ddbd..7bf2b18407854 100644 --- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs +++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs @@ -8,21 +8,23 @@ fn escape(x: &T) {} fn some_function() {} // EMIT_MIR ref_without_sb.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // CHECK: debug a => [[a:_.*]]; // CHECK: debug b => [[b:_.*]]; let mut a = 0; - // CHECK: {{_[0-9]+}} = escape::(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: {{_.*}} = escape::(move {{_.*}}) -> {{.*}} escape(&a); a = 1; - // CHECK: {{_[0-9]+}} = some_function() -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: {{_.*}} = some_function() -> {{.*}} some_function(); // This should currently not be propagated. + // CHECK-NOT: [[b]] = const // CHECK: [[b]] = [[a]]; + // CHECK-NOT: [[b]] = const let b = a; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.rs b/tests/mir-opt/dataflow-const-prop/repeat.rs index 5d1c1a3edb695..80eb14dedea3a 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.rs +++ b/tests/mir-opt/dataflow-const-prop/repeat.rs @@ -3,15 +3,19 @@ // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR repeat.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // CHECK: debug x => [[x:_.*]]; - // CHECK: {{_[0-9]+}} = const 8_usize; - // CHECK: {{_[0-9]+}} = const true; + // CHECK: [[array_lit:_.*]] = [const 42_u32; 8]; + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK: {{_.*}} = const 8_usize; + // CHECK: {{_.*}} = const true; // CHECK-LABEL: assert(const true - // CHECK: {{_[0-9]+}} = {{_[0-9]+}}[2 of 3]; - // CHECK: [[x]] = Add(move {{_[0-9]+}}, const 0_u32); + // CHECK-NOT: [[t:_.*]] = [[array_lit]][_ + // CHECK: [[t:_.*]] = [[array_lit]][2 of 3]; + // CHECK: [[x]] = Add(move [[t]], const 0_u32); let x: u32 = [42; 8][2] + 0; } diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.rs b/tests/mir-opt/dataflow-const-prop/repr_transparent.rs index d007301e568b1..39a2b357193ad 100644 --- a/tests/mir-opt/dataflow-const-prop/repr_transparent.rs +++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.rs @@ -7,7 +7,7 @@ struct I32(i32); // EMIT_MIR repr_transparent.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // CHECK: debug x => [[x:_.*]]; // CHECK: debug y => [[y:_.*]]; diff --git a/tests/mir-opt/dataflow-const-prop/self_assign.rs b/tests/mir-opt/dataflow-const-prop/self_assign.rs index 7d58b972d655b..a5b232131286f 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign.rs +++ b/tests/mir-opt/dataflow-const-prop/self_assign.rs @@ -2,25 +2,25 @@ // EMIT_MIR self_assign.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // CHECK: debug a => [[a:_.*]]; // CHECK: debug b => [[b:_.*]]; let mut a = 0; - // CHECK: [[a]] = Add(move {{_[0-9]+}}, const 1_i32); + // CHECK: [[a]] = Add(move {{_.*}}, const 1_i32); a = a + 1; - // CHECK: [[a]] = move {{_[0-9]+}}; + // CHECK: [[a]] = move {{_.*}}; a = a; // CHECK: [[b]] = &[[a]]; let mut b = &a; - // CHECK: [[b]] = move {{_[0-9]+}}; + // CHECK: [[b]] = move {{_.*}}; b = b; - // CHECK: [[a]] = move {{_[0-9]+}}; + // CHECK: [[a]] = move {{_.*}}; a = *b; } diff --git a/tests/mir-opt/dataflow-const-prop/self_assign_add.rs b/tests/mir-opt/dataflow-const-prop/self_assign_add.rs index 09be3865d60b3..7bfbda7a96c61 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign_add.rs +++ b/tests/mir-opt/dataflow-const-prop/self_assign_add.rs @@ -2,7 +2,7 @@ // EMIT_MIR self_assign_add.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // CHECK: debug a => [[a:_.*]]; let mut a = 0; diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs index 6e39e39839410..9c610aabe821a 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs @@ -10,9 +10,9 @@ // EMIT_MIR sibling_ptr.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { - // CHECK: debug x1 => [[x1:_[0-9]+]]; + // CHECK: debug x1 => [[x1:_.*]]; let mut x: (u8, u8) = (0, 0); unsafe { @@ -20,6 +20,6 @@ fn main() { *p.add(1) = 1; } - // CHECK: [[x1]] = ({{_[0-9]+}}.1: u8); + // CHECK: [[x1]] = ({{_.*}}.1: u8); let x1 = x.1; // should not be propagated } diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs index cd63980949638..65c87580330fc 100644 --- a/tests/mir-opt/dataflow-const-prop/slice_len.rs +++ b/tests/mir-opt/dataflow-const-prop/slice_len.rs @@ -5,19 +5,30 @@ // EMIT_MIR slice_len.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { - // CHECK: debug local => [[local:_[0-9]+]]; - // CHECK: debug constant => [[constant:_[0-9]+]]; + // CHECK: debug local => [[local:_.*]]; + // CHECK: debug constant => [[constant:_.*]]; - // CHECK: {{_[0-9]+}} = const 3_usize; - // CHECK: {{_[0-9]+}} = const true; + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK-NOT: assert(move _ + // CHECK: {{_.*}} = const 3_usize; + // CHECK: {{_.*}} = const true; + // CHECK: assert(const true, - // CHECK: [[local]] = (*{{_[0-9]+}})[1 of 2]; + // CHECK: [[local]] = (*{{_.*}})[1 of 2]; let local = (&[1u32, 2, 3] as &[u32])[1]; + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK-NOT: assert(move _ const SLICE: &[u32] = &[1, 2, 3]; + // CHECK: {{_.*}} = const 3_usize; + // CHECK: {{_.*}} = const true; + // CHECK: assert(const true, - // CHECK: [[constant]] = (*{{_[0-9]+}})[1 of 2]; + // CHECK-NOT: [[constant]] = (*{{_.*}})[_ + // CHECK: [[constant]] = (*{{_.*}})[1 of 2]; let constant = SLICE[1]; } diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index 4eec15a7f1630..a7e0f6a987d5a 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -12,25 +12,25 @@ struct BigStruct(f32, Option, &'static [f32]); // EMIT_MIR struct.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { - // CHECK: debug s => [[s:_[0-9]+]]; - // CHECK: debug a => [[a:_[0-9]+]]; - // CHECK: debug b => [[b:_[0-9]+]]; - // CHECK: debug a1 => [[a1:_[0-9]+]]; - // CHECK: debug b1 => [[b1:_[0-9]+]]; - // CHECK: debug c1 => [[c1:_[0-9]+]]; - // CHECK: debug a2 => [[a2:_[0-9]+]]; - // CHECK: debug b2 => [[b2:_[0-9]+]]; - // CHECK: debug c2 => [[c2:_[0-9]+]]; - // CHECK: debug ss => [[ss:_[0-9]+]]; - // CHECK: debug a3 => [[a3:_[0-9]+]]; - // CHECK: debug b3 => [[b3:_[0-9]+]]; - // CHECK: debug c3 => [[c3:_[0-9]+]]; - // CHECK: debug a4 => [[a4:_[0-9]+]]; - // CHECK: debug b4 => [[b4:_[0-9]+]]; - // CHECK: debug c4 => [[c4:_[0-9]+]]; - // CHECK: debug bs => [[bs:_[0-9]+]]; + // CHECK: debug s => [[s:_.*]]; + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug a1 => [[a1:_.*]]; + // CHECK: debug b1 => [[b1:_.*]]; + // CHECK: debug c1 => [[c1:_.*]]; + // CHECK: debug a2 => [[a2:_.*]]; + // CHECK: debug b2 => [[b2:_.*]]; + // CHECK: debug c2 => [[c2:_.*]]; + // CHECK: debug ss => [[ss:_.*]]; + // CHECK: debug a3 => [[a3:_.*]]; + // CHECK: debug b3 => [[b3:_.*]]; + // CHECK: debug c3 => [[c3:_.*]]; + // CHECK: debug a4 => [[a4:_.*]]; + // CHECK: debug b4 => [[b4:_.*]]; + // CHECK: debug c4 => [[c4:_.*]]; + // CHECK: debug bs => [[bs:_.*]]; // CHECK: [[s]] = const S(1_i32); let mut s = S(1); @@ -46,34 +46,34 @@ fn main() { // CHECK: [[a1]] = const 4f32; // CHECK: [[b1]] = const Option::::Some(S(1_i32)); - // CHECK: [[c1]] = ({{_[0-9]+}}.2: &[f32]); + // CHECK: [[c1]] = ({{_.*}}.2: &[f32]); let SmallStruct(a1, b1, c1) = SMALL_VAL; static SMALL_STAT: &SmallStruct = &SmallStruct(9., None, &[13.]); // CHECK: [[a2]] = const 9f32; - // CHECK: [[b2]] = ((*{{_[0-9]+}}).1: std::option::Option); - // CHECK: [[c2]] = ((*{{_[0-9]+}}).2: &[f32]); + // CHECK: [[b2]] = ((*{{_.*}}).1: std::option::Option); + // CHECK: [[c2]] = ((*{{_.*}}).2: &[f32]); let SmallStruct(a2, b2, c2) = *SMALL_STAT; - // CHECK: [[ss]] = SmallStruct(const 9f32, move {{_[0-9]+}}, move {{_[0-9]+}}); + // CHECK: [[ss]] = SmallStruct(const 9f32, move {{_.*}}, move {{_.*}}); let ss = SmallStruct(a2, b2, c2); const BIG_VAL: BigStruct = BigStruct(25., None, &[]); // CHECK: [[a3]] = const 25f32; - // CHECK: [[b3]] = ({{_[0-9]+}}.1: std::option::Option); - // CHECK: [[c3]] = ({{_[0-9]+}}.2: &[f32]); + // CHECK: [[b3]] = ({{_.*}}.1: std::option::Option); + // CHECK: [[c3]] = ({{_.*}}.2: &[f32]); let BigStruct(a3, b3, c3) = BIG_VAL; static BIG_STAT: &BigStruct = &BigStruct(82., Some(S(35)), &[45., 72.]); // CHECK: [[a4]] = const 82f32; // CHECK: [[b4]] = const Option::::Some(S(35_i32)); - // CHECK: [[c4]] = ((*{{_[0-9]+}}).2: &[f32]); + // CHECK: [[c4]] = ((*{{_.*}}).2: &[f32]); let BigStruct(a4, b4, c4) = *BIG_STAT; // We arbitrarily limit the size of synthetized values to 4 pointers. // `BigStruct` can be read, but we will keep a MIR aggregate for this. - // CHECK: [[bs]] = BigStruct(const 82f32, const Option::::Some(S(35_i32)), move {{_[0-9]+}}); + // CHECK: [[bs]] = BigStruct(const 82f32, const Option::::Some(S(35_i32)), move {{_.*}}); let bs = BigStruct(a4, b4, c4); } diff --git a/tests/mir-opt/dataflow-const-prop/terminator.rs b/tests/mir-opt/dataflow-const-prop/terminator.rs index 985eddad26440..37bf3b3347024 100644 --- a/tests/mir-opt/dataflow-const-prop/terminator.rs +++ b/tests/mir-opt/dataflow-const-prop/terminator.rs @@ -5,10 +5,10 @@ fn foo(n: i32) {} // EMIT_MIR terminator.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { let a = 1; // Checks that we propagate into terminators. - // CHECK: {{_[0-9]+}} = foo(const 2_i32) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: {{_.*}} = foo(const 2_i32) -> [return: {{bb.*}}, unwind continue]; foo(a + 1); } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.rs b/tests/mir-opt/dataflow-const-prop/tuple.rs index bd5adeda8b3dc..563558da04a5d 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.rs +++ b/tests/mir-opt/dataflow-const-prop/tuple.rs @@ -3,12 +3,12 @@ // EMIT_MIR tuple.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { - // CHECK: debug a => [[a:_[0-9]+]]; - // CHECK: debug b => [[b:_[0-9]+]]; - // CHECK: debug c => [[c:_[0-9]+]]; - // CHECK: debug d => [[d:_[0-9]+]]; + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: debug d => [[d:_.*]]; // CHECK: [[a]] = const (1_i32, 2_i32); let mut a = (1, 2); From 1c886d794c1772eb6a51e84939ef1093e9e10e17 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Thu, 11 Jan 2024 23:22:33 -0800 Subject: [PATCH 022/246] resolve code reviews --- tests/mir-opt/dataflow-const-prop/array_index.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs index 4b070e1d6d6f6..e21388ff5d211 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/array_index.rs @@ -9,8 +9,13 @@ fn main() { // CHECK: let mut [[array_lit:_.*]]: [u32; 4]; // CHECK: debug x => [[x:_.*]]; - let x: u32 = [0, 1, 2, 3][2]; // CHECK: [[array_lit]] = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; - // CHECK-LABEL: assert(const true, - // CHECK: [[x]] = [[array_lit]][2 of 3]; + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK-NOT: assert(move _ + // CHECK: {{_.*}} = const 4_usize; + // CHECK: {{_.*}} = const true; + // CHECK-LABEL: assert(const true + // CHECK: [[x]] = [[array_lit]][2 of 3]; + let x: u32 = [0, 1, 2, 3][2]; } From cd77d59f97cba2909b457b2ebb36f201b9dcb532 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Fri, 12 Jan 2024 20:50:28 -0800 Subject: [PATCH 023/246] update enum.rs for code review --- tests/mir-opt/dataflow-const-prop/enum.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index 26fdda2664a95..8a6fe3a3fdaa1 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -118,6 +118,7 @@ fn multiple(x: bool, i: u8) { // CHECK: debug x => [[x:_.*]]; // CHECK: debug e => [[e:_.*]]; // CHECK: debug x2 => [[x2:_.*]]; + // CHECK: debug y => [[y:_.*]]; let e = if x { // CHECK: [[e]] = Option::::Some(move {{_.*}}); Some(i) @@ -128,10 +129,18 @@ fn multiple(x: bool, i: u8) { // The dataflow state must have: // discriminant(e) => Top // (e as Some).0 => Top + // CHECK-NOT: [[x2]] = const 5 // CHECK: [[x2]] = const 0_u8; - // CHECK: [[x2]] = {{_.*}}; + // CHECK-NOT: [[x2]] = const 5 + // CHECK: [[some:_.*]] = (({{_.*}} as Some + // CHECK: [[x2]] = [[some]]; let x2 = match e { Some(i) => i, None => 0 }; + // Therefore, `x2` should be `Top` here, and no replacement shall happen. + + // CHECK-NOT: [[y]] = const + // CHECK: [[y]] = [[x2]]; + // CHECK-NOT: [[y]] = const let y = x2; } From f25126e9c9b25eb46462fd82f83028956e8d6ea0 Mon Sep 17 00:00:00 2001 From: usamoi Date: Wed, 3 Jan 2024 20:24:24 +0800 Subject: [PATCH 024/246] add avx512fp16 to x86 target features --- compiler/rustc_codegen_gcc/src/lib.rs | 2 +- compiler/rustc_target/src/target_features.rs | 1 + tests/ui/check-cfg/well-known-values.stderr | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 03f8f43ff1643..f8f054db65ede 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -408,7 +408,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &Locke .filter(|_feature| { target_info.cpu_supports(_feature) /* - adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512ifma, + 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 diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 5f5de57dd1d87..c350a37975d23 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -201,6 +201,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("avx512dq", Unstable(sym::avx512_target_feature)), ("avx512er", Unstable(sym::avx512_target_feature)), ("avx512f", Unstable(sym::avx512_target_feature)), + ("avx512fp16", Unstable(sym::avx512_target_feature)), ("avx512ifma", Unstable(sym::avx512_target_feature)), ("avx512pf", Unstable(sym::avx512_target_feature)), ("avx512vbmi", Unstable(sym::avx512_target_feature)), diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 9d134dcfcfd88..0ce0827c15a89 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -143,7 +143,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From 5747eceef859c6e1ac74c04723ac9e2b5e039e1f Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sun, 14 Jan 2024 22:35:00 -0800 Subject: [PATCH 025/246] add FIXME for default_boxed_slice.rs --- tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs index b15809f2510ff..bfa52b694d0ec 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -4,6 +4,8 @@ // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// This test is to check ICE in issue [#115789](https://github.com/rust-lang/rust/issues/115789). + struct A { foo: Box<[bool]>, } @@ -14,13 +16,14 @@ struct A { // CHECK-LABEL: fn main( fn main() { // ConstProp will create a constant of type `Box<[bool]>`. + // FIXME: it is not yet a constant. + // Verify that `DataflowConstProp` does not ICE trying to dereference it directly. // CHECK: debug a => [[a:_.*]]; // We may check other inlined functions as well... - // CHECK: [[box_obj:_.*]] = Box::<[bool]>(_3, const std::alloc::Global); - // CHECK: [[a]] = A { foo: move [[box_obj]] }; - // FIXME: we do not have `const Box::<[bool]>` after constprop right now. + // CHECK-LABEL: _.* = Box::<[bool]>( + // FIXME: should be `_.* = const Box::<[bool]>` let a: A = A { foo: Box::default() }; } From 6231ca5f5eddc7691a79373804e9530e19df9a5d Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 18 Jan 2024 06:50:06 +0000 Subject: [PATCH 026/246] fix(rust-analyzer): use new pkgid spec to compare Starting from cargo#13311, Cargo's compiler artifact message uses Package ID specification as package's identifier format. --- crates/proc-macro-srv/proc-macro-test/build.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/proc-macro-srv/proc-macro-test/build.rs b/crates/proc-macro-srv/proc-macro-test/build.rs index 6cf2b5643e579..e6903fb8d4aed 100644 --- a/crates/proc-macro-srv/proc-macro-test/build.rs +++ b/crates/proc-macro-srv/proc-macro-test/build.rs @@ -92,12 +92,24 @@ fn main() { panic!("proc-macro-test-impl failed to build"); } + // Old Package ID Spec + let repr = format!("{name} {version}"); + // New Package Id Spec since rust-lang/cargo#13311 + let pkgid = String::from_utf8( + Command::new(toolchain::cargo()) + .current_dir(&staging_dir) + .args(["pkgid", name]) + .output() + .unwrap().stdout, + ) + .unwrap(); + let pkgid = pkgid.trim(); + 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()) { - let repr = format!("{name} {version}"); - if artifact.package_id.repr.starts_with(&repr) { + if artifact.package_id.repr.starts_with(&repr) || artifact.package_id.repr == pkgid { artifact_path = Some(PathBuf::from(&artifact.filenames[0])); } } From 60a08196b6f473da17fc280a8545f1b62097b4fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Thu, 30 Nov 2023 18:11:02 -0300 Subject: [PATCH 027/246] feat: add LocalWaker type, ContextBuilder type, and LocalWake trait. --- library/alloc/src/lib.rs | 1 + library/alloc/src/task.rs | 165 +++++++++++++++- library/core/src/task/mod.rs | 2 +- library/core/src/task/wake.rs | 361 +++++++++++++++++++++++++++++++--- 4 files changed, 504 insertions(+), 25 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 78629b39d34b1..c8b4cebdf8987 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -135,6 +135,7 @@ #![feature(iter_next_chunk)] #![feature(iter_repeat_n)] #![feature(layout_for_ptr)] +#![feature(local_waker)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_uninit_array_transpose)] diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 5d9772b878b03..16ae5241da8a3 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -7,8 +7,9 @@ //! `#[cfg(target_has_atomic = "ptr")]`. use core::mem::ManuallyDrop; -use core::task::{RawWaker, RawWakerVTable, Waker}; +use core::task::{LocalWaker, RawWaker, RawWakerVTable, Waker}; +use crate::rc::Rc; use crate::sync::Arc; /// The implementation of waking a task on an executor. @@ -152,3 +153,165 @@ fn raw_waker(waker: Arc) -> RawWaker { &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), ) } + +/// An analogous trait to `Wake` but used to construct a `LocalWaker`. This API +/// works in exactly the same way as `Wake`, except that it uses an `Rc` instead +/// of an `Arc`, and the result is a `LocalWaker` instead of a `Waker`. +/// +/// The benefits of using `LocalWaker` over `Waker` are that it allows the local waker +/// to hold data that does not implement `Send` and `Sync`. Additionally, it saves calls +/// to `Arc::clone`, which requires atomic synchronization. +/// + +/// # Examples +/// +/// A +/// +/// This is a simplified example of a `spawn` and a `block_on` function. The `spawn` function +/// is used to push new tasks onto the run queue, while the block on function will remove them +/// and poll them. When a task is woken, it will put itself back on the run queue to be polled by the executor. +/// +/// **Note:** A real world example would interlieve poll calls with calls to an io reactor to wait for events instead +/// of spinning on a loop. +/// +/// ```rust +/// use std::task::{LocalWake, ContextBuilder, LocalWaker}; +/// use std::future::Future; +/// use std::pin::Pin; +/// use std::rc::Rc; +/// use std::cell::RefCell; +/// use std::collections::VecDeque; +/// +/// +/// thread_local! { +/// // A queue containing all tasks ready to do progress +/// static RUN_QUEUE: RefCell>> = RefCell::default(); +/// } +/// +/// type BoxedFuture = Pin>>; +/// +/// struct Task(RefCell); +/// +/// impl LocalWake for Task { +/// fn wake(self: Rc) { +/// RUN_QUEUE.with_borrow_mut(|queue| { +/// queue.push_back(self) +/// }) +/// } +/// } +/// +/// fn spawn(future: F) +/// where +/// F: Future + 'static + Send + Sync +/// { +/// let task = Rc::new(Box::pin(future)); +/// RUN_QUEUE.with_borrow_mut(|queue| { +/// queue.push_back(task) +/// }); +/// } +/// +/// fn block_on(future: F) +/// where +/// F: Future + 'static + Sync + Send +/// { +/// spawn(future); +/// loop { +/// let Some(task) = RUN_QUEUE.with_borrow_mut(|queue|queue.pop_front()) else { +/// // we exit, since there are no more tasks remaining on the queue +/// return; +/// }; +/// // cast the Rc into a `LocalWaker` +/// let waker: LocalWaker = task.into(); +/// // Build the context using `ContextBuilder` +/// let mut cx = ContextBuilder::new() +/// .local_waker(&waker) +/// .build(); +/// +/// // Poll the task +/// task.0 +/// .borrow_mut() +/// .as_mut() +/// .poll(&mut cx); +/// } +/// } +/// ``` +/// +#[unstable(feature = "local_waker", issue = "none")] +pub trait LocalWake { + /// Wake this task. + #[unstable(feature = "local_waker", issue = "none")] + fn wake(self: Rc); + + /// Wake this task without consuming the local waker. + /// + /// If an executor supports a cheaper way to wake without consuming the + /// waker, it should override this method. By default, it clones the + /// [`Rc`] and calls [`wake`] on the clone. + /// + /// [`wake`]: Rc::wake + #[unstable(feature = "local_waker", issue = "none")] + fn wake_by_ref(self: &Rc) { + self.clone().wake(); + } +} + +#[unstable(feature = "local_waker", issue = "none")] +impl From> for LocalWaker { + /// Use a `Wake`-able type as a `LocalWaker`. + /// + /// No heap allocations or atomic operations are used for this conversion. + fn from(waker: Rc) -> LocalWaker { + // SAFETY: This is safe because raw_waker safely constructs + // a RawWaker from Rc. + unsafe { LocalWaker::from_raw(local_raw_waker(waker)) } + } +} +#[allow(ineffective_unstable_trait_impl)] +#[unstable(feature = "local_waker", issue = "none")] +impl From> for RawWaker { + /// Use a `Wake`-able type as a `RawWaker`. + /// + /// No heap allocations or atomic operations are used for this conversion. + fn from(waker: Rc) -> RawWaker { + local_raw_waker(waker) + } +} + +// NB: This private function for constructing a RawWaker is used, rather than +// inlining this into the `From> for RawWaker` impl, to ensure that +// the safety of `From> for Waker` does not depend on the correct +// trait dispatch - instead both impls call this function directly and +// explicitly. +#[inline(always)] +fn local_raw_waker(waker: Rc) -> RawWaker { + // Increment the reference count of the Rc to clone it. + unsafe fn clone_waker(waker: *const ()) -> RawWaker { + unsafe { Rc::increment_strong_count(waker as *const W) }; + RawWaker::new( + waker as *const (), + &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), + ) + } + + // Wake by value, moving the Rc into the LocalWake::wake function + unsafe fn wake(waker: *const ()) { + let waker = unsafe { Rc::from_raw(waker as *const W) }; + ::wake(waker); + } + + // Wake by reference, wrap the waker in ManuallyDrop to avoid dropping it + unsafe fn wake_by_ref(waker: *const ()) { + let waker = unsafe { ManuallyDrop::new(Rc::from_raw(waker as *const W)) }; + ::wake_by_ref(&waker); + } + + // Decrement the reference count of the Rc on drop + unsafe fn drop_waker(waker: *const ()) { + unsafe { Rc::decrement_strong_count(waker as *const W) }; + } + + RawWaker::new( + Rc::into_raw(waker) as *const (), + &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), + ) +} diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs index 3f0080e3832e1..f1a789e32a7a7 100644 --- a/library/core/src/task/mod.rs +++ b/library/core/src/task/mod.rs @@ -8,7 +8,7 @@ pub use self::poll::Poll; mod wake; #[stable(feature = "futures_api", since = "1.36.0")] -pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker}; +pub use self::wake::{Context, ContextBuilder, LocalWaker, RawWaker, RawWakerVTable, Waker}; mod ready; #[stable(feature = "ready_macro", since = "1.64.0")] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 077852b0120c4..4dedcbe47a02f 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -1,5 +1,7 @@ #![stable(feature = "futures_api", since = "1.36.0")] +use crate::mem::transmute; + use crate::fmt; use crate::marker::PhantomData; use crate::ptr; @@ -60,6 +62,21 @@ impl RawWaker { pub fn vtable(&self) -> &'static RawWakerVTable { self.vtable } + + #[unstable(feature = "noop_waker", issue = "98286")] + const NOOP: RawWaker = { + const VTABLE: RawWakerVTable = RawWakerVTable::new( + // Cloning just returns a new no-op raw waker + |_| RawWaker::NOOP, + // `wake` does nothing + |_| {}, + // `wake_by_ref` does nothing + |_| {}, + // Dropping does nothing as we don't allocate anything + |_| {}, + ); + RawWaker::new(ptr::null(), &VTABLE) + }; } /// A virtual function pointer table (vtable) that specifies the behavior @@ -177,7 +194,8 @@ impl RawWakerVTable { #[stable(feature = "futures_api", since = "1.36.0")] #[lang = "Context"] pub struct Context<'a> { - waker: &'a Waker, + waker: Option<&'a Waker>, + local_waker: Option<&'a LocalWaker>, // Ensure we future-proof against variance changes by forcing // the lifetime to be invariant (argument-position lifetimes // are contravariant while return-position lifetimes are @@ -195,16 +213,36 @@ impl<'a> Context<'a> { #[must_use] #[inline] pub const fn from_waker(waker: &'a Waker) -> Self { - Context { waker, _marker: PhantomData, _marker2: PhantomData } + ContextBuilder::new().waker(waker).build() } /// Returns a reference to the [`Waker`] for the current task. + /// + /// Note that if the waker does not need to be sent across threads, it + /// is preferable to call `local_waker`, which is more portable and + /// potentially more efficient. + /// + /// # Panics + /// This function will panic if no `Waker` was set on the context. This happens if + /// the executor does not support working with thread safe wakers. An alternative + /// may be to call [`.local_waker()`](Context::local_waker) instead. #[stable(feature = "futures_api", since = "1.36.0")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] #[must_use] #[inline] pub const fn waker(&self) -> &'a Waker { - &self.waker + &self + .waker + .expect("no waker was set on this context, consider calling `local_waker` instead.") + } + /// Returns a reference to the [`LocalWaker`] for the current task. + #[unstable(feature = "local_waker", issue = "none")] + pub fn local_waker(&self) -> &'a LocalWaker { + // Safety: + // It is safe to transmute a `&Waker` into a `&LocalWaker` since both are a transparent + // wrapper around a local waker. Also, the Option<&Waker> here cannot be None since it is + // impossible to construct a Context without any waker set. + self.local_waker.unwrap_or_else(|| unsafe { transmute(self.waker) }) } } @@ -215,6 +253,94 @@ impl fmt::Debug for Context<'_> { } } +/// A Builder used to construct a `Context` instance +/// with support for `LocalWaker`. +/// +/// # Examples +/// ``` +/// #![feature(local_waker)] +/// #![feature(noop_waker)] +/// use std::task::{ContextBuilder, LocalWaker, Waker}; +/// +/// let local_waker = LocalWaker::noop(); +/// let waker = Waker::noop(); +/// +/// let context = ContextBuilder::default() +/// .local_waker(&local_waker) +/// .waker(&waker) +/// .build(); +/// ``` +#[unstable(feature = "local_waker", issue = "none")] +#[derive(Default, Debug)] +pub struct ContextBuilder<'a> { + waker: Option<&'a Waker>, + local_waker: Option<&'a LocalWaker>, +} + +impl<'a> ContextBuilder<'a> { + /// Creates a new empty `ContextBuilder`. + #[inline] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + #[unstable(feature = "local_waker", issue = "none")] + pub const fn new() -> Self { + ContextBuilder { waker: None, local_waker: None } + } + + /// This field is used to set the value of the waker on `Context`. + #[inline] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + #[unstable(feature = "local_waker", issue = "none")] + pub const fn waker(self, waker: &'a Waker) -> Self { + Self { waker: Some(waker), ..self } + } + + /// This method is used to set the value for the local waker on `Context`. + /// + /// # Examples + /// ``` + /// #![feature(local_waker)] + /// #![feature(noop_waker)] + /// + /// use std::task; + /// use std::pin; + /// use std::future::Future; + /// + /// let local_waker = task::LocalWaker::noop(); + /// + /// let mut context = task::ContextBuilder::new() + /// .local_waker(&local_waker) + /// .build(); + /// + /// let future = pin::pin!(async { 20 }); + /// + /// let poll = future.poll(&mut context); + /// + /// assert_eq!(poll, task::Poll::Ready(20)); + /// ``` + #[inline] + #[unstable(feature = "local_waker", issue = "none")] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + pub const fn local_waker(self, local_waker: &'a LocalWaker) -> Self { + Self { local_waker: Some(local_waker), ..self } + } + + /// Builds the `Context`. + /// + /// # Panics + /// Panics if no `Waker` or `LocalWaker` is set. + #[inline] + #[unstable(feature = "local_waker", issue = "none")] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + pub const fn build(self) -> Context<'a> { + let ContextBuilder { waker, local_waker } = self; + assert!( + waker.is_some() || local_waker.is_some(), + "at least one waker must be set with either the `local_waker` or `waker` methods on `ContextBuilder`." + ); + Context { waker, local_waker, _marker: PhantomData, _marker2: PhantomData } + } +} + /// A `Waker` is a handle for waking up a task by notifying its executor that it /// is ready to be run. /// @@ -229,7 +355,8 @@ impl fmt::Debug for Context<'_> { /// Implements [`Clone`], [`Send`], and [`Sync`]; therefore, a waker may be invoked /// from any thread, including ones not in any way managed by the executor. For example, /// this might be done to wake a future when a blocking function call completes on another -/// thread. +/// thread. If the waker does not need to be moved across threads, it is better to use +/// [`LocalWaker`], which the executor may use to skip unnecessary memory synchronization. /// /// Note that it is preferable to use `waker.clone_from(&new_waker)` instead /// of `*waker = new_waker.clone()`, as the former will avoid cloning the waker @@ -354,25 +481,8 @@ impl Waker { #[must_use] #[unstable(feature = "noop_waker", issue = "98286")] pub const fn noop() -> &'static Waker { - // Ideally all this data would be explicitly `static` because it is used by reference and - // only ever needs one copy. But `const fn`s (and `const` items) cannot refer to statics, - // even though their values can be promoted to static. (That might change; see #119618.) - // An alternative would be a `pub static NOOP: &Waker`, but associated static items are not - // currently allowed either, and making it non-associated would be unergonomic. - const VTABLE: RawWakerVTable = RawWakerVTable::new( - // Cloning just returns a new no-op raw waker - |_| RAW, - // `wake` does nothing - |_| {}, - // `wake_by_ref` does nothing - |_| {}, - // Dropping does nothing as we don't allocate anything - |_| {}, - ); - const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE); - const WAKER_REF: &Waker = &Waker { waker: RAW }; - - WAKER_REF + const WAKER: &Waker = &Waker { waker: RawWaker::NOOP }; + WAKER } /// Get a reference to the underlying [`RawWaker`]. @@ -425,3 +535,208 @@ impl fmt::Debug for Waker { .finish() } } + +/// A `LocalWaker` is analogous to a [`Waker`], but it does not implement [`Send`] or [`Sync`]. +/// This handle encapsulates a [`RawWaker`] instance, which defines the +/// executor-specific wakeup behavior. +/// +/// Local wakers can be requested from a `Context` with the [`local_waker`] method. +/// +/// The typical life of a `LocalWaker` is that it is constructed by an executor, wrapped in a +/// [`Context`], then passed to [`Future::poll()`]. Then, if the future chooses to return +/// [`Poll::Pending`], it must also store the waker somehow and call [`Waker::wake()`] when +/// the future should be polled again. +/// +/// Implements [`Clone`], but neither [`Send`] nor [`Sync`]; therefore, a local waker may +/// not be moved to other threads. In general, when deciding to use wakers or local wakers, +/// local wakers are preferable unless the waker needs to be sent across threads. This is because +/// wakers can incur in additional cost related to memory synchronization, and not all executors +/// may support wakers. +/// +/// Note that it is preferable to use `local_waker.clone_from(&new_waker)` instead +/// of `*local_waker = new_waker.clone()`, as the former will avoid cloning the waker +/// unnecessarily if the two wakers [wake the same task](Self::will_wake). +/// +/// # Examples +/// +/// ``` +/// #![feature(local_waker)] +/// use std::future::{Future, poll_fn}; +/// use std::task::Poll; +/// +/// // a future that returns pending once. +/// fn yield_now() -> impl Future + Unpin { +/// let mut yielded = false; +/// poll_fn(move |cx| { +/// if !yielded { +/// yielded = true; +/// cx.local_waker().wake_by_ref(); +/// return Poll::Pending; +/// } +/// return Poll::Ready(()) +/// }) +/// } +/// # async { +/// yield_now().await; +/// # }; +/// ``` +/// +/// [`Future::poll()`]: core::future::Future::poll +/// [`Poll::Pending`]: core::task::Poll::Pending +/// [`local_waker`]: core::task::Context::local_waker +#[unstable(feature = "local_waker", issue = "none")] +#[repr(transparent)] +pub struct LocalWaker { + waker: RawWaker, +} + +#[unstable(feature = "local_waker", issue = "none")] +impl Unpin for LocalWaker {} + +impl LocalWaker { + /// Creates a new `LocalWaker` from [`RawWaker`]. + /// + /// The behavior of the returned `Waker` is undefined if the contract defined + /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. + /// Therefore this method is unsafe. + #[inline] + #[must_use] + #[stable(feature = "futures_api", since = "1.36.0")] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker { + Self { waker } + } + + /// Wake up the task associated with this `LocalWaker`. + /// + /// As long as the executor keeps running and the task is not finished, it is + /// guaranteed that each invocation of [`wake()`](Self::wake) (or + /// [`wake_by_ref()`](Self::wake_by_ref)) will be followed by at least one + /// [`poll()`] of the task to which this `Waker` belongs. This makes + /// it possible to temporarily yield to other tasks while running potentially + /// unbounded processing loops. + /// + /// Note that the above implies that multiple wake-ups may be coalesced into a + /// single [`poll()`] invocation by the runtime. + /// + /// Also note that yielding to competing tasks is not guaranteed: it is the + /// executor’s choice which task to run and the executor may choose to run the + /// current task again. + /// + /// [`poll()`]: crate::future::Future::poll + #[inline] + #[stable(feature = "futures_api", since = "1.36.0")] + pub fn wake(self) { + // The actual wakeup call is delegated through a virtual function call + // to the implementation which is defined by the executor. + let wake = self.waker.vtable.wake; + let data = self.waker.data; + + // Don't call `drop` -- the waker will be consumed by `wake`. + crate::mem::forget(self); + + // SAFETY: This is safe because `Waker::from_raw` is the only way + // to initialize `wake` and `data` requiring the user to acknowledge + // that the contract of `RawWaker` is upheld. + unsafe { (wake)(data) }; + } + + /// Creates a new `LocalWaker` that does nothing when `wake` is called. + /// + /// This is mostly useful for writing tests that need a [`Context`] to poll + /// some futures, but are not expecting those futures to wake the waker or + /// do not need to do anything specific if it happens. + /// + /// # Examples + /// + /// ``` + /// #![feature(local_waker)] + /// #![feature(noop_waker)] + /// + /// use std::future::Future; + /// use std::task::{ContextBuilder, LocalWaker}; + /// + /// let mut cx = task::ContextBuilder::new() + /// .local_waker(LocalWaker::noop()) + /// .build(); + /// + /// let mut future = Box::pin(async { 10 }); + /// assert_eq!(future.as_mut().poll(&mut cx), task::Poll::Ready(10)); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "noop_waker", issue = "98286")] + pub const fn noop() -> &'static LocalWaker { + const WAKER: &LocalWaker = &LocalWaker { waker: RawWaker::NOOP }; + WAKER + } + + /// Get a reference to the underlying [`RawWaker`]. + #[inline] + #[must_use] + #[unstable(feature = "waker_getters", issue = "87021")] + pub fn as_raw(&self) -> &RawWaker { + &self.waker + } + + /// Returns `true` if this `LocalWaker` and another `LocalWaker` would awake the same task. + /// + /// This function works on a best-effort basis, and may return false even + /// when the `Waker`s would awaken the same task. However, if this function + /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task. + /// + /// This function is primarily used for optimization purposes — for example, + /// this type's [`clone_from`](Self::clone_from) implementation uses it to + /// avoid cloning the waker when they would wake the same task anyway. + #[inline] + #[must_use] + #[stable(feature = "futures_api", since = "1.36.0")] + pub fn will_wake(&self, other: &LocalWaker) -> bool { + self.waker == other.waker + } + + /// Wake up the task associated with this `LocalWaker` without consuming the `LocalWaker`. + /// + /// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in + /// the case where an owned `Waker` is available. This method should be preferred to + /// calling `waker.clone().wake()`. + #[inline] + #[stable(feature = "futures_api", since = "1.36.0")] + pub fn wake_by_ref(&self) { + // The actual wakeup call is delegated through a virtual function call + // to the implementation which is defined by the executor. + + // SAFETY: see `wake` + unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) } + } +} +#[unstable(feature = "local_waker", issue = "none")] +impl Clone for LocalWaker { + #[inline] + fn clone(&self) -> Self { + LocalWaker { + // SAFETY: This is safe because `Waker::from_raw` is the only way + // to initialize `clone` and `data` requiring the user to acknowledge + // that the contract of [`RawWaker`] is upheld. + waker: unsafe { (self.waker.vtable.clone)(self.waker.data) }, + } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + if !self.will_wake(source) { + *self = source.clone(); + } + } +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl fmt::Debug for LocalWaker { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let vtable_ptr = self.waker.vtable as *const RawWakerVTable; + f.debug_struct("LocalWaker") + .field("data", &self.waker.data) + .field("vtable", &vtable_ptr) + .finish() + } +} From 0cb5e2fe5f080f40059e673cec6f0bf27f4c7596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Thu, 30 Nov 2023 19:05:12 -0300 Subject: [PATCH 028/246] perf: move null check from local_wake() to build() --- library/core/src/task/wake.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 4dedcbe47a02f..fa2b730b31c44 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -195,7 +195,7 @@ impl RawWakerVTable { #[lang = "Context"] pub struct Context<'a> { waker: Option<&'a Waker>, - local_waker: Option<&'a LocalWaker>, + local_waker: &'a LocalWaker, // Ensure we future-proof against variance changes by forcing // the lifetime to be invariant (argument-position lifetimes // are contravariant while return-position lifetimes are @@ -238,11 +238,7 @@ impl<'a> Context<'a> { /// Returns a reference to the [`LocalWaker`] for the current task. #[unstable(feature = "local_waker", issue = "none")] pub fn local_waker(&self) -> &'a LocalWaker { - // Safety: - // It is safe to transmute a `&Waker` into a `&LocalWaker` since both are a transparent - // wrapper around a local waker. Also, the Option<&Waker> here cannot be None since it is - // impossible to construct a Context without any waker set. - self.local_waker.unwrap_or_else(|| unsafe { transmute(self.waker) }) + &self.local_waker } } @@ -325,7 +321,7 @@ impl<'a> ContextBuilder<'a> { } /// Builds the `Context`. - /// + /// /// # Panics /// Panics if no `Waker` or `LocalWaker` is set. #[inline] @@ -337,6 +333,16 @@ impl<'a> ContextBuilder<'a> { waker.is_some() || local_waker.is_some(), "at least one waker must be set with either the `local_waker` or `waker` methods on `ContextBuilder`." ); + let local_waker = match local_waker { + Some(local_waker) => local_waker, + None => { + // SAFETY: + // It is safe to transmute a `&Waker` into a `&LocalWaker` since both are a transparent + // wrapper around a local waker. Also, the Option<&Waker> here cannot be None because + // of the previous assert. + unsafe { transmute(self.waker) } + } + }; Context { waker, local_waker, _marker: PhantomData, _marker2: PhantomData } } } @@ -576,9 +582,10 @@ impl fmt::Debug for Waker { /// return Poll::Ready(()) /// }) /// } -/// # async { +/// # #[allow(unused_must_use)] +/// # async fn __() { /// yield_now().await; -/// # }; +/// # } /// ``` /// /// [`Future::poll()`]: core::future::Future::poll From 232cc2b4e4ba0a3c0e5e45fed64f0783201805f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Wed, 6 Dec 2023 12:11:28 -0300 Subject: [PATCH 029/246] refactor: remove in favor of and to make the API infallible. --- library/core/src/task/wake.rs | 81 +++++++++++++---------------------- 1 file changed, 29 insertions(+), 52 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index fa2b730b31c44..da36194d462d3 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -213,7 +213,7 @@ impl<'a> Context<'a> { #[must_use] #[inline] pub const fn from_waker(waker: &'a Waker) -> Self { - ContextBuilder::new().waker(waker).build() + ContextBuilder::from_waker(waker).build() } /// Returns a reference to the [`Waker`] for the current task. @@ -261,28 +261,43 @@ impl fmt::Debug for Context<'_> { /// let local_waker = LocalWaker::noop(); /// let waker = Waker::noop(); /// -/// let context = ContextBuilder::default() -/// .local_waker(&local_waker) +/// let context = ContextBuilder::from_local_waker(&local_waker) /// .waker(&waker) /// .build(); +/// +/// let future = pin::pin!(async { 20 }); +/// let poll = future.poll(&mut context); +/// assert_eq!(poll, task::Poll::Ready(20)); +/// /// ``` #[unstable(feature = "local_waker", issue = "none")] -#[derive(Default, Debug)] +#[derive(Debug)] pub struct ContextBuilder<'a> { waker: Option<&'a Waker>, - local_waker: Option<&'a LocalWaker>, + local_waker: &'a LocalWaker, } impl<'a> ContextBuilder<'a> { - /// Creates a new empty `ContextBuilder`. + /// Create a ContextBuilder from a Waker. + #[inline] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + #[unstable(feature = "local_waker", issue = "none")] + pub const fn from_waker(waker: &'a Waker) -> Self { + // SAFETY: LocalWaker is just Waker without thread safety + let local_waker = unsafe { transmute(waker) }; + Self { waker: Some(waker), local_waker } + } + + /// Create a ContextBuilder from a LocalWaker. #[inline] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] #[unstable(feature = "local_waker", issue = "none")] - pub const fn new() -> Self { - ContextBuilder { waker: None, local_waker: None } + pub const fn from_local_waker(local_waker: &'a LocalWaker) -> Self { + Self { local_waker, waker: None } } /// This field is used to set the value of the waker on `Context`. + #[inline] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] #[unstable(feature = "local_waker", issue = "none")] @@ -291,58 +306,19 @@ impl<'a> ContextBuilder<'a> { } /// This method is used to set the value for the local waker on `Context`. - /// - /// # Examples - /// ``` - /// #![feature(local_waker)] - /// #![feature(noop_waker)] - /// - /// use std::task; - /// use std::pin; - /// use std::future::Future; - /// - /// let local_waker = task::LocalWaker::noop(); - /// - /// let mut context = task::ContextBuilder::new() - /// .local_waker(&local_waker) - /// .build(); - /// - /// let future = pin::pin!(async { 20 }); - /// - /// let poll = future.poll(&mut context); - /// - /// assert_eq!(poll, task::Poll::Ready(20)); - /// ``` #[inline] #[unstable(feature = "local_waker", issue = "none")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] pub const fn local_waker(self, local_waker: &'a LocalWaker) -> Self { - Self { local_waker: Some(local_waker), ..self } + Self { local_waker, ..self } } /// Builds the `Context`. - /// - /// # Panics - /// Panics if no `Waker` or `LocalWaker` is set. #[inline] #[unstable(feature = "local_waker", issue = "none")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] pub const fn build(self) -> Context<'a> { let ContextBuilder { waker, local_waker } = self; - assert!( - waker.is_some() || local_waker.is_some(), - "at least one waker must be set with either the `local_waker` or `waker` methods on `ContextBuilder`." - ); - let local_waker = match local_waker { - Some(local_waker) => local_waker, - None => { - // SAFETY: - // It is safe to transmute a `&Waker` into a `&LocalWaker` since both are a transparent - // wrapper around a local waker. Also, the Option<&Waker> here cannot be None because - // of the previous assert. - unsafe { transmute(self.waker) } - } - }; Context { waker, local_waker, _marker: PhantomData, _marker2: PhantomData } } } @@ -549,8 +525,8 @@ impl fmt::Debug for Waker { /// Local wakers can be requested from a `Context` with the [`local_waker`] method. /// /// The typical life of a `LocalWaker` is that it is constructed by an executor, wrapped in a -/// [`Context`], then passed to [`Future::poll()`]. Then, if the future chooses to return -/// [`Poll::Pending`], it must also store the waker somehow and call [`Waker::wake()`] when +/// [`Context`] using [`ContextBuilder`], then passed to [`Future::poll()`]. Then, if the future chooses to return +/// [`Poll::Pending`], it must also store the waker somehow and call [`LocalWaker::wake()`] when /// the future should be polled again. /// /// Implements [`Clone`], but neither [`Send`] nor [`Sync`]; therefore, a local waker may @@ -564,7 +540,7 @@ impl fmt::Debug for Waker { /// unnecessarily if the two wakers [wake the same task](Self::will_wake). /// /// # Examples -/// +/// Usage of a local waker to implement a future /// ``` /// #![feature(local_waker)] /// use std::future::{Future, poll_fn}; @@ -582,12 +558,13 @@ impl fmt::Debug for Waker { /// return Poll::Ready(()) /// }) /// } +/// /// # #[allow(unused_must_use)] /// # async fn __() { /// yield_now().await; /// # } /// ``` -/// +/// /// [`Future::poll()`]: core::future::Future::poll /// [`Poll::Pending`]: core::task::Poll::Pending /// [`local_waker`]: core::task::Context::local_waker From 403718b19de6ad0979833fd2cf6074f2a1b50c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Wed, 6 Dec 2023 14:09:16 -0300 Subject: [PATCH 030/246] feat: add try_waker and From<&mut Context> for ContextBuilder to allow the extention of contexts by futures --- library/alloc/src/task.rs | 20 +++++---- library/core/src/task/wake.rs | 79 +++++++++++++++++++++++++++++------ 2 files changed, 78 insertions(+), 21 deletions(-) diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 16ae5241da8a3..736a55700f63e 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -165,16 +165,15 @@ fn raw_waker(waker: Arc) -> RawWaker { /// # Examples /// -/// A -/// /// This is a simplified example of a `spawn` and a `block_on` function. The `spawn` function /// is used to push new tasks onto the run queue, while the block on function will remove them /// and poll them. When a task is woken, it will put itself back on the run queue to be polled by the executor. /// /// **Note:** A real world example would interlieve poll calls with calls to an io reactor to wait for events instead -/// of spinning on a loop. +/// of spinning on a loop. /// /// ```rust +/// #![feature(local_waker)] /// use std::task::{LocalWake, ContextBuilder, LocalWaker}; /// use std::future::Future; /// use std::pin::Pin; @@ -204,9 +203,9 @@ fn raw_waker(waker: Arc) -> RawWaker { /// where /// F: Future + 'static + Send + Sync /// { -/// let task = Rc::new(Box::pin(future)); +/// let task = RefCell::new(Box::pin(future)); /// RUN_QUEUE.with_borrow_mut(|queue| { -/// queue.push_back(task) +/// queue.push_back(Rc::new(Task(task))); /// }); /// } /// @@ -221,19 +220,22 @@ fn raw_waker(waker: Arc) -> RawWaker { /// return; /// }; /// // cast the Rc into a `LocalWaker` -/// let waker: LocalWaker = task.into(); +/// let waker: LocalWaker = task.clone().into(); /// // Build the context using `ContextBuilder` -/// let mut cx = ContextBuilder::new() -/// .local_waker(&waker) +/// let mut cx = ContextBuilder::from_local_waker(&waker) /// .build(); /// /// // Poll the task -/// task.0 +/// let _ = task.0 /// .borrow_mut() /// .as_mut() /// .poll(&mut cx); /// } /// } +/// +/// block_on(async { +/// println!("hello world"); +/// }); /// ``` /// #[unstable(feature = "local_waker", issue = "none")] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index da36194d462d3..fa4590f18ec98 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -225,21 +225,32 @@ impl<'a> Context<'a> { /// # Panics /// This function will panic if no `Waker` was set on the context. This happens if /// the executor does not support working with thread safe wakers. An alternative - /// may be to call [`.local_waker()`](Context::local_waker) instead. + /// may be to call [`.local_waker()`](Context::local_waker) instead. For a fallible + /// version of this function see [`.try_waker()`](Context::try_waker). + #[inline] + #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] - #[must_use] - #[inline] pub const fn waker(&self) -> &'a Waker { &self .waker .expect("no waker was set on this context, consider calling `local_waker` instead.") } /// Returns a reference to the [`LocalWaker`] for the current task. + #[inline] #[unstable(feature = "local_waker", issue = "none")] - pub fn local_waker(&self) -> &'a LocalWaker { + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + pub const fn local_waker(&self) -> &'a LocalWaker { &self.local_waker } + /// Returns a `Some(&Waker)` if a waker was defined on the `Context`, + /// otherwise it returns `None`. + #[inline] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + #[unstable(feature = "local_waker", issue = "none")] + pub const fn try_waker(&self) -> Option<&'a Waker> { + self.waker + } } #[stable(feature = "futures_api", since = "1.36.0")] @@ -256,18 +267,19 @@ impl fmt::Debug for Context<'_> { /// ``` /// #![feature(local_waker)] /// #![feature(noop_waker)] -/// use std::task::{ContextBuilder, LocalWaker, Waker}; -/// +/// use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; +/// use std::future::Future; +/// /// let local_waker = LocalWaker::noop(); /// let waker = Waker::noop(); /// -/// let context = ContextBuilder::from_local_waker(&local_waker) +/// let mut cx = ContextBuilder::from_local_waker(&local_waker) /// .waker(&waker) /// .build(); /// -/// let future = pin::pin!(async { 20 }); -/// let poll = future.poll(&mut context); -/// assert_eq!(poll, task::Poll::Ready(20)); +/// let mut future = std::pin::pin!(async { 20 }); +/// let poll = future.as_mut().poll(&mut cx); +/// assert_eq!(poll, Poll::Ready(20)); /// /// ``` #[unstable(feature = "local_waker", issue = "none")] @@ -323,6 +335,50 @@ impl<'a> ContextBuilder<'a> { } } +/// Construct a `ContextBuilder`` from a `Context`. This is useful for +/// overriding values from a context. +/// +/// # Examples +/// An example of a future that allows to set a Waker on Context if none was defined. +/// This can be used to await futures that require a `Waker` even if the runtime does not +/// support `Waker`. +/// ```rust +/// #![feature(noop_waker, local_waker)] +/// use std::task::{Waker, ContextBuilder}; +/// use std::future::{poll_fn, Future}; +/// use std::pin::pin; +/// +/// async fn with_waker(f: F, waker: &Waker) -> F::Output +/// where +/// F: Future +/// { +/// let mut f = pin!(f); +/// poll_fn(move |cx| { +/// let has_waker = cx.try_waker().is_some(); +/// if has_waker { +/// return f.as_mut().poll(cx); +/// } +/// +/// let mut cx = ContextBuilder::from(cx) +/// .waker(&waker) +/// .build(); +/// f.as_mut().poll(&mut cx) +/// }).await +/// } +/// +/// # async fn __() { +/// with_waker(async { /* ... */ }, &Waker::noop()).await; +/// # } +/// ``` +#[unstable(feature = "local_waker", issue = "none")] +impl<'a> From<&mut Context<'a>> for ContextBuilder<'a> { + #[inline] + fn from(value: &mut Context<'a>) -> Self { + let Context { waker, local_waker, .. } = *value; + ContextBuilder { waker, local_waker } + } +} + /// A `Waker` is a handle for waking up a task by notifying its executor that it /// is ready to be run. /// @@ -559,12 +615,11 @@ impl fmt::Debug for Waker { /// }) /// } /// -/// # #[allow(unused_must_use)] /// # async fn __() { /// yield_now().await; /// # } /// ``` -/// +/// /// [`Future::poll()`]: core::future::Future::poll /// [`Poll::Pending`]: core::task::Poll::Pending /// [`local_waker`]: core::task::Context::local_waker From 2012d4b70370d86c9ed0c60a2ad6bf03d9fc5157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Wed, 6 Dec 2023 15:19:24 -0300 Subject: [PATCH 031/246] fix: make LocalWake available in targets that don't support atomics by removing a #[cfg(target_has_atomic = ptr)] --- library/alloc/src/lib.rs | 2 +- library/alloc/src/task.rs | 18 +++++++++++------- library/core/src/task/wake.rs | 4 ++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index c8b4cebdf8987..878aedce3a6a9 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -254,7 +254,7 @@ pub mod str; pub mod string; #[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))] pub mod sync; -#[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync), target_has_atomic = "ptr"))] +#[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync)))] pub mod task; #[cfg(test)] mod tests; diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 736a55700f63e..9db4c9195052b 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -2,15 +2,17 @@ //! Types and Traits for working with asynchronous tasks. //! -//! **Note**: This module is only available on platforms that support atomic -//! loads and stores of pointers. This may be detected at compile time using +//! **Note**: Some of the types in this module are only available +//! on platforms that support atomic loads and stores of pointers. +//! This may be detected at compile time using //! `#[cfg(target_has_atomic = "ptr")]`. use core::mem::ManuallyDrop; -use core::task::{LocalWaker, RawWaker, RawWakerVTable, Waker}; - +use core::task::{LocalWaker, RawWaker, RawWakerVTable}; use crate::rc::Rc; -use crate::sync::Arc; + +#[cfg(target_has_atomic = "ptr")] +use core::{task::Waker, sync::Arc}; /// The implementation of waking a task on an executor. /// @@ -74,6 +76,7 @@ use crate::sync::Arc; /// println!("Hi from inside a future!"); /// }); /// ``` +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "wake_trait", since = "1.51.0")] pub trait Wake { /// Wake this task. @@ -92,7 +95,7 @@ pub trait Wake { self.clone().wake(); } } - +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "wake_trait", since = "1.51.0")] impl From> for Waker { /// Use a `Wake`-able type as a `Waker`. @@ -104,7 +107,7 @@ impl From> for Waker { unsafe { Waker::from_raw(raw_waker(waker)) } } } - +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "wake_trait", since = "1.51.0")] impl From> for RawWaker { /// Use a `Wake`-able type as a `RawWaker`. @@ -120,6 +123,7 @@ impl From> for RawWaker { // the safety of `From> for Waker` does not depend on the correct // trait dispatch - instead both impls call this function directly and // explicitly. +#[cfg(target_has_atomic = "ptr")] #[inline(always)] fn raw_waker(waker: Arc) -> RawWaker { // Increment the reference count of the arc to clone it. diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index fa4590f18ec98..5696b63e5faf7 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -347,7 +347,7 @@ impl<'a> ContextBuilder<'a> { /// use std::task::{Waker, ContextBuilder}; /// use std::future::{poll_fn, Future}; /// use std::pin::pin; -/// +/// /// async fn with_waker(f: F, waker: &Waker) -> F::Output /// where /// F: Future @@ -365,7 +365,7 @@ impl<'a> ContextBuilder<'a> { /// f.as_mut().poll(&mut cx) /// }).await /// } -/// +/// /// # async fn __() { /// with_waker(async { /* ... */ }, &Waker::noop()).await; /// # } From 0cb7a0a90ef5862b87083546accb12467b279eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Thu, 14 Dec 2023 23:15:01 -0300 Subject: [PATCH 032/246] chore: add tracking issue number to local waker feature --- library/alloc/src/task.rs | 22 ++++++++++++---------- library/core/src/task/wake.rs | 28 ++++++++++++++-------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 9db4c9195052b..ce7aa3c44dc84 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -3,16 +3,18 @@ //! Types and Traits for working with asynchronous tasks. //! //! **Note**: Some of the types in this module are only available -//! on platforms that support atomic loads and stores of pointers. -//! This may be detected at compile time using +//! on platforms that support atomic loads and stores of pointers. +//! This may be detected at compile time using //! `#[cfg(target_has_atomic = "ptr")]`. +use crate::rc::Rc; use core::mem::ManuallyDrop; use core::task::{LocalWaker, RawWaker, RawWakerVTable}; -use crate::rc::Rc; #[cfg(target_has_atomic = "ptr")] -use core::{task::Waker, sync::Arc}; +use crate::sync::Arc; +#[cfg(target_has_atomic = "ptr")] +use core::task::Waker; /// The implementation of waking a task on an executor. /// @@ -174,7 +176,7 @@ fn raw_waker(waker: Arc) -> RawWaker { /// and poll them. When a task is woken, it will put itself back on the run queue to be polled by the executor. /// /// **Note:** A real world example would interlieve poll calls with calls to an io reactor to wait for events instead -/// of spinning on a loop. +/// of spinning on a loop. /// /// ```rust /// #![feature(local_waker)] @@ -242,10 +244,10 @@ fn raw_waker(waker: Arc) -> RawWaker { /// }); /// ``` /// -#[unstable(feature = "local_waker", issue = "none")] +#[unstable(feature = "local_waker", issue = "118959")] pub trait LocalWake { /// Wake this task. - #[unstable(feature = "local_waker", issue = "none")] + #[unstable(feature = "local_waker", issue = "118959")] fn wake(self: Rc); /// Wake this task without consuming the local waker. @@ -255,13 +257,13 @@ pub trait LocalWake { /// [`Rc`] and calls [`wake`] on the clone. /// /// [`wake`]: Rc::wake - #[unstable(feature = "local_waker", issue = "none")] + #[unstable(feature = "local_waker", issue = "118959")] fn wake_by_ref(self: &Rc) { self.clone().wake(); } } -#[unstable(feature = "local_waker", issue = "none")] +#[unstable(feature = "local_waker", issue = "118959")] impl From> for LocalWaker { /// Use a `Wake`-able type as a `LocalWaker`. /// @@ -273,7 +275,7 @@ impl From> for LocalWaker { } } #[allow(ineffective_unstable_trait_impl)] -#[unstable(feature = "local_waker", issue = "none")] +#[unstable(feature = "local_waker", issue = "118959")] impl From> for RawWaker { /// Use a `Wake`-able type as a `RawWaker`. /// diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 5696b63e5faf7..c02504b386e16 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -238,7 +238,7 @@ impl<'a> Context<'a> { } /// Returns a reference to the [`LocalWaker`] for the current task. #[inline] - #[unstable(feature = "local_waker", issue = "none")] + #[unstable(feature = "local_waker", issue = "118959")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] pub const fn local_waker(&self) -> &'a LocalWaker { &self.local_waker @@ -247,7 +247,7 @@ impl<'a> Context<'a> { /// otherwise it returns `None`. #[inline] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] - #[unstable(feature = "local_waker", issue = "none")] + #[unstable(feature = "local_waker", issue = "118959")] pub const fn try_waker(&self) -> Option<&'a Waker> { self.waker } @@ -282,7 +282,7 @@ impl fmt::Debug for Context<'_> { /// assert_eq!(poll, Poll::Ready(20)); /// /// ``` -#[unstable(feature = "local_waker", issue = "none")] +#[unstable(feature = "local_waker", issue = "118959")] #[derive(Debug)] pub struct ContextBuilder<'a> { waker: Option<&'a Waker>, @@ -293,7 +293,7 @@ impl<'a> ContextBuilder<'a> { /// Create a ContextBuilder from a Waker. #[inline] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] - #[unstable(feature = "local_waker", issue = "none")] + #[unstable(feature = "local_waker", issue = "118959")] pub const fn from_waker(waker: &'a Waker) -> Self { // SAFETY: LocalWaker is just Waker without thread safety let local_waker = unsafe { transmute(waker) }; @@ -303,7 +303,7 @@ impl<'a> ContextBuilder<'a> { /// Create a ContextBuilder from a LocalWaker. #[inline] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] - #[unstable(feature = "local_waker", issue = "none")] + #[unstable(feature = "local_waker", issue = "118959")] pub const fn from_local_waker(local_waker: &'a LocalWaker) -> Self { Self { local_waker, waker: None } } @@ -312,14 +312,14 @@ impl<'a> ContextBuilder<'a> { #[inline] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] - #[unstable(feature = "local_waker", issue = "none")] + #[unstable(feature = "local_waker", issue = "118959")] pub const fn waker(self, waker: &'a Waker) -> Self { Self { waker: Some(waker), ..self } } /// This method is used to set the value for the local waker on `Context`. #[inline] - #[unstable(feature = "local_waker", issue = "none")] + #[unstable(feature = "local_waker", issue = "118959")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] pub const fn local_waker(self, local_waker: &'a LocalWaker) -> Self { Self { local_waker, ..self } @@ -327,7 +327,7 @@ impl<'a> ContextBuilder<'a> { /// Builds the `Context`. #[inline] - #[unstable(feature = "local_waker", issue = "none")] + #[unstable(feature = "local_waker", issue = "118959")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] pub const fn build(self) -> Context<'a> { let ContextBuilder { waker, local_waker } = self; @@ -370,7 +370,7 @@ impl<'a> ContextBuilder<'a> { /// with_waker(async { /* ... */ }, &Waker::noop()).await; /// # } /// ``` -#[unstable(feature = "local_waker", issue = "none")] +#[unstable(feature = "local_waker", issue = "118959")] impl<'a> From<&mut Context<'a>> for ContextBuilder<'a> { #[inline] fn from(value: &mut Context<'a>) -> Self { @@ -623,19 +623,19 @@ impl fmt::Debug for Waker { /// [`Future::poll()`]: core::future::Future::poll /// [`Poll::Pending`]: core::task::Poll::Pending /// [`local_waker`]: core::task::Context::local_waker -#[unstable(feature = "local_waker", issue = "none")] +#[unstable(feature = "local_waker", issue = "118959")] #[repr(transparent)] pub struct LocalWaker { waker: RawWaker, } -#[unstable(feature = "local_waker", issue = "none")] +#[unstable(feature = "local_waker", issue = "118959")] impl Unpin for LocalWaker {} impl LocalWaker { /// Creates a new `LocalWaker` from [`RawWaker`]. /// - /// The behavior of the returned `Waker` is undefined if the contract defined + /// The behavior of the returned `LocalWaker` is undefined if the contract defined /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. /// Therefore this method is unsafe. #[inline] @@ -651,7 +651,7 @@ impl LocalWaker { /// As long as the executor keeps running and the task is not finished, it is /// guaranteed that each invocation of [`wake()`](Self::wake) (or /// [`wake_by_ref()`](Self::wake_by_ref)) will be followed by at least one - /// [`poll()`] of the task to which this `Waker` belongs. This makes + /// [`poll()`] of the task to which this `LocalWaker` belongs. This makes /// it possible to temporarily yield to other tasks while running potentially /// unbounded processing loops. /// @@ -749,7 +749,7 @@ impl LocalWaker { unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) } } } -#[unstable(feature = "local_waker", issue = "none")] +#[unstable(feature = "local_waker", issue = "118959")] impl Clone for LocalWaker { #[inline] fn clone(&self) -> Self { From f82437396fe2d21ae73134a6faa6c58bd03d96e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Thu, 14 Dec 2023 23:15:27 -0300 Subject: [PATCH 033/246] feat: impl AsRef for Waker. --- library/core/src/task/wake.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index c02504b386e16..e90994df0c720 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -769,6 +769,14 @@ impl Clone for LocalWaker { } } +#[unstable(feature = "local_waker", issue = "118959")] +impl AsRef for Waker { + fn as_ref(&self) -> &LocalWaker { + // SAFETY: LocalWaker is just Waker without thread safety + unsafe { transmute(self) } + } +} + #[stable(feature = "futures_api", since = "1.36.0")] impl fmt::Debug for LocalWaker { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { From 093f80ba7edc53a7e53c949fb0d083f00088d45c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Thu, 14 Dec 2023 23:38:58 -0300 Subject: [PATCH 034/246] chore: fix ci failures --- library/alloc/src/task.rs | 2 +- library/core/src/task/wake.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index ce7aa3c44dc84..611468a9feaab 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -256,7 +256,7 @@ pub trait LocalWake { /// waker, it should override this method. By default, it clones the /// [`Rc`] and calls [`wake`] on the clone. /// - /// [`wake`]: Rc::wake + /// [`wake`]: LocalWaker::wake #[unstable(feature = "local_waker", issue = "118959")] fn wake_by_ref(self: &Rc) { self.clone().wake(); diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index e90994df0c720..54528ad83a04e 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -269,7 +269,7 @@ impl fmt::Debug for Context<'_> { /// #![feature(noop_waker)] /// use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; /// use std::future::Future; -/// +/// /// let local_waker = LocalWaker::noop(); /// let waker = Waker::noop(); /// @@ -347,7 +347,7 @@ impl<'a> ContextBuilder<'a> { /// use std::task::{Waker, ContextBuilder}; /// use std::future::{poll_fn, Future}; /// use std::pin::pin; -/// +/// /// async fn with_waker(f: F, waker: &Waker) -> F::Output /// where /// F: Future @@ -365,7 +365,7 @@ impl<'a> ContextBuilder<'a> { /// f.as_mut().poll(&mut cx) /// }).await /// } -/// +/// /// # async fn __() { /// with_waker(async { /* ... */ }, &Waker::noop()).await; /// # } From ad28f755d82308b1e30f504d241b810f396233d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Fri, 15 Dec 2023 10:20:33 -0300 Subject: [PATCH 035/246] fix: change issue number of waker_getters from #87021 to #96992. --- library/core/src/task/wake.rs | 2 +- src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 54528ad83a04e..3fc97a199a6bf 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -713,7 +713,7 @@ impl LocalWaker { /// Get a reference to the underlying [`RawWaker`]. #[inline] #[must_use] - #[unstable(feature = "waker_getters", issue = "87021")] + #[unstable(feature = "waker_getters", issue = "96992")] pub fn as_raw(&self) -> &RawWaker { &self.waker } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index 1cb6ff8627a23..c3b806dec4dda 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -9630,9 +9630,9 @@ The tracking issue for this feature is: [#81944] label: "waker_getters", description: r##"# `waker_getters` -The tracking issue for this feature is: [#87021] +The tracking issue for this feature is: [#96992] -[#87021]: https://github.com/rust-lang/rust/issues/87021 +[#96992]: https://github.com/rust-lang/rust/issues/96992 ------------------------ "##, From 3e373f5ee7ab5cf6d9fe986f697fe27fe90c53ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Fri, 15 Dec 2023 10:30:43 -0300 Subject: [PATCH 036/246] chore: add and !Sync impls for LocalWaker as a stability guarantee. --- library/core/src/task/wake.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 3fc97a199a6bf..40f0b0c51446f 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -787,3 +787,8 @@ impl fmt::Debug for LocalWaker { .finish() } } + +#[unstable(feature = "local_waker", issue = "118959")] +impl !Send for LocalWaker {} +#[unstable(feature = "local_waker", issue = "118959")] +impl !Sync for LocalWaker {} From a8e71f225817d11acd9ba63721d539fb998ef319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Fri, 15 Dec 2023 15:10:15 -0300 Subject: [PATCH 037/246] doc: update thread safety explanation for RawWakerVTable and RawWaker. --- library/core/src/task/wake.rs | 62 ++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 40f0b0c51446f..3fa49d1ea0654 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -7,7 +7,7 @@ use crate::marker::PhantomData; use crate::ptr; /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`] -/// which provides customized wakeup behavior. +/// or a [`LocalWaker`] which provides customized wakeup behavior. /// /// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table /// @@ -35,9 +35,18 @@ impl RawWaker { /// The value of this pointer will get passed to all functions that are part /// of the `vtable` as the first parameter. /// + /// It is important to consider that the `data` pointer must point to a + /// thread safe type such as an `[Arc]` + /// when used to construct a [`Waker`]. This restriction is lifted when + /// constructing a [`LocalWaker`], which allows using types that do not implement + /// [Send] + [Sync] like `[Rc]`. + /// /// The `vtable` customizes the behavior of a `Waker` which gets created /// from a `RawWaker`. For each operation on the `Waker`, the associated /// function in the `vtable` of the underlying `RawWaker` will be called. + /// + /// [`Arc`]: std::sync::Arc + /// [`Rc`]: std::rc::Rc #[inline] #[rustc_promotable] #[stable(feature = "futures_api", since = "1.36.0")] @@ -90,11 +99,19 @@ impl RawWaker { /// [`RawWaker`] implementation. Calling one of the contained functions using /// any other `data` pointer will cause undefined behavior. /// -/// These functions must all be thread-safe (even though [`RawWaker`] is -/// \![Send] + \![Sync]) -/// because [`Waker`] is [Send] + [Sync], and thus wakers may be moved to -/// arbitrary threads or invoked by `&` reference. For example, this means that if the -/// `clone` and `drop` functions manage a reference count, they must do so atomically. +/// # Thread safety +/// If the [`RawWaker`] will be used to construct a [`Waker`] then +/// these functions must all be thread-safe (even though [`RawWaker`] is +/// \![Send] + \![Sync]). This is because [`Waker`] is [Send] + [Sync], +/// and it may be moved to arbitrary threads or invoked by `&` reference. For example, +/// this means that if the `clone` and `drop` functions manage a reference count, +/// they must do so atomically. +/// +/// However, if the [`RawWaker`] will be used to construct a [`LocalWaker`] instead, then +/// these functions don't need to be thread safe. This means that \![Send] + \![Sync] +/// data can be stored in the data pointer, and reference counting does not need any atomic +/// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot +/// be sent across threads. #[stable(feature = "futures_api", since = "1.36.0")] #[derive(PartialEq, Copy, Clone, Debug)] pub struct RawWakerVTable { @@ -134,16 +151,22 @@ impl RawWakerVTable { /// Creates a new `RawWakerVTable` from the provided `clone`, `wake`, /// `wake_by_ref`, and `drop` functions. /// - /// These functions must all be thread-safe (even though [`RawWaker`] is - /// \![Send] + \![Sync]) - /// because [`Waker`] is [Send] + [Sync], and thus wakers may be moved to - /// arbitrary threads or invoked by `&` reference. For example, this means that if the - /// `clone` and `drop` functions manage a reference count, they must do so atomically. - /// + /// If the [`RawWaker`] will be used to construct a [`Waker`] then + /// these functions must all be thread-safe (even though [`RawWaker`] is + /// \![Send] + \![Sync]). This is because [`Waker`] is [Send] + [Sync], + /// and it may be moved to arbitrary threads or invoked by `&` reference. For example, + /// this means that if the `clone` and `drop` functions manage a reference count, + /// they must do so atomically. + /// + /// However, if the [`RawWaker`] will be used to construct a [`LocalWaker`] instead, then + /// these functions don't need to be thread safe. This means that \![Send] + \![Sync] + /// data can be stored in the data pointer, and reference counting does not need any atomic + /// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot + /// be sent across threads. /// # `clone` /// /// This function will be called when the [`RawWaker`] gets cloned, e.g. when - /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned. + /// the [`Waker`]/[`LocalWaker`] in which the [`RawWaker`] is stored gets cloned. /// /// The implementation of this function must retain all resources that are /// required for this additional instance of a [`RawWaker`] and associated @@ -169,7 +192,7 @@ impl RawWakerVTable { /// /// # `drop` /// - /// This function gets called when a [`Waker`] gets dropped. + /// This function gets called when a [`Waker`]/[`LocalWaker`] gets dropped. /// /// The implementation of this function must make sure to release any /// resources that are associated with this instance of a [`RawWaker`] and @@ -335,13 +358,13 @@ impl<'a> ContextBuilder<'a> { } } -/// Construct a `ContextBuilder`` from a `Context`. This is useful for +/// Construct a [`ContextBuilder`] from a [`Context`]. This is useful for /// overriding values from a context. /// /// # Examples -/// An example of a future that allows to set a Waker on Context if none was defined. -/// This can be used to await futures that require a `Waker` even if the runtime does not -/// support `Waker`. +/// An example of a future that allows to set a [`Waker`] on Context if none was defined. +/// This can be used to await futures that require a [`Waker`] even if the runtime does not +/// support [`Waker`]. /// ```rust /// #![feature(noop_waker, local_waker)] /// use std::task::{Waker, ContextBuilder}; @@ -596,7 +619,7 @@ impl fmt::Debug for Waker { /// unnecessarily if the two wakers [wake the same task](Self::will_wake). /// /// # Examples -/// Usage of a local waker to implement a future +/// Usage of a local waker to implement a future analogous to `std::thread::yield_now()`. /// ``` /// #![feature(local_waker)] /// use std::future::{Future, poll_fn}; @@ -623,6 +646,7 @@ impl fmt::Debug for Waker { /// [`Future::poll()`]: core::future::Future::poll /// [`Poll::Pending`]: core::task::Poll::Pending /// [`local_waker`]: core::task::Context::local_waker + #[unstable(feature = "local_waker", issue = "118959")] #[repr(transparent)] pub struct LocalWaker { From c67a446e72764663892606b131ed35c6e32e7133 Mon Sep 17 00:00:00 2001 From: tvallotton <57121854+tvallotton@users.noreply.github.com> Date: Sat, 13 Jan 2024 10:44:01 -0300 Subject: [PATCH 038/246] fix: Apply suggestions from code review Co-authored-by: Mark Rousskov --- library/alloc/src/task.rs | 6 +++--- library/core/src/task/wake.rs | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 611468a9feaab..7dad2f3f82270 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -168,14 +168,14 @@ fn raw_waker(waker: Arc) -> RawWaker { /// to hold data that does not implement `Send` and `Sync`. Additionally, it saves calls /// to `Arc::clone`, which requires atomic synchronization. /// - +/// /// # Examples /// /// This is a simplified example of a `spawn` and a `block_on` function. The `spawn` function /// is used to push new tasks onto the run queue, while the block on function will remove them /// and poll them. When a task is woken, it will put itself back on the run queue to be polled by the executor. /// -/// **Note:** A real world example would interlieve poll calls with calls to an io reactor to wait for events instead +/// **Note:** A real world example would interleave poll calls with calls to an io reactor to wait for events instead /// of spinning on a loop. /// /// ```rust @@ -221,7 +221,7 @@ fn raw_waker(waker: Arc) -> RawWaker { /// { /// spawn(future); /// loop { -/// let Some(task) = RUN_QUEUE.with_borrow_mut(|queue|queue.pop_front()) else { +/// let Some(task) = RUN_QUEUE.with_borrow_mut(|queue| queue.pop_front()) else { /// // we exit, since there are no more tasks remaining on the queue /// return; /// }; diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 3fa49d1ea0654..da34e070e2922 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -332,7 +332,6 @@ impl<'a> ContextBuilder<'a> { } /// This field is used to set the value of the waker on `Context`. - #[inline] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] #[unstable(feature = "local_waker", issue = "118959")] @@ -598,6 +597,7 @@ impl fmt::Debug for Waker { } /// A `LocalWaker` is analogous to a [`Waker`], but it does not implement [`Send`] or [`Sync`]. +/// /// This handle encapsulates a [`RawWaker`] instance, which defines the /// executor-specific wakeup behavior. /// @@ -646,9 +646,8 @@ impl fmt::Debug for Waker { /// [`Future::poll()`]: core::future::Future::poll /// [`Poll::Pending`]: core::task::Poll::Pending /// [`local_waker`]: core::task::Context::local_waker - #[unstable(feature = "local_waker", issue = "118959")] -#[repr(transparent)] +#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401 pub struct LocalWaker { waker: RawWaker, } From eccb5e7c1bc3b36ed19bbca75ddf80470d3f0caa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Sat, 13 Jan 2024 11:14:04 -0300 Subject: [PATCH 039/246] docs: remove recommendations to use LocalWaker in stable API documentation --- library/core/src/task/wake.rs | 103 +++++++++++++++------------------- 1 file changed, 46 insertions(+), 57 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index da34e070e2922..e64a25960e05e 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -39,7 +39,7 @@ impl RawWaker { /// thread safe type such as an `[Arc]` /// when used to construct a [`Waker`]. This restriction is lifted when /// constructing a [`LocalWaker`], which allows using types that do not implement - /// [Send] + [Sync] like `[Rc]`. + /// [Send] + [Sync] like `[Rc]`. /// /// The `vtable` customizes the behavior of a `Waker` which gets created /// from a `RawWaker`. For each operation on the `Waker`, the associated @@ -240,16 +240,6 @@ impl<'a> Context<'a> { } /// Returns a reference to the [`Waker`] for the current task. - /// - /// Note that if the waker does not need to be sent across threads, it - /// is preferable to call `local_waker`, which is more portable and - /// potentially more efficient. - /// - /// # Panics - /// This function will panic if no `Waker` was set on the context. This happens if - /// the executor does not support working with thread safe wakers. An alternative - /// may be to call [`.local_waker()`](Context::local_waker) instead. For a fallible - /// version of this function see [`.try_waker()`](Context::try_waker). #[inline] #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] @@ -396,7 +386,7 @@ impl<'a> ContextBuilder<'a> { impl<'a> From<&mut Context<'a>> for ContextBuilder<'a> { #[inline] fn from(value: &mut Context<'a>) -> Self { - let Context { waker, local_waker, .. } = *value; + let Context { waker, local_waker, _marker, _marker2 } = *value; ContextBuilder { waker, local_waker } } } @@ -415,8 +405,7 @@ impl<'a> From<&mut Context<'a>> for ContextBuilder<'a> { /// Implements [`Clone`], [`Send`], and [`Sync`]; therefore, a waker may be invoked /// from any thread, including ones not in any way managed by the executor. For example, /// this might be done to wake a future when a blocking function call completes on another -/// thread. If the waker does not need to be moved across threads, it is better to use -/// [`LocalWaker`], which the executor may use to skip unnecessary memory synchronization. +/// thread. /// /// Note that it is preferable to use `waker.clone_from(&new_waker)` instead /// of `*waker = new_waker.clone()`, as the former will avoid cloning the waker @@ -656,19 +645,6 @@ pub struct LocalWaker { impl Unpin for LocalWaker {} impl LocalWaker { - /// Creates a new `LocalWaker` from [`RawWaker`]. - /// - /// The behavior of the returned `LocalWaker` is undefined if the contract defined - /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. - /// Therefore this method is unsafe. - #[inline] - #[must_use] - #[stable(feature = "futures_api", since = "1.36.0")] - #[rustc_const_unstable(feature = "const_waker", issue = "102012")] - pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker { - Self { waker } - } - /// Wake up the task associated with this `LocalWaker`. /// /// As long as the executor keeps running and the task is not finished, it is @@ -703,6 +679,37 @@ impl LocalWaker { unsafe { (wake)(data) }; } + /// Wake up the task associated with this `LocalWaker` without consuming the `LocalWaker`. + /// + /// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in + /// the case where an owned `Waker` is available. This method should be preferred to + /// calling `waker.clone().wake()`. + #[inline] + #[stable(feature = "futures_api", since = "1.36.0")] + pub fn wake_by_ref(&self) { + // The actual wakeup call is delegated through a virtual function call + // to the implementation which is defined by the executor. + + // SAFETY: see `wake` + unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) } + } + + /// Returns `true` if this `LocalWaker` and another `LocalWaker` would awake the same task. + /// + /// This function works on a best-effort basis, and may return false even + /// when the `Waker`s would awaken the same task. However, if this function + /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task. + /// + /// This function is primarily used for optimization purposes — for example, + /// this type's [`clone_from`](Self::clone_from) implementation uses it to + /// avoid cloning the waker when they would wake the same task anyway. + #[inline] + #[must_use] + #[stable(feature = "futures_api", since = "1.36.0")] + pub fn will_wake(&self, other: &LocalWaker) -> bool { + self.waker == other.waker + } + /// Creates a new `LocalWaker` that does nothing when `wake` is called. /// /// This is mostly useful for writing tests that need a [`Context`] to poll @@ -733,43 +740,25 @@ impl LocalWaker { WAKER } - /// Get a reference to the underlying [`RawWaker`]. - #[inline] - #[must_use] - #[unstable(feature = "waker_getters", issue = "96992")] - pub fn as_raw(&self) -> &RawWaker { - &self.waker - } - - /// Returns `true` if this `LocalWaker` and another `LocalWaker` would awake the same task. - /// - /// This function works on a best-effort basis, and may return false even - /// when the `Waker`s would awaken the same task. However, if this function - /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task. + /// Creates a new `LocalWaker` from [`RawWaker`]. /// - /// This function is primarily used for optimization purposes — for example, - /// this type's [`clone_from`](Self::clone_from) implementation uses it to - /// avoid cloning the waker when they would wake the same task anyway. + /// The behavior of the returned `LocalWaker` is undefined if the contract defined + /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. + /// Therefore this method is unsafe. #[inline] #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] - pub fn will_wake(&self, other: &LocalWaker) -> bool { - self.waker == other.waker + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker { + Self { waker } } - /// Wake up the task associated with this `LocalWaker` without consuming the `LocalWaker`. - /// - /// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in - /// the case where an owned `Waker` is available. This method should be preferred to - /// calling `waker.clone().wake()`. + /// Get a reference to the underlying [`RawWaker`]. #[inline] - #[stable(feature = "futures_api", since = "1.36.0")] - pub fn wake_by_ref(&self) { - // The actual wakeup call is delegated through a virtual function call - // to the implementation which is defined by the executor. - - // SAFETY: see `wake` - unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) } + #[must_use] + #[unstable(feature = "waker_getters", issue = "96992")] + pub fn as_raw(&self) -> &RawWaker { + &self.waker } } #[unstable(feature = "local_waker", issue = "118959")] From 7c6a9cbef103c0a9511aedad691a040ceb003917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Sat, 13 Jan 2024 11:18:18 -0300 Subject: [PATCH 040/246] chore: make method order consistent with waker --- library/core/src/task/wake.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index e64a25960e05e..6a5b5a3fb544d 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -710,6 +710,19 @@ impl LocalWaker { self.waker == other.waker } + /// Creates a new `LocalWaker` from [`RawWaker`]. + /// + /// The behavior of the returned `LocalWaker` is undefined if the contract defined + /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. + /// Therefore this method is unsafe. + #[inline] + #[must_use] + #[stable(feature = "futures_api", since = "1.36.0")] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker { + Self { waker } + } + /// Creates a new `LocalWaker` that does nothing when `wake` is called. /// /// This is mostly useful for writing tests that need a [`Context`] to poll @@ -740,19 +753,6 @@ impl LocalWaker { WAKER } - /// Creates a new `LocalWaker` from [`RawWaker`]. - /// - /// The behavior of the returned `LocalWaker` is undefined if the contract defined - /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. - /// Therefore this method is unsafe. - #[inline] - #[must_use] - #[stable(feature = "futures_api", since = "1.36.0")] - #[rustc_const_unstable(feature = "const_waker", issue = "102012")] - pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker { - Self { waker } - } - /// Get a reference to the underlying [`RawWaker`]. #[inline] #[must_use] From 038c6e046c450082ebd087336d9b11979e0dd4f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Sat, 13 Jan 2024 14:57:13 -0300 Subject: [PATCH 041/246] refactor: make waker mandatory. This also removes * impl From<&Context> for ContextBuilder * Context::try_waker() The from implementation is removed because now that wakers are always supported, there are less incentives to override the current context. Before, the incentive was to add Waker support to a reactor that didn't have any. --- library/alloc/src/task.rs | 16 +++--- library/core/src/task/wake.rs | 99 +++++++---------------------------- 2 files changed, 28 insertions(+), 87 deletions(-) diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 7dad2f3f82270..357f7e0650ae7 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -173,14 +173,16 @@ fn raw_waker(waker: Arc) -> RawWaker { /// /// This is a simplified example of a `spawn` and a `block_on` function. The `spawn` function /// is used to push new tasks onto the run queue, while the block on function will remove them -/// and poll them. When a task is woken, it will put itself back on the run queue to be polled by the executor. +/// and poll them. When a task is woken, it will put itself back on the run queue to be polled +/// by the executor. /// -/// **Note:** A real world example would interleave poll calls with calls to an io reactor to wait for events instead -/// of spinning on a loop. +/// **Note:** This example trades correctness for simplicity. A real world example would interleave +/// poll calls with calls to an io reactor to wait for events instead of spinning on a loop. /// /// ```rust /// #![feature(local_waker)] -/// use std::task::{LocalWake, ContextBuilder, LocalWaker}; +/// #![feature(noop_waker)] +/// use std::task::{LocalWake, ContextBuilder, LocalWaker, Waker}; /// use std::future::Future; /// use std::pin::Pin; /// use std::rc::Rc; @@ -225,10 +227,12 @@ fn raw_waker(waker: Arc) -> RawWaker { /// // we exit, since there are no more tasks remaining on the queue /// return; /// }; +/// let waker = Waker::noop(); /// // cast the Rc into a `LocalWaker` -/// let waker: LocalWaker = task.clone().into(); +/// let local_waker: LocalWaker = task.clone().into(); /// // Build the context using `ContextBuilder` -/// let mut cx = ContextBuilder::from_local_waker(&waker) +/// let mut cx = ContextBuilder::from_waker(&waker) +/// .local_waker(&local_waker) /// .build(); /// /// // Poll the task diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 6a5b5a3fb544d..a746fe58f47de 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -217,7 +217,7 @@ impl RawWakerVTable { #[stable(feature = "futures_api", since = "1.36.0")] #[lang = "Context"] pub struct Context<'a> { - waker: Option<&'a Waker>, + waker: &'a Waker, local_waker: &'a LocalWaker, // Ensure we future-proof against variance changes by forcing // the lifetime to be invariant (argument-position lifetimes @@ -245,9 +245,7 @@ impl<'a> Context<'a> { #[stable(feature = "futures_api", since = "1.36.0")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] pub const fn waker(&self) -> &'a Waker { - &self - .waker - .expect("no waker was set on this context, consider calling `local_waker` instead.") + &self.waker } /// Returns a reference to the [`LocalWaker`] for the current task. #[inline] @@ -256,14 +254,6 @@ impl<'a> Context<'a> { pub const fn local_waker(&self) -> &'a LocalWaker { &self.local_waker } - /// Returns a `Some(&Waker)` if a waker was defined on the `Context`, - /// otherwise it returns `None`. - #[inline] - #[rustc_const_unstable(feature = "const_waker", issue = "102012")] - #[unstable(feature = "local_waker", issue = "118959")] - pub const fn try_waker(&self) -> Option<&'a Waker> { - self.waker - } } #[stable(feature = "futures_api", since = "1.36.0")] @@ -286,8 +276,8 @@ impl fmt::Debug for Context<'_> { /// let local_waker = LocalWaker::noop(); /// let waker = Waker::noop(); /// -/// let mut cx = ContextBuilder::from_local_waker(&local_waker) -/// .waker(&waker) +/// let mut cx = ContextBuilder::from_waker(&waker) +/// .local_waker(&local_waker) /// .build(); /// /// let mut future = std::pin::pin!(async { 20 }); @@ -298,8 +288,16 @@ impl fmt::Debug for Context<'_> { #[unstable(feature = "local_waker", issue = "118959")] #[derive(Debug)] pub struct ContextBuilder<'a> { - waker: Option<&'a Waker>, + waker: &'a Waker, local_waker: &'a LocalWaker, + // Ensure we future-proof against variance changes by forcing + // the lifetime to be invariant (argument-position lifetimes + // are contravariant while return-position lifetimes are + // covariant). + _marker: PhantomData &'a ()>, + // Ensure `Context` is `!Send` and `!Sync` in order to allow + // for future `!Send` and / or `!Sync` fields. + _marker2: PhantomData<*mut ()>, } impl<'a> ContextBuilder<'a> { @@ -310,23 +308,7 @@ impl<'a> ContextBuilder<'a> { pub const fn from_waker(waker: &'a Waker) -> Self { // SAFETY: LocalWaker is just Waker without thread safety let local_waker = unsafe { transmute(waker) }; - Self { waker: Some(waker), local_waker } - } - - /// Create a ContextBuilder from a LocalWaker. - #[inline] - #[rustc_const_unstable(feature = "const_waker", issue = "102012")] - #[unstable(feature = "local_waker", issue = "118959")] - pub const fn from_local_waker(local_waker: &'a LocalWaker) -> Self { - Self { local_waker, waker: None } - } - - /// This field is used to set the value of the waker on `Context`. - #[inline] - #[rustc_const_unstable(feature = "const_waker", issue = "102012")] - #[unstable(feature = "local_waker", issue = "118959")] - pub const fn waker(self, waker: &'a Waker) -> Self { - Self { waker: Some(waker), ..self } + Self { waker: waker, local_waker, _marker: PhantomData, _marker2: PhantomData } } /// This method is used to set the value for the local waker on `Context`. @@ -342,52 +324,8 @@ impl<'a> ContextBuilder<'a> { #[unstable(feature = "local_waker", issue = "118959")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] pub const fn build(self) -> Context<'a> { - let ContextBuilder { waker, local_waker } = self; - Context { waker, local_waker, _marker: PhantomData, _marker2: PhantomData } - } -} - -/// Construct a [`ContextBuilder`] from a [`Context`]. This is useful for -/// overriding values from a context. -/// -/// # Examples -/// An example of a future that allows to set a [`Waker`] on Context if none was defined. -/// This can be used to await futures that require a [`Waker`] even if the runtime does not -/// support [`Waker`]. -/// ```rust -/// #![feature(noop_waker, local_waker)] -/// use std::task::{Waker, ContextBuilder}; -/// use std::future::{poll_fn, Future}; -/// use std::pin::pin; -/// -/// async fn with_waker(f: F, waker: &Waker) -> F::Output -/// where -/// F: Future -/// { -/// let mut f = pin!(f); -/// poll_fn(move |cx| { -/// let has_waker = cx.try_waker().is_some(); -/// if has_waker { -/// return f.as_mut().poll(cx); -/// } -/// -/// let mut cx = ContextBuilder::from(cx) -/// .waker(&waker) -/// .build(); -/// f.as_mut().poll(&mut cx) -/// }).await -/// } -/// -/// # async fn __() { -/// with_waker(async { /* ... */ }, &Waker::noop()).await; -/// # } -/// ``` -#[unstable(feature = "local_waker", issue = "118959")] -impl<'a> From<&mut Context<'a>> for ContextBuilder<'a> { - #[inline] - fn from(value: &mut Context<'a>) -> Self { - let Context { waker, local_waker, _marker, _marker2 } = *value; - ContextBuilder { waker, local_waker } + let ContextBuilder { waker, local_waker, _marker, _marker2 } = self; + Context { waker, local_waker, _marker, _marker2 } } } @@ -600,8 +538,7 @@ impl fmt::Debug for Waker { /// Implements [`Clone`], but neither [`Send`] nor [`Sync`]; therefore, a local waker may /// not be moved to other threads. In general, when deciding to use wakers or local wakers, /// local wakers are preferable unless the waker needs to be sent across threads. This is because -/// wakers can incur in additional cost related to memory synchronization, and not all executors -/// may support wakers. +/// wakers can incur in additional cost related to memory synchronization. /// /// Note that it is preferable to use `local_waker.clone_from(&new_waker)` instead /// of `*local_waker = new_waker.clone()`, as the former will avoid cloning the waker @@ -738,7 +675,7 @@ impl LocalWaker { /// use std::future::Future; /// use std::task::{ContextBuilder, LocalWaker}; /// - /// let mut cx = task::ContextBuilder::new() + /// let mut cx = task::ContextBuilder::from_waker(Waker::noop()) /// .local_waker(LocalWaker::noop()) /// .build(); /// From 180c68bef5f42bd61f517e1a48db4152b6e1989e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Vallotton?= Date: Sat, 20 Jan 2024 10:25:00 -0300 Subject: [PATCH 042/246] doc: fix some doctests after rebase --- library/alloc/src/task.rs | 4 ++-- library/core/src/task/wake.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 357f7e0650ae7..87db8629ad09a 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -227,11 +227,11 @@ fn raw_waker(waker: Arc) -> RawWaker { /// // we exit, since there are no more tasks remaining on the queue /// return; /// }; -/// let waker = Waker::noop(); +/// /// // cast the Rc into a `LocalWaker` /// let local_waker: LocalWaker = task.clone().into(); /// // Build the context using `ContextBuilder` -/// let mut cx = ContextBuilder::from_waker(&waker) +/// let mut cx = ContextBuilder::from_waker(Waker::noop()) /// .local_waker(&local_waker) /// .build(); /// diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index a746fe58f47de..9ad71e394eacf 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -673,14 +673,14 @@ impl LocalWaker { /// #![feature(noop_waker)] /// /// use std::future::Future; - /// use std::task::{ContextBuilder, LocalWaker}; + /// use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; /// - /// let mut cx = task::ContextBuilder::from_waker(Waker::noop()) + /// let mut cx = ContextBuilder::from_waker(Waker::noop()) /// .local_waker(LocalWaker::noop()) /// .build(); /// /// let mut future = Box::pin(async { 10 }); - /// assert_eq!(future.as_mut().poll(&mut cx), task::Poll::Ready(10)); + /// assert_eq!(future.as_mut().poll(&mut cx), Poll::Ready(10)); /// ``` #[inline] #[must_use] From edba94907d2f84f35f8e5673a363bf2d42e1c29a Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sat, 20 Jan 2024 08:09:14 -0800 Subject: [PATCH 043/246] update misuse of check-label --- tests/mir-opt/dataflow-const-prop/array_index.rs | 2 +- tests/mir-opt/dataflow-const-prop/checked.rs | 4 ++-- tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs | 4 ++-- tests/mir-opt/dataflow-const-prop/inherit_overflow.rs | 2 +- tests/mir-opt/dataflow-const-prop/large_array_index.rs | 2 +- tests/mir-opt/dataflow-const-prop/repeat.rs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs index e21388ff5d211..8f0cc489a5bb7 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/array_index.rs @@ -15,7 +15,7 @@ fn main() { // CHECK-NOT: assert(move _ // CHECK: {{_.*}} = const 4_usize; // CHECK: {{_.*}} = const true; - // CHECK-LABEL: assert(const true + // CHECK: assert(const true // CHECK: [[x]] = [[array_lit]][2 of 3]; let x: u32 = [0, 1, 2, 3][2]; } diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs index 45331f91323e4..30b0afa8334dd 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.rs +++ b/tests/mir-opt/dataflow-const-prop/checked.rs @@ -19,14 +19,14 @@ fn main() { // CHECK: [[b]] = const 2_i32; let b = 2; - // CHECK-LABEL: assert(!const false, + // CHECK: assert(!const false, // CHECK: [[c]] = const 3_i32; let c = a + b; // CHECK: [[d]] = const _; let d = i32::MAX; - // CHECK-LABEL: assert(!const true, + // CHECK: assert(!const true, // CHECK: [[e]] = const i32::MIN; let e = d + 1; } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs index bfa52b694d0ec..fb708e5084bb9 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -23,7 +23,7 @@ fn main() { // CHECK: debug a => [[a:_.*]]; // We may check other inlined functions as well... - // CHECK-LABEL: _.* = Box::<[bool]>( - // FIXME: should be `_.* = const Box::<[bool]>` + // CHECK: {{_.*}} = Box::<[bool]>( + // FIXME: should be `{{_.*}} = const Box::<[bool]>` let a: A = A { foo: Box::default() }; } diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs index 0a2774c782009..b0acc31e0dbcc 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs @@ -9,6 +9,6 @@ fn main() { // Propagating the overflow is ok as codegen will just skip emitting the panic. // CHECK: {{_.*}} = const (0_u8, true); - // CHECK-LABEL: assert(!const true, + // CHECK: assert(!const true, let _ = ::add(255, 1); } diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.rs b/tests/mir-opt/dataflow-const-prop/large_array_index.rs index fbca411e204d1..62be2c3824fa5 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.rs @@ -12,7 +12,7 @@ fn main() { // CHECK: [[array_lit:_.*]] = [const 0_u8; 5000]; // CHECK: {{_.*}} = const 5000_usize; // CHECK: {{_.*}} = const true; - // CHECK-LABEL: assert(const true + // CHECK: assert(const true // CHECK: [[x]] = [[array_lit]][2 of 3]; let x: u8 = [0_u8; 5000][2]; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.rs b/tests/mir-opt/dataflow-const-prop/repeat.rs index 80eb14dedea3a..daa8dbaf07655 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.rs +++ b/tests/mir-opt/dataflow-const-prop/repeat.rs @@ -12,7 +12,7 @@ fn main() { // CHECK-NOT: {{_.*}} = Lt( // CHECK: {{_.*}} = const 8_usize; // CHECK: {{_.*}} = const true; - // CHECK-LABEL: assert(const true + // CHECK: assert(const true // CHECK-NOT: [[t:_.*]] = [[array_lit]][_ // CHECK: [[t:_.*]] = [[array_lit]][2 of 3]; From 7ad307dc9d014fb8d06e42d495c88328455510c1 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sat, 20 Jan 2024 08:22:07 -0800 Subject: [PATCH 044/246] finish a pattern in `enum.rs` --- tests/mir-opt/dataflow-const-prop/enum.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index 8a6fe3a3fdaa1..86288020bab45 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -132,7 +132,7 @@ fn multiple(x: bool, i: u8) { // CHECK-NOT: [[x2]] = const 5 // CHECK: [[x2]] = const 0_u8; // CHECK-NOT: [[x2]] = const 5 - // CHECK: [[some:_.*]] = (({{_.*}} as Some + // CHECK: [[some:_.*]] = (({{_.*}} as Some).0: u8) // CHECK: [[x2]] = [[some]]; let x2 = match e { Some(i) => i, None => 0 }; From 1a9ef233b736e063d8b51437022b366c77d5ac75 Mon Sep 17 00:00:00 2001 From: r0cky Date: Sun, 21 Jan 2024 12:56:23 +0800 Subject: [PATCH 045/246] Remove unused codes --- crates/hir-ty/src/diagnostics/match_check.rs | 95 ------------------- crates/ide-assists/src/handlers/sort_items.rs | 2 - 2 files changed, 97 deletions(-) diff --git a/crates/hir-ty/src/diagnostics/match_check.rs b/crates/hir-ty/src/diagnostics/match_check.rs index e4d4536fc9321..9e84cd0184cd4 100644 --- a/crates/hir-ty/src/diagnostics/match_check.rs +++ b/crates/hir-ty/src/diagnostics/match_check.rs @@ -413,98 +413,3 @@ where (self.0)(f) } } - -pub(crate) trait PatternFoldable: Sized { - fn fold_with(&self, folder: &mut F) -> Self { - self.super_fold_with(folder) - } - - fn super_fold_with(&self, folder: &mut F) -> Self; -} - -pub(crate) trait PatternFolder: Sized { - fn fold_pattern(&mut self, pattern: &Pat) -> Pat { - pattern.super_fold_with(self) - } - - fn fold_pattern_kind(&mut self, kind: &PatKind) -> PatKind { - kind.super_fold_with(self) - } -} - -impl PatternFoldable for Box { - fn super_fold_with(&self, folder: &mut F) -> Self { - let content: T = (**self).fold_with(folder); - Box::new(content) - } -} - -impl PatternFoldable for Vec { - fn super_fold_with(&self, folder: &mut F) -> Self { - self.iter().map(|t| t.fold_with(folder)).collect() - } -} - -impl PatternFoldable for Option { - fn super_fold_with(&self, folder: &mut F) -> Self { - self.as_ref().map(|t| t.fold_with(folder)) - } -} - -macro_rules! clone_impls { - ($($ty:ty),+) => { - $( - impl PatternFoldable for $ty { - fn super_fold_with(&self, _: &mut F) -> Self { - Clone::clone(self) - } - } - )+ - } -} - -clone_impls! { LocalFieldId, Ty, Substitution, EnumVariantId } - -impl PatternFoldable for FieldPat { - fn super_fold_with(&self, folder: &mut F) -> Self { - FieldPat { field: self.field.fold_with(folder), pattern: self.pattern.fold_with(folder) } - } -} - -impl PatternFoldable for Pat { - fn fold_with(&self, folder: &mut F) -> Self { - folder.fold_pattern(self) - } - - fn super_fold_with(&self, folder: &mut F) -> Self { - Pat { ty: self.ty.fold_with(folder), kind: self.kind.fold_with(folder) } - } -} - -impl PatternFoldable for PatKind { - fn fold_with(&self, folder: &mut F) -> Self { - folder.fold_pattern_kind(self) - } - - fn super_fold_with(&self, folder: &mut F) -> Self { - match self { - PatKind::Wild => PatKind::Wild, - PatKind::Binding { name, subpattern } => { - PatKind::Binding { name: name.clone(), subpattern: subpattern.fold_with(folder) } - } - PatKind::Variant { substs, enum_variant, subpatterns } => PatKind::Variant { - substs: substs.fold_with(folder), - enum_variant: enum_variant.fold_with(folder), - subpatterns: subpatterns.fold_with(folder), - }, - PatKind::Leaf { subpatterns } => { - PatKind::Leaf { subpatterns: subpatterns.fold_with(folder) } - } - PatKind::Deref { subpattern } => { - PatKind::Deref { subpattern: subpattern.fold_with(folder) } - } - &PatKind::LiteralBool { value } => PatKind::LiteralBool { value }, - PatKind::Or { pats } => PatKind::Or { pats: pats.fold_with(folder) }, - } - } -} diff --git a/crates/ide-assists/src/handlers/sort_items.rs b/crates/ide-assists/src/handlers/sort_items.rs index 3a0121f55fa02..64e30b1834522 100644 --- a/crates/ide-assists/src/handlers/sort_items.rs +++ b/crates/ide-assists/src/handlers/sort_items.rs @@ -116,11 +116,9 @@ trait AddRewrite { new: Vec, target: TextRange, ) -> Option<()>; - fn yeet() {} } impl AddRewrite for Assists { - fn yeet() {} fn add_rewrite( &mut self, label: &str, From e4866b6ddb1126646b8d78fc10514ac1ac4c4bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sun, 21 Jan 2024 16:53:06 +0200 Subject: [PATCH 046/246] Merge commit 'a9116523604c998e7781f60d3b5a6f586e0414a9' into sync-from-ra --- .editorconfig | 1 + Cargo.lock | 25 +- Cargo.toml | 73 +- crates/base-db/src/input.rs | 51 +- crates/hir-def/src/attr.rs | 95 +- crates/hir-def/src/body.rs | 19 +- crates/hir-def/src/body/lower.rs | 65 +- crates/hir-def/src/body/pretty.rs | 46 +- crates/hir-def/src/child_by_source.rs | 25 +- crates/hir-def/src/data.rs | 17 +- crates/hir-def/src/data/adt.rs | 205 +- crates/hir-def/src/db.rs | 80 +- crates/hir-def/src/dyn_map/keys.rs | 2 +- crates/hir-def/src/find_path.rs | 14 +- crates/hir-def/src/generics.rs | 10 +- crates/hir-def/src/hir.rs | 2 +- crates/hir-def/src/hir/type_ref.rs | 28 +- crates/hir-def/src/import_map.rs | 12 +- crates/hir-def/src/item_tree.rs | 67 +- crates/hir-def/src/item_tree/lower.rs | 28 +- crates/hir-def/src/item_tree/pretty.rs | 96 +- crates/hir-def/src/item_tree/tests.rs | 69 +- crates/hir-def/src/lang_item.rs | 55 +- crates/hir-def/src/lib.rs | 86 +- .../hir-def/src/macro_expansion_tests/mbe.rs | 22 +- .../hir-def/src/macro_expansion_tests/mod.rs | 11 +- .../src/macro_expansion_tests/proc_macros.rs | 6 +- crates/hir-def/src/nameres.rs | 8 +- crates/hir-def/src/nameres/collector.rs | 171 +- crates/hir-def/src/nameres/diagnostics.rs | 17 + crates/hir-def/src/nameres/path_resolution.rs | 51 +- crates/hir-def/src/nameres/tests/macros.rs | 4 +- crates/hir-def/src/path.rs | 6 +- crates/hir-def/src/path/lower.rs | 2 +- crates/hir-def/src/pretty.rs | 15 +- crates/hir-def/src/resolver.rs | 13 +- crates/hir-def/src/src.rs | 21 +- crates/hir-def/src/trace.rs | 2 + crates/hir-def/src/visibility.rs | 8 +- crates/hir-expand/src/ast_id_map.rs | 10 +- crates/hir-expand/src/attrs.rs | 4 +- crates/hir-expand/src/builtin_derive_macro.rs | 2 +- crates/hir-expand/src/builtin_fn_macro.rs | 9 +- crates/hir-expand/src/db.rs | 17 +- crates/hir-expand/src/fixup.rs | 2 +- crates/hir-expand/src/lib.rs | 16 +- crates/hir-expand/src/mod_path.rs | 2 +- crates/hir-expand/src/name.rs | 22 +- crates/hir-expand/src/quote.rs | 14 +- crates/hir-ty/Cargo.toml | 8 +- crates/hir-ty/src/builder.rs | 14 +- crates/hir-ty/src/chalk_db.rs | 48 +- crates/hir-ty/src/chalk_ext.rs | 10 +- crates/hir-ty/src/consteval.rs | 19 +- crates/hir-ty/src/db.rs | 12 +- crates/hir-ty/src/diagnostics/decl_check.rs | 10 +- crates/hir-ty/src/diagnostics/expr.rs | 46 +- crates/hir-ty/src/diagnostics/match_check.rs | 3 +- .../match_check/deconstruct_pat.rs | 2 +- .../src/diagnostics/match_check/usefulness.rs | 2 +- crates/hir-ty/src/display.rs | 102 +- crates/hir-ty/src/infer.rs | 91 +- crates/hir-ty/src/infer/cast.rs | 1 - crates/hir-ty/src/infer/closure.rs | 46 +- crates/hir-ty/src/infer/coerce.rs | 4 +- crates/hir-ty/src/infer/expr.rs | 43 +- crates/hir-ty/src/infer/pat.rs | 10 +- crates/hir-ty/src/infer/path.rs | 11 +- crates/hir-ty/src/infer/unify.rs | 9 +- crates/hir-ty/src/inhabitedness.rs | 19 +- crates/hir-ty/src/interner.rs | 8 +- crates/hir-ty/src/layout.rs | 14 +- crates/hir-ty/src/layout/adt.rs | 19 +- crates/hir-ty/src/layout/target.rs | 2 +- crates/hir-ty/src/layout/tests.rs | 8 +- crates/hir-ty/src/layout/tests/closure.rs | 15 +- crates/hir-ty/src/lib.rs | 163 +- crates/hir-ty/src/lower.rs | 116 +- crates/hir-ty/src/mapping.rs | 10 +- crates/hir-ty/src/method_resolution.rs | 13 +- crates/hir-ty/src/mir.rs | 46 +- crates/hir-ty/src/mir/borrowck.rs | 34 +- crates/hir-ty/src/mir/eval.rs | 229 +- crates/hir-ty/src/mir/eval/shim.rs | 51 +- crates/hir-ty/src/mir/eval/shim/simd.rs | 4 +- crates/hir-ty/src/mir/eval/tests.rs | 6 +- crates/hir-ty/src/mir/lower.rs | 141 +- crates/hir-ty/src/mir/lower/as_place.rs | 94 +- .../hir-ty/src/mir/lower/pattern_matching.rs | 86 +- crates/hir-ty/src/mir/monomorphization.rs | 4 +- crates/hir-ty/src/mir/pretty.rs | 17 +- crates/hir-ty/src/test_db.rs | 4 +- crates/hir-ty/src/tests.rs | 22 +- crates/hir-ty/src/tests/coercion.rs | 3 +- crates/hir-ty/src/tests/macros.rs | 4 +- crates/hir-ty/src/tests/patterns.rs | 12 +- crates/hir-ty/src/tests/regression.rs | 58 +- crates/hir-ty/src/tests/simple.rs | 80 +- crates/hir-ty/src/tests/traits.rs | 26 +- crates/hir-ty/src/tls.rs | 5 +- crates/hir-ty/src/utils.rs | 26 +- crates/hir/src/attrs.rs | 2 +- crates/hir/src/db.rs | 22 +- crates/hir/src/from_id.rs | 4 +- crates/hir/src/has_source.rs | 2 +- crates/hir/src/lib.rs | 138 +- crates/hir/src/semantics.rs | 14 +- crates/hir/src/semantics/source_to_def.rs | 15 +- crates/hir/src/source_analyzer.rs | 12 +- crates/hir/src/symbols.rs | 4 +- .../src/handlers/add_missing_match_arms.rs | 4 +- .../src/handlers/add_turbo_fish.rs | 4 +- .../ide-assists/src/handlers/auto_import.rs | 4 +- .../ide-assists/src/handlers/bool_to_enum.rs | 8 +- .../src/handlers/change_visibility.rs | 2 +- .../src/handlers/convert_integer_literal.rs | 2 +- .../src/handlers/convert_match_to_let_else.rs | 4 +- .../src/handlers/convert_to_guarded_return.rs | 34 +- .../src/handlers/destructure_tuple_binding.rs | 8 +- .../src/handlers/extract_module.rs | 23 +- .../extract_struct_from_enum_variant.rs | 46 + .../src/handlers/extract_type_alias.rs | 2 +- .../src/handlers/extract_variable.rs | 2 +- .../src/handlers/flip_trait_bound.rs | 4 +- .../src/handlers/generate_constant.rs | 7 +- .../src/handlers/generate_delegate_methods.rs | 2 +- .../src/handlers/generate_delegate_trait.rs | 70 +- .../generate_documentation_template.rs | 2 +- .../src/handlers/generate_enum_is_method.rs | 10 +- .../src/handlers/generate_enum_variant.rs | 4 +- .../handlers/generate_from_impl_for_enum.rs | 2 +- .../src/handlers/generate_getter_or_setter.rs | 18 +- .../ide-assists/src/handlers/generate_impl.rs | 4 +- .../handlers/generate_is_empty_from_len.rs | 2 +- .../src/handlers/generate_trait_from_impl.rs | 26 +- .../ide-assists/src/handlers/inline_call.rs | 147 +- .../src/handlers/inline_const_as_literal.rs | 20 +- .../ide-assists/src/handlers/inline_macro.rs | 2 +- .../src/handlers/introduce_named_generic.rs | 2 +- .../ide-assists/src/handlers/merge_imports.rs | 214 +- .../src/handlers/remove_unused_imports.rs | 10 +- .../src/handlers/replace_if_let_with_match.rs | 2 +- .../replace_is_method_with_if_let_method.rs | 2 +- .../src/handlers/replace_method_eager_lazy.rs | 2 +- .../replace_qualified_name_with_use.rs | 2 +- .../replace_turbofish_with_explicit_type.rs | 4 +- .../src/handlers/unnecessary_async.rs | 6 +- .../ide-assists/src/handlers/unwrap_block.rs | 2 +- crates/ide-assists/src/tests.rs | 44 +- crates/ide-assists/src/tests/sourcegen.rs | 2 +- crates/ide-assists/src/utils.rs | 4 +- .../src/utils/gen_trait_fn_body.rs | 4 +- crates/ide-assists/src/utils/suggest_name.rs | 8 +- crates/ide-completion/src/completions.rs | 8 +- .../src/completions/attribute.rs | 4 +- crates/ide-completion/src/completions/dot.rs | 8 +- .../src/completions/env_vars.rs | 2 +- .../src/completions/extern_abi.rs | 5 +- .../ide-completion/src/completions/field.rs | 28 +- .../src/completions/flyimport.rs | 17 +- .../src/completions/fn_param.rs | 2 +- .../src/completions/item_list.rs | 2 +- .../src/completions/item_list/trait_impl.rs | 12 +- .../ide-completion/src/completions/postfix.rs | 4 +- .../ide-completion/src/completions/record.rs | 18 +- .../ide-completion/src/completions/snippet.rs | 4 +- crates/ide-completion/src/completions/use_.rs | 4 +- crates/ide-completion/src/context.rs | 9 +- crates/ide-completion/src/context/analysis.rs | 31 +- crates/ide-completion/src/item.rs | 16 +- crates/ide-completion/src/render.rs | 17 +- crates/ide-completion/src/render/function.rs | 13 +- crates/ide-completion/src/render/literal.rs | 10 +- crates/ide-completion/src/render/macro_.rs | 4 +- crates/ide-completion/src/tests/use_tree.rs | 27 + crates/ide-db/src/active_parameter.rs | 24 +- crates/ide-db/src/apply_change.rs | 10 +- crates/ide-db/src/defs.rs | 24 +- crates/ide-db/src/generated/lints.rs | 1683 ++++++++------- crates/ide-db/src/imports/import_assets.rs | 2 +- crates/ide-db/src/imports/insert_use.rs | 112 +- crates/ide-db/src/imports/insert_use/tests.rs | 248 ++- crates/ide-db/src/imports/merge_imports.rs | 340 ++- crates/ide-db/src/lib.rs | 16 +- crates/ide-db/src/path_transform.rs | 2 +- crates/ide-db/src/rename.rs | 9 +- crates/ide-db/src/search.rs | 6 +- crates/ide-db/src/symbol_index.rs | 14 +- .../src/handlers/break_outside_of_loop.rs | 2 +- .../src/handlers/expected_function.rs | 2 +- .../src/handlers/inactive_code.rs | 2 +- .../src/handlers/incoherent_impl.rs | 4 +- .../src/handlers/incorrect_case.rs | 4 +- .../src/handlers/invalid_derive_target.rs | 2 +- .../src/handlers/macro_error.rs | 2 +- .../src/handlers/malformed_derive.rs | 2 +- .../src/handlers/mismatched_arg_count.rs | 4 +- .../src/handlers/missing_fields.rs | 9 +- .../src/handlers/missing_match_arms.rs | 2 +- .../src/handlers/missing_unsafe.rs | 2 +- .../src/handlers/moved_out_of_ref.rs | 2 +- .../src/handlers/mutability_errors.rs | 2 +- .../src/handlers/no_such_field.rs | 2 +- .../src/handlers/private_assoc_item.rs | 2 +- .../src/handlers/private_field.rs | 2 +- .../replace_filter_map_next_with_find_map.rs | 2 +- .../src/handlers/trait_impl_orphan.rs | 5 +- .../trait_impl_redundant_assoc_item.rs | 11 +- .../src/handlers/type_mismatch.rs | 8 +- .../src/handlers/typed_hole.rs | 2 +- .../src/handlers/undeclared_label.rs | 2 +- .../handlers/unimplemented_builtin_macro.rs | 2 +- .../src/handlers/unreachable_label.rs | 2 +- .../src/handlers/unresolved_assoc_item.rs | 2 +- .../src/handlers/unresolved_extern_crate.rs | 2 +- .../src/handlers/unresolved_import.rs | 2 +- .../src/handlers/unresolved_module.rs | 2 +- crates/ide-diagnostics/src/lib.rs | 8 +- crates/ide-ssr/src/fragments.rs | 4 +- crates/ide-ssr/src/matching.rs | 10 +- crates/ide-ssr/src/search.rs | 2 +- crates/ide/src/annotations/fn_references.rs | 2 +- crates/ide/src/doc_links.rs | 28 +- crates/ide/src/doc_links/tests.rs | 50 +- crates/ide/src/fetch_crates.rs | 2 +- crates/ide/src/folding_ranges.rs | 12 +- crates/ide/src/highlight_related.rs | 12 +- crates/ide/src/hover.rs | 152 +- crates/ide/src/hover/render.rs | 151 +- crates/ide/src/hover/tests.rs | 1883 +++++++++++------ crates/ide/src/inlay_hints.rs | 2 +- crates/ide/src/inlay_hints/discriminant.rs | 2 +- crates/ide/src/inlay_hints/fn_lifetime_fn.rs | 24 +- crates/ide/src/inlay_hints/implicit_drop.rs | 5 +- crates/ide/src/inlay_hints/param_name.rs | 2 +- crates/ide/src/interpret_function.rs | 2 +- crates/ide/src/lib.rs | 11 +- crates/ide/src/markup.rs | 3 + crates/ide/src/moniker.rs | 6 +- crates/ide/src/navigation_target.rs | 6 +- crates/ide/src/references.rs | 19 +- crates/ide/src/rename.rs | 70 +- crates/ide/src/runnables.rs | 4 +- crates/ide/src/signature_help.rs | 12 +- crates/ide/src/syntax_highlighting.rs | 7 +- crates/ide/src/syntax_tree.rs | 2 - crates/ide/src/typing.rs | 21 +- crates/ide/src/view_crate_graph.rs | 2 +- crates/ide/src/view_memory_layout.rs | 4 +- crates/load-cargo/src/lib.rs | 6 +- crates/mbe/src/expander/transcriber.rs | 20 +- crates/mbe/src/lib.rs | 2 +- crates/mbe/src/syntax_bridge.rs | 4 +- crates/parser/src/grammar/items.rs | 43 +- crates/parser/src/grammar/items/use_item.rs | 28 +- .../src/tests/sourcegen_inline_tests.rs | 2 +- .../parser/err/0036_partial_use.rast | 45 +- .../err/0026_macro_rules_as_macro_name.rast | 39 + .../err/0026_macro_rules_as_macro_name.rs | 3 + .../err/0026_use_tree_list_err_recovery.rast | 46 + .../err/0026_use_tree_list_err_recovery.rs | 4 + .../ok/0208_macro_rules_as_macro_name.rast | 72 + .../ok/0208_macro_rules_as_macro_name.rs | 6 + crates/project-model/src/build_scripts.rs | 19 +- crates/project-model/src/cargo_workspace.rs | 6 +- crates/project-model/src/manifest_path.rs | 2 +- crates/project-model/src/sysroot.rs | 272 ++- crates/project-model/src/tests.rs | 65 +- crates/project-model/src/workspace.rs | 340 +-- ...rust_project_hello_world_project_model.txt | 2 +- crates/rust-analyzer/Cargo.toml | 1 + crates/rust-analyzer/src/bin/main.rs | 2 +- .../rust-analyzer/src/cli/analysis_stats.rs | 3 +- crates/rust-analyzer/src/cli/diagnostics.rs | 2 +- crates/rust-analyzer/src/cli/flags.rs | 4 + crates/rust-analyzer/src/cli/lsif.rs | 5 +- .../rust-analyzer/src/cli/progress_report.rs | 2 +- crates/rust-analyzer/src/cli/rustc_tests.rs | 61 +- crates/rust-analyzer/src/cli/scip.rs | 4 +- crates/rust-analyzer/src/config.rs | 38 +- crates/rust-analyzer/src/diagnostics.rs | 2 +- crates/rust-analyzer/src/global_state.rs | 4 +- .../src/handlers/notification.rs | 2 +- crates/rust-analyzer/src/handlers/request.rs | 43 +- crates/rust-analyzer/src/line_index.rs | 5 +- crates/rust-analyzer/src/lsp/from_proto.rs | 2 +- .../rust-analyzer/src/lsp/semantic_tokens.rs | 2 +- crates/rust-analyzer/src/lsp/to_proto.rs | 36 +- crates/rust-analyzer/src/main_loop.rs | 41 +- crates/rust-analyzer/src/reload.rs | 82 +- crates/rust-analyzer/tests/slow-tests/main.rs | 47 +- .../rust-analyzer/tests/slow-tests/support.rs | 16 +- .../rust-analyzer/tests/slow-tests/testdir.rs | 37 +- crates/rust-analyzer/tests/slow-tests/tidy.rs | 2 +- crates/span/src/lib.rs | 19 +- crates/span/src/map.rs | 2 +- crates/stdx/src/lib.rs | 4 + crates/syntax/src/algo.rs | 4 +- crates/syntax/src/ast/edit_in_place.rs | 21 +- crates/syntax/src/ast/make.rs | 3 + crates/syntax/src/ast/node_ext.rs | 28 +- crates/syntax/src/ast/token_ext.rs | 90 +- crates/syntax/src/lib.rs | 2 +- crates/syntax/src/ptr.rs | 4 +- crates/test-fixture/src/lib.rs | 2 +- crates/test-utils/src/minicore.rs | 24 +- crates/vfs-notify/src/lib.rs | 24 +- crates/vfs/src/loader.rs | 14 +- docs/user/generated_config.adoc | 15 + docs/user/manual.adoc | 3 +- editors/code/package.json | 16 +- lib/la-arena/src/map.rs | 2 + lib/line-index/src/lib.rs | 113 +- lib/lsp-server/src/lib.rs | 18 +- xtask/src/metrics.rs | 8 +- 315 files changed, 7171 insertions(+), 4498 deletions(-) create mode 100644 crates/parser/test_data/parser/inline/err/0026_macro_rules_as_macro_name.rast create mode 100644 crates/parser/test_data/parser/inline/err/0026_macro_rules_as_macro_name.rs create mode 100644 crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rast create mode 100644 crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rs create mode 100644 crates/parser/test_data/parser/inline/ok/0208_macro_rules_as_macro_name.rast create mode 100644 crates/parser/test_data/parser/inline/ok/0208_macro_rules_as_macro_name.rs diff --git a/.editorconfig b/.editorconfig index f00ade5fd8266..e337066f7eaca 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,6 +8,7 @@ end_of_line = lf insert_final_newline = true indent_style = space indent_size = 4 +max_line_length = 100 [*.md] indent_size = 2 diff --git a/Cargo.lock b/Cargo.lock index 15d06222eb42d..a743d1c870a5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -160,9 +160,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chalk-derive" -version = "0.95.0" +version = "0.96.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "329427f28cd2bddaacd47c4dcd3d7082d315c61fb164394c690fe98c1b6ee9d3" +checksum = "5676cea088c32290fe65c82895be9d06dd21e0fa49bb97ca840529e9417ab71a" dependencies = [ "proc-macro2", "quote", @@ -172,9 +172,9 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.95.0" +version = "0.96.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1e1659238bd598d0f7dbc5034cf1ff46010a3d6827704c9ed443c8359cb484" +checksum = "ff550c2cdd63ff74394214dce03d06386928a641c0f08837535f04af573a966d" dependencies = [ "bitflags 2.4.1", "chalk-derive", @@ -183,9 +183,9 @@ dependencies = [ [[package]] name = "chalk-recursive" -version = "0.95.0" +version = "0.96.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e0bff0ba1bed11407384fcec0353aeb6888901e63cb47d04505ec47adad847" +checksum = "4c4559e5c9b200240453b07d893f9c3c74413b53b0d33cbe272c68b0b77aa1c3" dependencies = [ "chalk-derive", "chalk-ir", @@ -196,9 +196,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.95.0" +version = "0.96.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9c46d501cf83732a91056c0c846ae7a16d6b3c67a6a6bb5e9cc0a2e91563b6" +checksum = "0882e68ce9eb5a0a2413806538494d19df6ee520ab17d1faf489e952f32e98b8" dependencies = [ "chalk-derive", "chalk-ir", @@ -1001,9 +1001,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" @@ -1532,6 +1532,7 @@ dependencies = [ "lsp-server 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-types", "mbe", + "memchr", "mimalloc", "nohash-hasher", "num_cpus", @@ -1712,9 +1713,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smol_str" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49" dependencies = [ "serde", ] diff --git a/Cargo.toml b/Cargo.toml index 35bef151196f0..2547f1ccb9915 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,7 +105,7 @@ dissimilar = "1.0.7" either = "1.9.0" expect-test = "1.4.0" hashbrown = { version = "0.14", features = [ - "inline-more", + "inline-more", ], default-features = false } indexmap = "2.1.0" itertools = "0.12.0" @@ -118,11 +118,11 @@ semver = "1.0.14" serde = { version = "1.0.192", features = ["derive"] } serde_json = "1.0.108" smallvec = { version = "1.10.0", features = [ - "const_new", - "union", - "const_generics", + "const_new", + "union", + "const_generics", ] } -smol_str = "0.2.0" +smol_str = "0.2.1" text-size = "1.1.1" tracing = "0.1.40" tracing-tree = "0.3.0" @@ -138,8 +138,63 @@ xshell = "0.2.5" # 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"] } +[workspace.lints.rust] +rust_2018_idioms = "warn" +unused_lifetimes = "warn" +semicolon_in_expressions_from_macros = "warn" + [workspace.lints.clippy] -collapsible_if = "allow" -needless_pass_by_value = "allow" -nonminimal_bool = "allow" -redundant_pattern_matching = "allow" +# FIXME Remove the tidy test once the lint table is stable + +## lint groups +complexity = { level = "warn", priority = -1 } +correctness = { level = "deny", priority = -1 } +perf = { level = "deny", priority = -1 } +restriction = { level = "allow", priority = -1 } +style = { level = "warn", priority = -1 } +suspicious = { level = "warn", priority = -1 } + +## allow following lints +# () makes a fine error in most cases +result_unit_err = "allow" +# We don't expose public APIs that matter like this +len_without_is_empty = "allow" +# We have macros that rely on this currently +enum_variant_names = "allow" +# Builder pattern disagrees +new_ret_no_self = "allow" + +## Following lints should be tackled at some point +borrowed_box = "allow" +borrow_deref_ref = "allow" +derivable_impls = "allow" +derived_hash_with_manual_eq = "allow" +field_reassign_with_default = "allow" +forget_non_drop = "allow" +format_collect = "allow" +large_enum_variant = "allow" +needless_doctest_main = "allow" +new_without_default = "allow" +non_canonical_clone_impl = "allow" +non_canonical_partial_ord_impl = "allow" +self_named_constructors = "allow" +skip_while_next = "allow" +too_many_arguments = "allow" +toplevel_ref_arg = "allow" +type_complexity = "allow" +unnecessary_cast = "allow" +unnecessary_filter_map = "allow" +unnecessary_lazy_evaluations = "allow" +unnecessary_mut_passed = "allow" +useless_conversion = "allow" +useless_format = "allow" +wildcard_in_or_patterns = "allow" +wrong_self_convention = "allow" + +## warn at following lints +dbg_macro = "warn" +todo = "warn" +unimplemented = "allow" +rc_buffer = "warn" +# FIXME enable this, we use this pattern a lot so its annoying work ... +# str_to_string = "warn" diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index e45a81238ac9b..852f36ea712a6 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -9,7 +9,7 @@ use std::{fmt, mem, ops, str::FromStr}; use cfg::CfgOptions; -use la_arena::{Arena, Idx}; +use la_arena::{Arena, Idx, RawIdx}; use rustc_hash::{FxHashMap, FxHashSet}; use semver::Version; use syntax::SmolStr; @@ -157,6 +157,10 @@ impl CrateOrigin { pub fn is_lib(&self) -> bool { matches!(self, CrateOrigin::Library { .. }) } + + pub fn is_lang(&self) -> bool { + matches!(self, CrateOrigin::Lang { .. }) + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -174,7 +178,7 @@ impl From<&str> for LangCrateOrigin { match s { "alloc" => LangCrateOrigin::Alloc, "core" => LangCrateOrigin::Core, - "proc-macro" => LangCrateOrigin::ProcMacro, + "proc-macro" | "proc_macro" => LangCrateOrigin::ProcMacro, "std" => LangCrateOrigin::Std, "test" => LangCrateOrigin::Test, _ => LangCrateOrigin::Other, @@ -257,6 +261,7 @@ impl ReleaseChannel { } } + #[allow(clippy::should_implement_trait)] pub fn from_str(str: &str) -> Option { Some(match str { "" | "stable" => ReleaseChannel::Stable, @@ -326,7 +331,7 @@ impl CrateData { return false; } - if let Some(_) = opts.next() { + if opts.next().is_some() { return false; } } @@ -522,7 +527,7 @@ impl CrateGraph { self.arena.iter().map(|(idx, _)| idx) } - // FIXME: used for `handle_hack_cargo_workspace`, should be removed later + // FIXME: used for fixing up the toolchain sysroot, should be removed and done differently #[doc(hidden)] pub fn iter_mut(&mut self) -> impl Iterator + '_ { self.arena.iter_mut() @@ -619,7 +624,12 @@ impl CrateGraph { /// This will deduplicate the crates of the graph where possible. /// Note that for deduplication to fully work, `self`'s crate dependencies must be sorted by crate id. /// If the crate dependencies were sorted, the resulting graph from this `extend` call will also have the crate dependencies sorted. - pub fn extend(&mut self, mut other: CrateGraph, proc_macros: &mut ProcMacroPaths) { + pub fn extend( + &mut self, + mut other: CrateGraph, + proc_macros: &mut ProcMacroPaths, + on_finished: impl FnOnce(&FxHashMap), + ) { let topo = other.crates_in_topological_order(); let mut id_map: FxHashMap = FxHashMap::default(); for topo in topo { @@ -630,7 +640,7 @@ impl CrateGraph { let res = self.arena.iter().find_map(|(id, data)| { match (&data.origin, &crate_data.origin) { (a, b) if a == b => { - if data.eq_ignoring_origin_and_deps(&crate_data, false) { + if data.eq_ignoring_origin_and_deps(crate_data, false) { return Some((id, false)); } } @@ -642,8 +652,8 @@ impl CrateGraph { // version and discard the library one as the local version may have // dev-dependencies that we want to keep resolving. See #15656 for more // information. - if data.eq_ignoring_origin_and_deps(&crate_data, true) { - return Some((id, if a.is_local() { false } else { true })); + if data.eq_ignoring_origin_and_deps(crate_data, true) { + return Some((id, !a.is_local())); } } (_, _) => return None, @@ -670,6 +680,8 @@ impl CrateGraph { *proc_macros = mem::take(proc_macros).into_iter().map(|(id, macros)| (id_map[&id], macros)).collect(); + + on_finished(&id_map); } fn find_path( @@ -721,6 +733,29 @@ impl CrateGraph { fn hacky_find_crate<'a>(&'a self, display_name: &'a str) -> impl Iterator + 'a { self.iter().filter(move |it| self[*it].display_name.as_deref() == Some(display_name)) } + + /// 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> { + let mut id_map = vec![None; self.arena.len()]; + self.arena = std::mem::take(&mut self.arena) + .into_iter() + .filter_map(|(id, data)| if to_keep.contains(&id) { Some((id, data)) } else { None }) + .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))); + data + }) + .collect(); + for (_, data) in self.arena.iter_mut() { + data.dependencies.iter_mut().for_each(|dep| { + dep.crate_id = + id_map[dep.crate_id.into_raw().into_u32() as usize].expect("crate was filtered") + }); + } + id_map + } } impl ops::Index for CrateGraph { diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 30452e34aac36..8fbfcc81d2800 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -24,12 +24,12 @@ use triomphe::Arc; use crate::{ db::DefDatabase, - item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode}, + item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeModItemNode}, lang_item::LangItem, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource}, - AdtId, AssocItemLoc, AttrDefId, EnumId, GenericParamId, ItemLoc, LocalEnumVariantId, - LocalFieldId, Lookup, MacroId, VariantId, + AdtId, AssocItemLoc, AttrDefId, GenericParamId, ItemLoc, LocalFieldId, Lookup, MacroId, + VariantId, }; #[derive(Default, Debug, Clone, PartialEq, Eq)] @@ -70,33 +70,6 @@ impl ops::Deref for AttrsWithOwner { impl Attrs { pub const EMPTY: Self = Self(RawAttrs::EMPTY); - pub(crate) fn variants_attrs_query( - db: &dyn DefDatabase, - e: EnumId, - ) -> Arc> { - let _p = profile::span("variants_attrs_query"); - // FIXME: There should be some proper form of mapping between item tree enum variant ids and hir enum variant ids - let mut res = ArenaMap::default(); - - let loc = e.lookup(db); - let krate = loc.container.krate; - let item_tree = loc.id.item_tree(db); - let enum_ = &item_tree[loc.id.value]; - let crate_graph = db.crate_graph(); - let cfg_options = &crate_graph[krate].cfg_options; - - let mut idx = 0; - for variant in enum_.variants.clone() { - let attrs = item_tree.attrs(db, krate, variant.into()); - if attrs.is_cfg_enabled(cfg_options) { - res.insert(Idx::from_raw(RawIdx::from(idx)), attrs); - idx += 1; - } - } - - Arc::new(res) - } - pub(crate) fn fields_attrs_query( db: &dyn DefDatabase, v: VariantId, @@ -108,29 +81,11 @@ impl Attrs { let crate_graph = db.crate_graph(); let (fields, item_tree, krate) = match v { VariantId::EnumVariantId(it) => { - let e = it.parent; - let loc = e.lookup(db); - let krate = loc.container.krate; + let loc = it.lookup(db); + let krate = loc.parent.lookup(db).container.krate; let item_tree = loc.id.item_tree(db); - let enum_ = &item_tree[loc.id.value]; - - let cfg_options = &crate_graph[krate].cfg_options; - - let Some(variant) = enum_ - .variants - .clone() - .filter(|variant| { - let attrs = item_tree.attrs(db, krate, (*variant).into()); - attrs.is_cfg_enabled(cfg_options) - }) - .zip(0u32..) - .find(|(_variant, idx)| it.local_id == Idx::from_raw(RawIdx::from(*idx))) - .map(|(variant, _idx)| variant) - else { - return Arc::new(res); - }; - - (item_tree[variant].fields.clone(), item_tree, krate) + let variant = &item_tree[loc.id.value]; + (variant.fields.clone(), item_tree, krate) } VariantId::StructId(it) => { let loc = it.lookup(db); @@ -401,10 +356,12 @@ impl AttrsWithOwner { AttrDefId::FieldId(it) => { return db.fields_attrs(it.parent)[it.local_id].clone(); } + // FIXME: DRY this up AttrDefId::EnumVariantId(it) => { - return db.variants_attrs(it.parent)[it.local_id].clone(); + let id = it.lookup(db).id; + let tree = id.item_tree(db); + tree.raw_attrs(id.value.into()).clone() } - // FIXME: DRY this up AttrDefId::AdtId(it) => match it { AdtId::StructId(it) => attrs_from_item_tree_loc(db, it), AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it), @@ -503,12 +460,7 @@ impl AttrsWithOwner { AdtId::EnumId(id) => any_has_attrs(db, id), }, AttrDefId::FunctionId(id) => any_has_attrs(db, id), - AttrDefId::EnumVariantId(id) => { - let map = db.variants_attrs_source_map(id.parent); - let file_id = id.parent.lookup(db).id.file_id(); - let root = db.parse_or_expand(file_id); - InFile::new(file_id, ast::AnyHasAttrs::new(map[id.local_id].to_node(&root))) - } + AttrDefId::EnumVariantId(id) => any_has_attrs(db, id), AttrDefId::StaticId(id) => any_has_attrs(db, id), AttrDefId::ConstId(id) => any_has_attrs(db, id), AttrDefId::TraitId(id) => any_has_attrs(db, id), @@ -654,13 +606,16 @@ fn any_has_attrs<'db>( id.lookup(db).source(db).map(ast::AnyHasAttrs::new) } -fn attrs_from_item_tree(db: &dyn DefDatabase, id: ItemTreeId) -> RawAttrs { +fn attrs_from_item_tree( + db: &dyn DefDatabase, + id: ItemTreeId, +) -> RawAttrs { let tree = id.item_tree(db); let mod_item = N::id_to_mod_item(id.value); tree.raw_attrs(mod_item.into()).clone() } -fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( +fn attrs_from_item_tree_loc<'db, N: ItemTreeModItemNode>( db: &(dyn DefDatabase + 'db), lookup: impl Lookup = dyn DefDatabase + 'db, Data = ItemLoc>, ) -> RawAttrs { @@ -668,7 +623,7 @@ fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( attrs_from_item_tree(db, id) } -fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>( +fn attrs_from_item_tree_assoc<'db, N: ItemTreeModItemNode>( db: &(dyn DefDatabase + 'db), lookup: impl Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, ) -> RawAttrs { @@ -676,20 +631,6 @@ fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>( attrs_from_item_tree(db, id) } -pub(crate) fn variants_attrs_source_map( - db: &dyn DefDatabase, - def: EnumId, -) -> Arc>> { - let mut res = ArenaMap::default(); - let child_source = def.child_source(db); - - for (idx, variant) in child_source.value.iter() { - res.insert(idx, AstPtr::new(variant)); - } - - Arc::new(res) -} - pub(crate) fn fields_attrs_source_map( db: &dyn DefDatabase, def: VariantId, diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index db28c6731ece1..81132d738539f 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -26,7 +26,7 @@ use crate::{ }, nameres::DefMap, path::{ModPath, Path}, - src::{HasChildSource, HasSource}, + src::HasSource, BlockId, DefWithBodyId, HasModule, Lookup, }; @@ -37,7 +37,7 @@ pub struct Body { pub pats: Arena, pub bindings: Arena, pub labels: Arena, + T: PartialEq, { #[inline] - fn eq(&self, other: &[A; N]) -> bool { - let b: Result<&[B; N], _> = self.try_into(); + fn eq(&self, other: &[U; N]) -> bool { + let b: Result<&[T; N], _> = self.try_into(); match b { Ok(b) => *b == *other, Err(_) => false, } } #[inline] - fn ne(&self, other: &[A; N]) -> bool { - let b: Result<&[B; N], _> = self.try_into(); + fn ne(&self, other: &[U; N]) -> bool { + let b: Result<&[T; N], _> = self.try_into(); match b { Ok(b) => *b != *other, Err(_) => true, @@ -63,61 +63,61 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<&[B]> for [A; N] +impl PartialEq<&[U]> for [T; N] where - A: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &&[B]) -> bool { + fn eq(&self, other: &&[U]) -> bool { *self == **other } #[inline] - fn ne(&self, other: &&[B]) -> bool { + fn ne(&self, other: &&[U]) -> bool { *self != **other } } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[A; N]> for &[B] +impl PartialEq<[U; N]> for &[T] where - B: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &[A; N]) -> bool { + fn eq(&self, other: &[U; N]) -> bool { **self == *other } #[inline] - fn ne(&self, other: &[A; N]) -> bool { + fn ne(&self, other: &[U; N]) -> bool { **self != *other } } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<&mut [B]> for [A; N] +impl PartialEq<&mut [U]> for [T; N] where - A: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &&mut [B]) -> bool { + fn eq(&self, other: &&mut [U]) -> bool { *self == **other } #[inline] - fn ne(&self, other: &&mut [B]) -> bool { + fn ne(&self, other: &&mut [U]) -> bool { *self != **other } } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[A; N]> for &mut [B] +impl PartialEq<[U; N]> for &mut [T] where - B: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &[A; N]) -> bool { + fn eq(&self, other: &[U; N]) -> bool { **self == *other } #[inline] - fn ne(&self, other: &[A; N]) -> bool { + fn ne(&self, other: &[U; N]) -> bool { **self != *other } } diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 8a8d634c0072a..e8b0010ba1574 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -8,15 +8,15 @@ use super::from_raw_parts; use super::memchr; #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[B]> for [A] +impl PartialEq<[U]> for [T] where - A: PartialEq, + T: PartialEq, { - fn eq(&self, other: &[B]) -> bool { + fn eq(&self, other: &[U]) -> bool { SlicePartialEq::equal(self, other) } - fn ne(&self, other: &[B]) -> bool { + fn ne(&self, other: &[U]) -> bool { SlicePartialEq::not_equal(self, other) } } diff --git a/tests/ui/consts/too_generic_eval_ice.stderr b/tests/ui/consts/too_generic_eval_ice.stderr index 843d6d9e04ba7..4089c850c8021 100644 --- a/tests/ui/consts/too_generic_eval_ice.stderr +++ b/tests/ui/consts/too_generic_eval_ice.stderr @@ -22,13 +22,13 @@ LL | [5; Self::HOST_SIZE] == [6; 0] | = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; Self::HOST_SIZE]` = help: the following other types implement trait `PartialEq`: - <[A; N] as PartialEq<[B; N]>> - <[A; N] as PartialEq<[B]>> - <[A; N] as PartialEq<&[B]>> - <[A; N] as PartialEq<&mut [B]>> + <[T; N] as PartialEq<[U; N]>> + <[T; N] as PartialEq<[U]>> + <[T; N] as PartialEq<&[U]>> + <[T; N] as PartialEq<&mut [U]>> <[T] as PartialEq>> - <[A] as PartialEq<[B]>> - <[B] as PartialEq<[A; N]>> + <[T] as PartialEq<[U; N]>> + <[T] as PartialEq<[U]>> <&[T] as PartialEq>> and 3 others From e320004dade39b99cd1f239c5d1289ea2ebf2c79 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 24 Jan 2024 22:32:46 +0100 Subject: [PATCH 068/246] Remove tt -> ast -> tt round trips in attrs lowering --- crates/cfg/src/cfg_expr.rs | 22 ------ crates/cfg/src/lib.rs | 8 +- crates/hir-def/src/attr.rs | 11 +-- crates/hir-def/src/db.rs | 2 +- crates/hir-expand/src/attrs.rs | 78 ++++++++++---------- crates/hir-expand/src/mod_path.rs | 45 +++++++++++ crates/proc-macro-srv/src/server/token_id.rs | 2 +- 7 files changed, 95 insertions(+), 73 deletions(-) diff --git a/crates/cfg/src/cfg_expr.rs b/crates/cfg/src/cfg_expr.rs index fb7505ba2dd5b..4be6ae7481d8e 100644 --- a/crates/cfg/src/cfg_expr.rs +++ b/crates/cfg/src/cfg_expr.rs @@ -18,28 +18,6 @@ pub enum CfgAtom { KeyValue { key: SmolStr, value: SmolStr }, } -impl CfgAtom { - /// Returns `true` when the atom comes from the target specification. - /// - /// If this returns `true`, then changing this atom requires changing the compilation target. If - /// it returns `false`, the atom might come from a build script or the build system. - pub fn is_target_defined(&self) -> bool { - match self { - CfgAtom::Flag(flag) => matches!(&**flag, "unix" | "windows"), - CfgAtom::KeyValue { key, value: _ } => matches!( - &**key, - "target_arch" - | "target_os" - | "target_env" - | "target_family" - | "target_endian" - | "target_pointer_width" - | "target_vendor" // NOTE: `target_feature` is left out since it can be configured via `-Ctarget-feature` - ), - } - } -} - impl fmt::Display for CfgAtom { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs index 6b178e7b04a76..3b41de14335ac 100644 --- a/crates/cfg/src/lib.rs +++ b/crates/cfg/src/lib.rs @@ -131,11 +131,9 @@ impl CfgDiff { /// of both. pub fn new(enable: Vec, disable: Vec) -> Option { let mut occupied = FxHashSet::default(); - for item in enable.iter().chain(disable.iter()) { - if !occupied.insert(item) { - // was present - return None; - } + if enable.iter().chain(disable.iter()).any(|item| occupied.insert(item)) { + // was present + return None; } Some(CfgDiff { enable, disable }) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 8fbfcc81d2800..a8e081705e324 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -32,6 +32,7 @@ use crate::{ VariantId, }; +/// Desugared attributes of an item post `cfg_attr` expansion. #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct Attrs(RawAttrs); @@ -228,7 +229,6 @@ pub enum DocAtom { KeyValue { key: SmolStr, value: SmolStr }, } -// Adapted from `CfgExpr` parsing code #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum DocExpr { Invalid, @@ -448,10 +448,7 @@ impl AttrsWithOwner { let map = db.fields_attrs_source_map(id.parent); let file_id = id.parent.file_id(db); let root = db.parse_or_expand(file_id); - let owner = match &map[id.local_id] { - Either::Left(it) => ast::AnyHasAttrs::new(it.to_node(&root)), - Either::Right(it) => ast::AnyHasAttrs::new(it.to_node(&root)), - }; + let owner = ast::AnyHasAttrs::new(map[id.local_id].to_node(&root)); InFile::new(file_id, owner) } AttrDefId::AdtId(adt) => match adt { @@ -634,7 +631,7 @@ fn attrs_from_item_tree_assoc<'db, N: ItemTreeModItemNode>( pub(crate) fn fields_attrs_source_map( db: &dyn DefDatabase, def: VariantId, -) -> Arc, AstPtr>>> { +) -> Arc>>> { let mut res = ArenaMap::default(); let child_source = def.child_source(db); @@ -643,7 +640,7 @@ pub(crate) fn fields_attrs_source_map( idx, variant .as_ref() - .either(|l| Either::Left(AstPtr::new(l)), |r| Either::Right(AstPtr::new(r))), + .either(|l| AstPtr::new(l).wrap_left(), |r| AstPtr::new(r).wrap_right()), ); } diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index c9789ceb207c5..708abb5369377 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -194,7 +194,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Arc, AstPtr>>>; + ) -> Arc>>>; #[salsa::invoke(AttrsWithOwner::attrs_query)] fn attrs(&self, def: AttrDefId) -> Attrs; diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs index 67a318afd062c..b7c50fd82aa2e 100644 --- a/crates/hir-expand/src/attrs.rs +++ b/crates/hir-expand/src/attrs.rs @@ -117,14 +117,10 @@ impl RawAttrs { None => return smallvec![attr.clone()], }; let index = attr.id; - let attrs = - parts.enumerate().take(1 << AttrId::CFG_ATTR_BITS).filter_map(|(idx, attr)| { - let tree = Subtree { - delimiter: tt::Delimiter::invisible_spanned(attr.first()?.first_span()), - token_trees: attr.to_vec(), - }; - Attr::from_tt(db, &tree, index.with_cfg_attr(idx)) - }); + let attrs = parts + .enumerate() + .take(1 << AttrId::CFG_ATTR_BITS) + .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx))); let cfg_options = &crate_graph[krate].cfg_options; let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() }; @@ -222,12 +218,41 @@ impl Attr { Some(Attr { id, path, input, span }) } - fn from_tt(db: &dyn ExpandDatabase, tt: &tt::Subtree, id: AttrId) -> Option { - // FIXME: Unecessary roundtrip tt -> ast -> tt - let (parse, map) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MetaItem); - let ast = ast::Meta::cast(parse.syntax_node())?; - - Self::from_src(db, ast, SpanMapRef::ExpansionSpanMap(&map), id) + fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree], id: AttrId) -> Option { + dbg!(tt); + let span = tt.first()?.first_span(); + let path_end = tt + .iter() + .position(|tt| { + !matches!( + tt, + tt::TokenTree::Leaf( + tt::Leaf::Punct(tt::Punct { char: ':' | '$', .. }) | tt::Leaf::Ident(_), + ) + ) + }) + .unwrap_or_else(|| tt.len()); + + let (path, input) = tt.split_at(path_end); + let path = Interned::new(ModPath::from_tt(db, path)?); + + let input = match input.get(0) { + Some(tt::TokenTree::Subtree(tree)) => { + Some(Interned::new(AttrInput::TokenTree(Box::new(tree.clone())))) + } + Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. }))) => { + let input = match input.get(1) { + Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { text, .. }))) => { + //FIXME the trimming here isn't quite right, raw strings are not handled + Some(Interned::new(AttrInput::Literal(text.trim_matches('"').into()))) + } + _ => None, + }; + input + } + _ => None, + }; + Some(Attr { id, path, input, span }) } pub fn path(&self) -> &ModPath { @@ -277,29 +302,8 @@ impl Attr { .token_trees .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. })))) .filter_map(move |tts| { - if tts.is_empty() { - return None; - } - // FIXME: This is necessarily a hack. It'd be nice if we could avoid allocation - // here or maybe just parse a mod path from a token tree directly - let subtree = tt::Subtree { - delimiter: tt::Delimiter::invisible_spanned(tts.first()?.first_span()), - token_trees: tts.to_vec(), - }; - let (parse, span_map) = - mbe::token_tree_to_syntax_node(&subtree, mbe::TopEntryPoint::MetaItem); - let meta = ast::Meta::cast(parse.syntax_node())?; - // Only simple paths are allowed. - if meta.eq_token().is_some() || meta.expr().is_some() || meta.token_tree().is_some() - { - return None; - } - let path = meta.path()?; - let call_site = span_map.span_at(path.syntax().text_range().start()); - Some(( - ModPath::from_src(db, path, SpanMapRef::ExpansionSpanMap(&span_map))?, - call_site, - )) + let span = tts.first()?.first_span(); + Some((ModPath::from_tt(db, tts)?, span)) }); Some(paths) diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 47a587e407c52..9b72e03410371 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -10,6 +10,7 @@ use crate::{ hygiene::{marks_rev, SyntaxContextExt, Transparency}, name::{known, AsName, Name}, span_map::SpanMapRef, + tt, }; use base_db::CrateId; use smallvec::SmallVec; @@ -53,6 +54,10 @@ impl ModPath { convert_path(db, None, path, span_map) } + pub fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option { + convert_path_tt(db, tt) + } + pub fn from_segments(kind: PathKind, segments: impl IntoIterator) -> ModPath { let segments = segments.into_iter().collect(); ModPath { kind, segments } @@ -281,6 +286,46 @@ fn convert_path( Some(mod_path) } +fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option { + let mut leafs = tt.iter().filter_map(|tt| match tt { + tt::TokenTree::Leaf(leaf) => Some(leaf), + tt::TokenTree::Subtree(_) => None, + }); + let mut segments = smallvec::smallvec![]; + let kind = match leafs.next()? { + tt::Leaf::Punct(tt::Punct { char: ':', .. }) => match leafs.next()? { + tt::Leaf::Punct(tt::Punct { char: ':', .. }) => PathKind::Abs, + _ => return None, + }, + tt::Leaf::Ident(tt::Ident { text, span }) if text == "$crate" => { + resolve_crate_root(db, span.ctx).map(PathKind::DollarCrate).unwrap_or(PathKind::Crate) + } + tt::Leaf::Ident(tt::Ident { text, .. }) if text == "self" => PathKind::Super(0), + tt::Leaf::Ident(tt::Ident { text, .. }) if text == "super" => { + let mut deg = 1; + while let Some(tt::Leaf::Ident(tt::Ident { text, .. })) = leafs.next() { + if text != "super" { + segments.push(Name::new_text_dont_use(text.clone())); + break; + } + deg += 1; + } + PathKind::Super(deg) + } + tt::Leaf::Ident(tt::Ident { text, .. }) if text == "crate" => PathKind::Crate, + tt::Leaf::Ident(ident) => { + segments.push(Name::new_text_dont_use(ident.text.clone())); + PathKind::Plain + } + _ => return None, + }; + segments.extend(leafs.filter_map(|leaf| match leaf { + ::tt::Leaf::Ident(ident) => Some(Name::new_text_dont_use(ident.text.clone())), + _ => None, + })); + Some(ModPath { kind, segments }) +} + 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` diff --git a/crates/proc-macro-srv/src/server/token_id.rs b/crates/proc-macro-srv/src/server/token_id.rs index 12526ad4f3ae6..f3da01cb104b2 100644 --- a/crates/proc-macro-srv/src/server/token_id.rs +++ b/crates/proc-macro-srv/src/server/token_id.rs @@ -206,7 +206,7 @@ impl server::TokenStream for TokenIdServer { stream: if subtree.token_trees.is_empty() { None } else { - Some(subtree.token_trees.into_iter().collect()) + Some(subtree.token_trees) }, span: bridge::DelimSpan::from_single(subtree.delimiter.open), }), From 880baa9e568c5aff70a49f02e517fce075e40b3f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 25 Jan 2024 10:07:29 +0100 Subject: [PATCH 069/246] Shuffle hir-expand things around --- crates/hir-expand/src/ast_id_map.rs | 9 +- crates/hir-expand/src/db.rs | 275 +++------------------------ crates/hir-expand/src/declarative.rs | 176 +++++++++++++++++ crates/hir-expand/src/hygiene.rs | 40 ++++ crates/hir-expand/src/lib.rs | 9 +- crates/hir-expand/src/mod_path.rs | 5 +- crates/hir-expand/src/span_map.rs | 37 +++- rustfmt.toml | 2 +- 8 files changed, 295 insertions(+), 258 deletions(-) create mode 100644 crates/hir-expand/src/declarative.rs diff --git a/crates/hir-expand/src/ast_id_map.rs b/crates/hir-expand/src/ast_id_map.rs index 7bdd6db9321cb..530f10a06847e 100644 --- a/crates/hir-expand/src/ast_id_map.rs +++ b/crates/hir-expand/src/ast_id_map.rs @@ -155,7 +155,14 @@ impl PartialEq for AstIdMap { impl Eq for AstIdMap {} impl AstIdMap { - pub(crate) fn from_source(node: &SyntaxNode) -> AstIdMap { + pub(crate) fn ast_id_map( + db: &dyn ExpandDatabase, + file_id: span::HirFileId, + ) -> triomphe::Arc { + triomphe::Arc::new(AstIdMap::from_source(&db.parse_or_expand(file_id))) + } + + fn from_source(node: &SyntaxNode) -> AstIdMap { assert!(node.parent().is_none()); let mut res = AstIdMap::default(); diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 2f8c0951b1439..08542c6430af4 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -1,16 +1,14 @@ //! Defines database & queries for macro expansion. -use std::sync::OnceLock; - use base_db::{ salsa::{self, debug::DebugQueryTable}, - CrateId, Edition, FileId, SourceDatabase, VersionReq, + CrateId, FileId, SourceDatabase, }; use either::Either; use limit::Limit; use mbe::{syntax_node_to_token_tree, ValueResult}; use rustc_hash::FxHashSet; -use span::{Span, SyntaxContextId}; +use span::SyntaxContextId; use syntax::{ ast::{self, HasAttrs}, AstNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T, @@ -19,13 +17,14 @@ use triomphe::Arc; use crate::{ ast_id_map::AstIdMap, - attrs::{collect_attrs, RawAttrs}, + attrs::collect_attrs, builtin_attr_macro::pseudo_derive_attr_expansion, builtin_fn_macro::EagerExpander, + declarative::DeclarativeMacroExpander, fixup::{self, reverse_fixups, SyntaxFixupUndoInfo}, hygiene::{ - apply_mark, span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt, - SyntaxContextData, Transparency, + span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt, + SyntaxContextData, }, proc_macro::ProcMacros, span_map::{RealSpanMap, SpanMap, SpanMapRef}, @@ -43,82 +42,6 @@ use crate::{ /// Actual max for `analysis-stats .` at some point: 30672. static TOKEN_LIMIT: Limit = Limit::new(1_048_576); -#[derive(Debug, Clone, Eq, PartialEq)] -/// Old-style `macro_rules` or the new macros 2.0 -pub struct DeclarativeMacroExpander { - pub mac: mbe::DeclarativeMacro, - pub transparency: Transparency, -} - -// FIXME: Remove this once we drop support for 1.76 -static REQUIREMENT: OnceLock = OnceLock::new(); - -impl DeclarativeMacroExpander { - pub fn expand( - &self, - db: &dyn ExpandDatabase, - tt: tt::Subtree, - call_id: MacroCallId, - ) -> ExpandResult { - let loc = db.lookup_intern_macro_call(call_id); - let toolchain = &db.crate_graph()[loc.def.krate].toolchain; - let new_meta_vars = toolchain.as_ref().map_or(false, |version| { - REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( - &base_db::Version { - pre: base_db::Prerelease::EMPTY, - build: base_db::BuildMetadata::EMPTY, - major: version.major, - minor: version.minor, - patch: version.patch, - }, - ) - }); - match self.mac.err() { - Some(e) => ExpandResult::new( - tt::Subtree::empty(tt::DelimSpan { open: loc.call_site, close: loc.call_site }), - ExpandError::other(format!("invalid macro definition: {e}")), - ), - None => self - .mac - .expand( - &tt, - |s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency), - new_meta_vars, - loc.call_site, - ) - .map_err(Into::into), - } - } - - pub fn expand_unhygienic( - &self, - db: &dyn ExpandDatabase, - tt: tt::Subtree, - krate: CrateId, - call_site: Span, - ) -> ExpandResult { - let toolchain = &db.crate_graph()[krate].toolchain; - let new_meta_vars = toolchain.as_ref().map_or(false, |version| { - REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( - &base_db::Version { - pre: base_db::Prerelease::EMPTY, - build: base_db::BuildMetadata::EMPTY, - major: version.major, - minor: version.minor, - patch: version.patch, - }, - ) - }); - match self.mac.err() { - Some(e) => ExpandResult::new( - tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }), - ExpandError::other(format!("invalid macro definition: {e}")), - ), - None => self.mac.expand(&tt, |_| (), new_meta_vars, call_site).map_err(Into::into), - } - } -} - #[derive(Debug, Clone, Eq, PartialEq)] pub enum TokenExpander { /// Old-style `macro_rules` or the new macros 2.0 @@ -141,6 +64,7 @@ pub trait ExpandDatabase: SourceDatabase { #[salsa::input] fn proc_macros(&self) -> Arc; + #[salsa::invoke(AstIdMap::ast_id_map)] fn ast_id_map(&self, file_id: HirFileId) -> Arc; /// Main public API -- parses a hir file, not caring whether it's a real @@ -156,8 +80,10 @@ pub trait ExpandDatabase: SourceDatabase { macro_file: MacroFileId, ) -> ExpandResult<(Parse, Arc)>; #[salsa::transparent] + #[salsa::invoke(SpanMap::new)] fn span_map(&self, file_id: HirFileId) -> SpanMap; + #[salsa::invoke(crate::span_map::real_span_map)] fn real_span_map(&self, file_id: FileId) -> Arc; /// Macro ids. That's probably the tricksiest bit in rust-analyzer, and the @@ -173,6 +99,7 @@ pub trait ExpandDatabase: SourceDatabase { #[salsa::transparent] fn setup_syntax_context_root(&self) -> (); #[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 @@ -184,8 +111,10 @@ pub trait ExpandDatabase: SourceDatabase { ) -> ValueResult, SyntaxFixupUndoInfo)>, Arc>>; /// Fetches the expander for this macro. #[salsa::transparent] + #[salsa::invoke(TokenExpander::macro_expander)] fn macro_expander(&self, id: MacroDefId) -> TokenExpander; /// Fetches (and compiles) the expander of this decl macro. + #[salsa::invoke(DeclarativeMacroExpander::expander)] fn decl_macro_expander( &self, def_crate: CrateId, @@ -203,36 +132,6 @@ pub trait ExpandDatabase: SourceDatabase { ) -> ExpandResult>; } -#[inline] -pub fn span_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> SpanMap { - match file_id.repr() { - HirFileIdRepr::FileId(file_id) => SpanMap::RealSpanMap(db.real_span_map(file_id)), - HirFileIdRepr::MacroFile(m) => { - SpanMap::ExpansionSpanMap(db.parse_macro_expansion(m).value.1) - } - } -} - -pub fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> 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 tree = db.parse(file_id).tree(); - // FIXME: Descend into modules and other item containing items that are not annotated with attributes - // and allocate pairs for those as well. This gives us finer grained span anchors resulting in - // better incrementality - pairs.extend( - tree.items() - .map(|item| (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())), - ); - - Arc::new(RealSpanMap::from_file( - file_id, - pairs.into_boxed_slice(), - tree.syntax().text_range().end(), - )) -} - /// This expands the given macro call, but with different arguments. This is /// used for completion, where we want to see what 'would happen' if we insert a /// token. The `token_to_map` mapped down into the expansion, with the mapped @@ -357,10 +256,6 @@ pub fn expand_speculative( Some((node.syntax_node(), token)) } -fn ast_id_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> Arc { - Arc::new(AstIdMap::from_source(&db.parse_or_expand(file_id))) -} - 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(), @@ -412,7 +307,10 @@ fn parse_macro_expansion_error( .map(|it| it.0.errors().to_vec().into_boxed_slice()) } -fn parse_with_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> (Parse, SpanMap) { +pub(crate) fn parse_with_map( + db: &dyn ExpandDatabase, + 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))) @@ -581,100 +479,18 @@ fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet, -) -> Arc { - let crate_data = &db.crate_graph()[def_crate]; - let is_2021 = crate_data.edition >= Edition::Edition2021; - let (root, map) = parse_with_map(db, id.file_id); - let root = root.syntax_node(); - - let transparency = |node| { - // ... would be nice to have the item tree here - let attrs = RawAttrs::new(db, node, map.as_ref()).filter(db, def_crate); - match &*attrs - .iter() - .find(|it| { - it.path.as_ident().and_then(|it| it.as_str()) == Some("rustc_macro_transparency") - })? - .token_tree_value()? - .token_trees - { - [tt::TokenTree::Leaf(tt::Leaf::Ident(i)), ..] => match &*i.text { - "transparent" => Some(Transparency::Transparent), - "semitransparent" => Some(Transparency::SemiTransparent), - "opaque" => Some(Transparency::Opaque), - _ => None, - }, - _ => None, - } - }; - let toolchain = crate_data.toolchain.as_ref(); - let new_meta_vars = toolchain.as_ref().map_or(false, |version| { - REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( - &base_db::Version { - pre: base_db::Prerelease::EMPTY, - build: base_db::BuildMetadata::EMPTY, - major: version.major, - minor: version.minor, - patch: version.patch, - }, - ) - }); - - let (mac, transparency) = match id.to_ptr(db).to_node(&root) { - ast::Macro::MacroRules(macro_rules) => ( - match macro_rules.token_tree() { - Some(arg) => { - let tt = mbe::syntax_node_to_token_tree( - arg.syntax(), - map.as_ref(), - map.span_for_range(macro_rules.macro_rules_token().unwrap().text_range()), - ); - - mbe::DeclarativeMacro::parse_macro_rules(&tt, is_2021, new_meta_vars) - } - None => mbe::DeclarativeMacro::from_err( - mbe::ParseError::Expected("expected a token tree".into()), - is_2021, - ), - }, - transparency(¯o_rules).unwrap_or(Transparency::SemiTransparent), - ), - ast::Macro::MacroDef(macro_def) => ( - match macro_def.body() { - Some(arg) => { - let tt = mbe::syntax_node_to_token_tree( - arg.syntax(), - map.as_ref(), - map.span_for_range(macro_def.macro_token().unwrap().text_range()), - ); - - mbe::DeclarativeMacro::parse_macro2(&tt, is_2021, new_meta_vars) - } - None => mbe::DeclarativeMacro::from_err( - mbe::ParseError::Expected("expected a token tree".into()), - is_2021, - ), - }, - transparency(¯o_def).unwrap_or(Transparency::Opaque), - ), - }; - Arc::new(DeclarativeMacroExpander { mac, transparency }) -} - -fn macro_expander(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander { - match id.kind { - MacroDefKind::Declarative(ast_id) => { - TokenExpander::DeclarativeMacro(db.decl_macro_expander(id.krate, ast_id)) +impl TokenExpander { + fn macro_expander(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander { + match id.kind { + MacroDefKind::Declarative(ast_id) => { + TokenExpander::DeclarativeMacro(db.decl_macro_expander(id.krate, ast_id)) + } + MacroDefKind::BuiltIn(expander, _) => TokenExpander::BuiltIn(expander), + MacroDefKind::BuiltInAttr(expander, _) => TokenExpander::BuiltInAttr(expander), + MacroDefKind::BuiltInDerive(expander, _) => TokenExpander::BuiltInDerive(expander), + MacroDefKind::BuiltInEager(expander, ..) => TokenExpander::BuiltInEager(expander), + MacroDefKind::ProcMacro(expander, ..) => TokenExpander::ProcMacro(expander), } - MacroDefKind::BuiltIn(expander, _) => TokenExpander::BuiltIn(expander), - MacroDefKind::BuiltInAttr(expander, _) => TokenExpander::BuiltInAttr(expander), - MacroDefKind::BuiltInDerive(expander, _) => TokenExpander::BuiltInDerive(expander), - MacroDefKind::BuiltInEager(expander, ..) => TokenExpander::BuiltInEager(expander), - MacroDefKind::ProcMacro(expander, ..) => TokenExpander::ProcMacro(expander), } } @@ -862,40 +678,3 @@ fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<()>> { fn setup_syntax_context_root(db: &dyn ExpandDatabase) { db.intern_syntax_context(SyntaxContextData::root()); } - -fn dump_syntax_contexts(db: &dyn ExpandDatabase) -> String { - 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(); - s.push_str(&format!( - "\n{:?}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}", - id, - expn_data.kind.file_id(), - expn_data.call_site, - SyntaxContextId::ROOT, // FIXME expn_data.def_site, - expn_data.kind.descr(), - )); - } - - s.push_str("\n\nSyntaxContexts:\n"); - let mut entries = InternSyntaxContextLookupQuery.in_db(db).entries::>(); - entries.sort_by_key(|e| e.key); - for e in entries { - struct SyntaxContextDebug<'a>( - &'a dyn ExpandDatabase, - SyntaxContextId, - &'a SyntaxContextData, - ); - - impl<'a> std::fmt::Debug for SyntaxContextDebug<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.2.fancy_debug(self.1, self.0, f) - } - } - stdx::format_to!(s, "{:?}\n", SyntaxContextDebug(db, e.key, &e.value.unwrap())); - } - s -} diff --git a/crates/hir-expand/src/declarative.rs b/crates/hir-expand/src/declarative.rs new file mode 100644 index 0000000000000..ff1a9625e111b --- /dev/null +++ b/crates/hir-expand/src/declarative.rs @@ -0,0 +1,176 @@ +use std::sync::OnceLock; + +use base_db::{CrateId, Edition, VersionReq}; +use span::{MacroCallId, Span}; +use syntax::{ast, AstNode}; +use triomphe::Arc; + +use crate::{ + attrs::RawAttrs, + db::ExpandDatabase, + hygiene::{apply_mark, Transparency}, + tt, AstId, ExpandError, ExpandResult, +}; + +/// Old-style `macro_rules` or the new macros 2.0 +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct DeclarativeMacroExpander { + pub mac: mbe::DeclarativeMacro, + pub transparency: Transparency, +} + +// FIXME: Remove this once we drop support for 1.76 +static REQUIREMENT: OnceLock = OnceLock::new(); + +impl DeclarativeMacroExpander { + pub fn expand( + &self, + db: &dyn ExpandDatabase, + tt: tt::Subtree, + call_id: MacroCallId, + ) -> ExpandResult { + let loc = db.lookup_intern_macro_call(call_id); + let toolchain = &db.crate_graph()[loc.def.krate].toolchain; + let new_meta_vars = toolchain.as_ref().map_or(false, |version| { + REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( + &base_db::Version { + pre: base_db::Prerelease::EMPTY, + build: base_db::BuildMetadata::EMPTY, + major: version.major, + minor: version.minor, + patch: version.patch, + }, + ) + }); + match self.mac.err() { + Some(e) => ExpandResult::new( + tt::Subtree::empty(tt::DelimSpan { open: loc.call_site, close: loc.call_site }), + ExpandError::other(format!("invalid macro definition: {e}")), + ), + None => self + .mac + .expand( + &tt, + |s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency), + new_meta_vars, + loc.call_site, + ) + .map_err(Into::into), + } + } + + pub fn expand_unhygienic( + &self, + db: &dyn ExpandDatabase, + tt: tt::Subtree, + krate: CrateId, + call_site: Span, + ) -> ExpandResult { + let toolchain = &db.crate_graph()[krate].toolchain; + let new_meta_vars = toolchain.as_ref().map_or(false, |version| { + REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( + &base_db::Version { + pre: base_db::Prerelease::EMPTY, + build: base_db::BuildMetadata::EMPTY, + major: version.major, + minor: version.minor, + patch: version.patch, + }, + ) + }); + match self.mac.err() { + Some(e) => ExpandResult::new( + tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }), + ExpandError::other(format!("invalid macro definition: {e}")), + ), + None => self.mac.expand(&tt, |_| (), new_meta_vars, call_site).map_err(Into::into), + } + } + + pub(crate) fn expander( + db: &dyn ExpandDatabase, + def_crate: CrateId, + id: AstId, + ) -> Arc { + let crate_data = &db.crate_graph()[def_crate]; + let is_2021 = crate_data.edition >= Edition::Edition2021; + let (root, map) = crate::db::parse_with_map(db, id.file_id); + let root = root.syntax_node(); + + let transparency = |node| { + // ... would be nice to have the item tree here + let attrs = RawAttrs::new(db, node, map.as_ref()).filter(db, def_crate); + match &*attrs + .iter() + .find(|it| { + it.path.as_ident().and_then(|it| it.as_str()) + == Some("rustc_macro_transparency") + })? + .token_tree_value()? + .token_trees + { + [tt::TokenTree::Leaf(tt::Leaf::Ident(i)), ..] => match &*i.text { + "transparent" => Some(Transparency::Transparent), + "semitransparent" => Some(Transparency::SemiTransparent), + "opaque" => Some(Transparency::Opaque), + _ => None, + }, + _ => None, + } + }; + let toolchain = crate_data.toolchain.as_ref(); + let new_meta_vars = toolchain.as_ref().map_or(false, |version| { + REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( + &base_db::Version { + pre: base_db::Prerelease::EMPTY, + build: base_db::BuildMetadata::EMPTY, + major: version.major, + minor: version.minor, + patch: version.patch, + }, + ) + }); + + let (mac, transparency) = match id.to_ptr(db).to_node(&root) { + ast::Macro::MacroRules(macro_rules) => ( + match macro_rules.token_tree() { + Some(arg) => { + let tt = mbe::syntax_node_to_token_tree( + arg.syntax(), + map.as_ref(), + map.span_for_range( + macro_rules.macro_rules_token().unwrap().text_range(), + ), + ); + + mbe::DeclarativeMacro::parse_macro_rules(&tt, is_2021, new_meta_vars) + } + None => mbe::DeclarativeMacro::from_err( + mbe::ParseError::Expected("expected a token tree".into()), + is_2021, + ), + }, + transparency(¯o_rules).unwrap_or(Transparency::SemiTransparent), + ), + ast::Macro::MacroDef(macro_def) => ( + match macro_def.body() { + Some(arg) => { + let tt = mbe::syntax_node_to_token_tree( + arg.syntax(), + map.as_ref(), + map.span_for_range(macro_def.macro_token().unwrap().text_range()), + ); + + mbe::DeclarativeMacro::parse_macro2(&tt, is_2021, new_meta_vars) + } + None => mbe::DeclarativeMacro::from_err( + mbe::ParseError::Expected("expected a token tree".into()), + is_2021, + ), + }, + transparency(¯o_def).unwrap_or(Transparency::Opaque), + ), + }; + Arc::new(DeclarativeMacroExpander { mac, transparency }) + } +} diff --git a/crates/hir-expand/src/hygiene.rs b/crates/hir-expand/src/hygiene.rs index 57921543c4b4b..8ddaa3f3039ec 100644 --- a/crates/hir-expand/src/hygiene.rs +++ b/crates/hir-expand/src/hygiene.rs @@ -245,3 +245,43 @@ pub fn marks_rev( }) .map(|ctx| ctx.outer_mark(db)) } + +pub(crate) fn dump_syntax_contexts(db: &dyn ExpandDatabase) -> String { + use crate::db::{InternMacroCallLookupQuery, InternSyntaxContextLookupQuery}; + use base_db::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(); + s.push_str(&format!( + "\n{:?}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}", + id, + expn_data.kind.file_id(), + expn_data.call_site, + SyntaxContextId::ROOT, // FIXME expn_data.def_site, + expn_data.kind.descr(), + )); + } + + s.push_str("\n\nSyntaxContexts:\n"); + let mut entries = InternSyntaxContextLookupQuery.in_db(db).entries::>(); + entries.sort_by_key(|e| e.key); + for e in entries { + struct SyntaxContextDebug<'a>( + &'a dyn ExpandDatabase, + SyntaxContextId, + &'a SyntaxContextData, + ); + + impl<'a> std::fmt::Debug for SyntaxContextDebug<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.2.fancy_debug(self.1, self.0, f) + } + } + stdx::format_to!(s, "{:?}\n", SyntaxContextDebug(db, e.key, &e.value.unwrap())); + } + s +} diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index bd216ccca8239..05f12527a4400 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -11,16 +11,18 @@ pub mod attrs; pub mod builtin_attr_macro; pub mod builtin_derive_macro; pub mod builtin_fn_macro; +pub mod change; pub mod db; +pub mod declarative; pub mod eager; pub mod files; -pub mod change; pub mod hygiene; pub mod mod_path; pub mod name; pub mod proc_macro; pub mod quote; pub mod span_map; + mod fixup; use attrs::collect_attrs; @@ -167,7 +169,8 @@ pub struct MacroCallLoc { pub krate: CrateId, /// Some if this is a macro call for an eager macro. Note that this is `None` /// for the eager input macro file. - // FIXME: This seems bad to save in an interned structure + // FIXME: This is being interned, subtrees can vary quickly differ just slightly causing + // leakage problems here eager: Option>, pub kind: MacroCallKind, pub call_site: Span, @@ -220,7 +223,7 @@ pub enum MacroCallKind { }, Attr { ast_id: AstId, - // FIXME: This is being interned, subtrees can very quickly differ just slightly causing + // FIXME: This is being interned, subtrees can vary quickly differ just slightly causing // leakage problems here attr_args: Option>, /// Syntactical index of the invoking `#[attribute]`. diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 9b72e03410371..01ccebea201e2 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -40,7 +40,7 @@ pub enum PathKind { Crate, /// Absolute path (::foo) Abs, - // FIXME: Remove this + // FIXME: Can we remove this somehow? /// `$crate` from macro expansion DollarCrate(CrateId), } @@ -59,7 +59,8 @@ impl ModPath { } pub fn from_segments(kind: PathKind, segments: impl IntoIterator) -> ModPath { - let segments = segments.into_iter().collect(); + let mut segments: SmallVec<_> = segments.into_iter().collect(); + segments.shrink_to_fit(); ModPath { kind, segments } } diff --git a/crates/hir-expand/src/span_map.rs b/crates/hir-expand/src/span_map.rs index 4ec6e657f9ed9..8e624f5585d48 100644 --- a/crates/hir-expand/src/span_map.rs +++ b/crates/hir-expand/src/span_map.rs @@ -1,10 +1,12 @@ //! Span maps for real files and macro expansions. -use span::Span; -use syntax::TextRange; +use span::{FileId, HirFileId, HirFileIdRepr, Span}; +use syntax::{AstNode, TextRange}; use triomphe::Arc; pub use span::RealSpanMap; +use crate::db::ExpandDatabase; + pub type ExpansionSpanMap = span::SpanMap; /// Spanmap for a macro file or a real file @@ -34,7 +36,6 @@ impl mbe::SpanMapper for SpanMapRef<'_> { self.span_for_range(range) } } - impl SpanMap { pub fn span_for_range(&self, range: TextRange) -> Span { match self { @@ -53,6 +54,16 @@ impl SpanMap { Self::RealSpanMap(span_map) => SpanMapRef::RealSpanMap(span_map), } } + + #[inline] + pub(crate) fn new(db: &dyn ExpandDatabase, file_id: HirFileId) -> SpanMap { + match file_id.repr() { + HirFileIdRepr::FileId(file_id) => SpanMap::RealSpanMap(db.real_span_map(file_id)), + HirFileIdRepr::MacroFile(m) => { + SpanMap::ExpansionSpanMap(db.parse_macro_expansion(m).value.1) + } + } + } } impl SpanMapRef<'_> { @@ -63,3 +74,23 @@ impl SpanMapRef<'_> { } } } + +pub(crate) fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> 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 tree = db.parse(file_id).tree(); + // FIXME: Descend into modules and other item containing items that are not annotated with attributes + // and allocate pairs for those as well. This gives us finer grained span anchors resulting in + // better incrementality + pairs.extend( + tree.items() + .map(|item| (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())), + ); + + Arc::new(RealSpanMap::from_file( + file_id, + pairs.into_boxed_slice(), + tree.syntax().text_range().end(), + )) +} diff --git a/rustfmt.toml b/rustfmt.toml index 71007de81b9f6..20bf59547b86a 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,2 +1,2 @@ -reorder_modules = false +reorder_modules = true use_small_heuristics = "Max" From d8ef6c24cc4e2aa594dcbd561f33fb995278cf17 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 25 Jan 2024 10:23:00 +0100 Subject: [PATCH 070/246] Cleanup `convert_path` --- crates/cfg/src/lib.rs | 2 +- crates/hir-expand/src/attrs.rs | 1 - crates/hir-expand/src/db.rs | 5 +-- crates/hir-expand/src/mod_path.rs | 68 +++++++++++++++---------------- 4 files changed, 34 insertions(+), 42 deletions(-) diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs index 3b41de14335ac..454d6fc5384ba 100644 --- a/crates/cfg/src/lib.rs +++ b/crates/cfg/src/lib.rs @@ -131,7 +131,7 @@ impl CfgDiff { /// of both. pub fn new(enable: Vec, disable: Vec) -> Option { let mut occupied = FxHashSet::default(); - if enable.iter().chain(disable.iter()).any(|item| occupied.insert(item)) { + if enable.iter().chain(disable.iter()).any(|item| !occupied.insert(item)) { // was present return None; } diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs index b7c50fd82aa2e..30d38299d99d4 100644 --- a/crates/hir-expand/src/attrs.rs +++ b/crates/hir-expand/src/attrs.rs @@ -219,7 +219,6 @@ impl Attr { } fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree], id: AttrId) -> Option { - dbg!(tt); let span = tt.first()?.first_span(); let path_end = tt .iter() diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 08542c6430af4..8c43017971fb0 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -1,9 +1,6 @@ //! Defines database & queries for macro expansion. -use base_db::{ - salsa::{self, debug::DebugQueryTable}, - CrateId, FileId, SourceDatabase, -}; +use base_db::{salsa, CrateId, FileId, SourceDatabase}; use either::Either; use limit::Limit; use mbe::{syntax_node_to_token_tree, ValueResult}; diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 01ccebea201e2..0eb1fc1eb5009 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -51,7 +51,7 @@ impl ModPath { path: ast::Path, span_map: SpanMapRef<'_>, ) -> Option { - convert_path(db, None, path, span_map) + convert_path(db, path, span_map) } pub fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option { @@ -199,22 +199,15 @@ fn display_fmt_path( fn convert_path( db: &dyn ExpandDatabase, - prefix: Option, path: ast::Path, span_map: SpanMapRef<'_>, ) -> Option { - let prefix = match path.qualifier() { - Some(qual) => Some(convert_path(db, prefix, qual, span_map)?), - None => prefix, - }; + let mut segments = path.segments(); - let segment = path.segment()?; + let segment = &segments.next()?; let mut mod_path = match segment.kind()? { ast::PathSegmentKind::Name(name_ref) => { if name_ref.text() == "$crate" { - if prefix.is_some() { - return None; - } ModPath::from_kind( resolve_crate_root( db, @@ -224,41 +217,36 @@ fn convert_path( .unwrap_or(PathKind::Crate), ) } else { - let mut res = prefix.unwrap_or_else(|| { - ModPath::from_kind( - segment.coloncolon_token().map_or(PathKind::Plain, |_| PathKind::Abs), - ) - }); + let mut res = ModPath::from_kind( + segment.coloncolon_token().map_or(PathKind::Plain, |_| PathKind::Abs), + ); res.segments.push(name_ref.as_name()); res } } ast::PathSegmentKind::SelfTypeKw => { - if prefix.is_some() { - return None; - } ModPath::from_segments(PathKind::Plain, Some(known::SELF_TYPE)) } - ast::PathSegmentKind::CrateKw => { - if prefix.is_some() { - return None; - } - ModPath::from_segments(PathKind::Crate, iter::empty()) - } - ast::PathSegmentKind::SelfKw => { - if prefix.is_some() { - return None; - } - ModPath::from_segments(PathKind::Super(0), iter::empty()) - } + ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()), + ast::PathSegmentKind::SelfKw => ModPath::from_segments(PathKind::Super(0), iter::empty()), ast::PathSegmentKind::SuperKw => { - let nested_super_count = match prefix.map(|p| p.kind) { - Some(PathKind::Super(n)) => n, - Some(_) => return None, - None => 0, - }; + let mut deg = 1; + let mut next_segment = None; + while let Some(segment) = segments.next() { + match segment.kind()? { + ast::PathSegmentKind::SuperKw => deg += 1, + ast::PathSegmentKind::Name(name) => { + next_segment = Some(name.as_name()); + break; + } + ast::PathSegmentKind::Type { .. } + | ast::PathSegmentKind::SelfTypeKw + | ast::PathSegmentKind::SelfKw + | ast::PathSegmentKind::CrateKw => return None, + } + } - ModPath::from_segments(PathKind::Super(nested_super_count + 1), iter::empty()) + ModPath::from_segments(PathKind::Super(deg), next_segment) } ast::PathSegmentKind::Type { .. } => { // not allowed in imports @@ -266,6 +254,14 @@ fn convert_path( } }; + for segment in segments { + let name = match segment.kind()? { + ast::PathSegmentKind::Name(name) => name.as_name(), + _ => return None, + }; + mod_path.segments.push(name); + } + // handle local_inner_macros : // Basically, even in rustc it is quite hacky: // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 From 5a343415e83b9cf88a2cce9ce945746c4601f765 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 26 Jan 2024 10:43:25 +0100 Subject: [PATCH 071/246] Add some size assertions --- crates/hir-def/src/lib.rs | 71 +------ crates/hir-def/src/nameres/attr_resolution.rs | 67 +++++- crates/hir-def/src/nameres/collector.rs | 10 +- crates/hir-def/src/visibility.rs | 2 + crates/hir-expand/src/builtin_attr_macro.rs | 8 +- crates/hir-expand/src/lib.rs | 3 + crates/hir-expand/src/mod_path.rs | 2 + crates/hir-expand/src/name.rs | 2 + crates/hir/src/lib.rs | 197 ++++++++---------- crates/mbe/src/syntax_bridge.rs | 10 +- crates/span/src/lib.rs | 5 +- crates/stdx/src/macros.rs | 9 + editors/code/language-configuration.json | 6 +- 13 files changed, 194 insertions(+), 198 deletions(-) diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 790e3b414b698..243de663977fd 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -25,13 +25,13 @@ extern crate ra_ap_rustc_abi as rustc_abi; pub mod db; pub mod attr; -pub mod path; pub mod builtin_type; -pub mod per_ns; pub mod item_scope; +pub mod path; +pub mod per_ns; -pub mod lower; pub mod expander; +pub mod lower; pub mod dyn_map; @@ -46,24 +46,24 @@ pub use self::hir::type_ref; pub mod body; pub mod resolver; -mod trace; pub mod nameres; +mod trace; -pub mod src; pub mod child_by_source; +pub mod src; -pub mod visibility; pub mod find_path; pub mod import_map; +pub mod visibility; pub use rustc_abi as layout; use triomphe::Arc; -#[cfg(test)] -mod test_db; #[cfg(test)] mod macro_expansion_tests; mod pretty; +#[cfg(test)] +mod test_db; use std::{ hash::{Hash, Hasher}, @@ -73,7 +73,6 @@ use std::{ use base_db::{impl_intern_key, salsa, CrateId, Edition}; use hir_expand::{ ast_id_map::{AstIdNode, FileAstId}, - attrs::{Attr, AttrId, AttrInput}, builtin_attr_macro::BuiltinAttrExpander, builtin_derive_macro::BuiltinDeriveExpander, builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander}, @@ -1274,60 +1273,6 @@ fn macro_call_as_call_id_with_eager( Ok(res) } -fn derive_macro_as_call_id( - db: &dyn DefDatabase, - item_attr: &AstIdWithPath, - derive_attr_index: AttrId, - derive_pos: u32, - call_site: Span, - krate: CrateId, - resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>, -) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> { - let (macro_id, def_id) = resolver(item_attr.path.clone()) - .filter(|(_, def_id)| def_id.is_derive()) - .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?; - let call_id = def_id.as_lazy_macro( - db.upcast(), - krate, - MacroCallKind::Derive { - ast_id: item_attr.ast_id, - derive_index: derive_pos, - derive_attr_index, - }, - call_site, - ); - Ok((macro_id, def_id, call_id)) -} - -fn attr_macro_as_call_id( - db: &dyn DefDatabase, - item_attr: &AstIdWithPath, - macro_attr: &Attr, - krate: CrateId, - def: MacroDefId, -) -> MacroCallId { - let arg = match macro_attr.input.as_deref() { - Some(AttrInput::TokenTree(tt)) => { - let mut tt = tt.as_ref().clone(); - tt.delimiter = tt::Delimiter::invisible_spanned(macro_attr.span); - Some(tt) - } - - _ => None, - }; - - def.as_lazy_macro( - db.upcast(), - krate, - MacroCallKind::Attr { - ast_id: item_attr.ast_id, - attr_args: arg.map(Arc::new), - invoc_attr_index: macro_attr.id, - }, - macro_attr.span, - ) -} - #[derive(Debug)] pub struct UnresolvedMacro { pub path: hir_expand::mod_path::ModPath, diff --git a/crates/hir-def/src/nameres/attr_resolution.rs b/crates/hir-def/src/nameres/attr_resolution.rs index 6288b8366bf05..1cadae8c87c49 100644 --- a/crates/hir-def/src/nameres/attr_resolution.rs +++ b/crates/hir-def/src/nameres/attr_resolution.rs @@ -1,16 +1,21 @@ //! Post-nameres attribute resolution. -use hir_expand::{attrs::Attr, MacroCallId}; +use base_db::CrateId; +use hir_expand::{ + attrs::{Attr, AttrId, AttrInput}, + MacroCallId, MacroCallKind, MacroDefId, +}; +use span::Span; use syntax::{ast, SmolStr}; +use triomphe::Arc; use crate::{ attr::builtin::{find_builtin_attr_idx, TOOL_MODULES}, - attr_macro_as_call_id, db::DefDatabase, item_scope::BuiltinShadowMode, nameres::path_resolution::ResolveMode, - path::{ModPath, PathKind}, - AstIdWithPath, LocalModuleId, UnresolvedMacro, + path::{self, ModPath, PathKind}, + AstIdWithPath, LocalModuleId, MacroId, UnresolvedMacro, }; use super::{DefMap, MacroSubNs}; @@ -93,3 +98,57 @@ impl DefMap { false } } + +pub(super) fn attr_macro_as_call_id( + db: &dyn DefDatabase, + item_attr: &AstIdWithPath, + macro_attr: &Attr, + krate: CrateId, + def: MacroDefId, +) -> MacroCallId { + let arg = match macro_attr.input.as_deref() { + Some(AttrInput::TokenTree(tt)) => { + let mut tt = tt.as_ref().clone(); + tt.delimiter = tt::Delimiter::invisible_spanned(macro_attr.span); + Some(tt) + } + + _ => None, + }; + + def.as_lazy_macro( + db.upcast(), + krate, + MacroCallKind::Attr { + ast_id: item_attr.ast_id, + attr_args: arg.map(Arc::new), + invoc_attr_index: macro_attr.id, + }, + macro_attr.span, + ) +} + +pub(super) fn derive_macro_as_call_id( + db: &dyn DefDatabase, + item_attr: &AstIdWithPath, + derive_attr_index: AttrId, + derive_pos: u32, + call_site: Span, + krate: CrateId, + resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>, +) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> { + let (macro_id, def_id) = resolver(item_attr.path.clone()) + .filter(|(_, def_id)| def_id.is_derive()) + .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?; + let call_id = def_id.as_lazy_macro( + db.upcast(), + krate, + MacroCallKind::Derive { + ast_id: item_attr.ast_id, + derive_index: derive_pos, + derive_attr_index, + }, + call_site, + ); + Ok((macro_id, def_id, call_id)) +} diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 1c0f4d4d35ff1..248d3213d5d75 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -30,9 +30,7 @@ use triomphe::Arc; use crate::{ attr::Attrs, - attr_macro_as_call_id, db::DefDatabase, - derive_macro_as_call_id, item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports}, item_tree::{ self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, @@ -40,6 +38,7 @@ use crate::{ }, macro_call_as_call_id, macro_call_as_call_id_with_eager, nameres::{ + attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id}, diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, @@ -1245,7 +1244,9 @@ impl DefCollector<'_> { MacroDefId { kind: MacroDefKind::BuiltInAttr(expander, _),.. } if expander.is_derive() ) { - // Resolved to `#[derive]` + // Resolved to `#[derive]`, we don't actually expand this attribute like + // normal (as that would just be an identity expansion with extra output) + // Instead we treat derive attributes special and apply them separately. let item_tree = tree.item_tree(self.db); let ast_adt_id: FileAstId = match *mod_item { @@ -1284,7 +1285,8 @@ impl DefCollector<'_> { } // We treat the #[derive] macro as an attribute call, but we do not resolve it for nameres collection. - // This is just a trick to be able to resolve the input to derives as proper paths. + // This is just a trick to be able to resolve the input to derives + // as proper paths in `Semantics`. // Check the comment in [`builtin_attr_macro`]. let call_id = attr_macro_as_call_id( self.db, diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs index 3294ce29a4a05..8d27884c26969 100644 --- a/crates/hir-def/src/visibility.rs +++ b/crates/hir-def/src/visibility.rs @@ -4,6 +4,7 @@ use std::iter; use hir_expand::{span_map::SpanMapRef, InFile}; use la_arena::ArenaMap; +use stdx::assert_eq_size; use syntax::ast; use triomphe::Arc; @@ -24,6 +25,7 @@ pub enum RawVisibility { /// `pub`. Public, } +assert_eq_size!(RawVisibility, 48); impl RawVisibility { pub(crate) const fn private() -> RawVisibility { diff --git a/crates/hir-expand/src/builtin_attr_macro.rs b/crates/hir-expand/src/builtin_attr_macro.rs index 55157abe671ad..dd2aa94ad01df 100644 --- a/crates/hir-expand/src/builtin_attr_macro.rs +++ b/crates/hir-expand/src/builtin_attr_macro.rs @@ -48,11 +48,13 @@ impl BuiltinAttrExpander { register_builtin! { expand: (bench, Bench) => dummy_attr_expand, + (cfg, Cfg) => dummy_attr_expand, + (cfg_attr, CfgAttr) => dummy_attr_expand, (cfg_accessible, CfgAccessible) => dummy_attr_expand, (cfg_eval, CfgEval) => dummy_attr_expand, - (derive, Derive) => derive_attr_expand, + (derive, Derive) => derive_expand, // derive const is equivalent to derive for our proposes. - (derive_const, DeriveConst) => derive_attr_expand, + (derive_const, DeriveConst) => derive_expand, (global_allocator, GlobalAllocator) => dummy_attr_expand, (test, Test) => dummy_attr_expand, (test_case, TestCase) => dummy_attr_expand @@ -91,7 +93,7 @@ fn dummy_attr_expand( /// always resolve as a derive without nameres recollecting them. /// So this hacky approach is a lot more friendly for us, though it does require a bit of support in /// [`hir::Semantics`] to make this work. -fn derive_attr_expand( +fn derive_expand( db: &dyn ExpandDatabase, id: MacroCallId, tt: &tt::Subtree, diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index 05f12527a4400..37b41c09c5f63 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -26,6 +26,7 @@ pub mod span_map; mod fixup; use attrs::collect_attrs; +use stdx::assert_eq_size; use triomphe::Arc; use std::{fmt, hash::Hash}; @@ -175,6 +176,7 @@ pub struct MacroCallLoc { pub kind: MacroCallKind, pub call_site: Span, } +assert_eq_size!(MacroCallLoc, 104); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroDefId { @@ -185,6 +187,7 @@ pub struct MacroDefId { pub allow_internal_unsafe: bool, pub span: Span, } +assert_eq_size!(MacroDefId, 44); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum MacroDefKind { diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 0eb1fc1eb5009..6dc01fba91b75 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -15,6 +15,7 @@ use crate::{ use base_db::CrateId; use smallvec::SmallVec; use span::SyntaxContextId; +use stdx::assert_eq_size; use syntax::{ast, AstNode}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -22,6 +23,7 @@ pub struct ModPath { pub kind: PathKind, segments: SmallVec<[Name; 1]>, } +assert_eq_size!(ModPath, 40); #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct UnescapedModPath<'a>(&'a ModPath); diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 91c362399e773..6ebefde32c4ae 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -2,6 +2,7 @@ use std::fmt; +use stdx::assert_eq_size; use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr}; /// `Name` is a wrapper around string, which is used in hir for both references @@ -13,6 +14,7 @@ use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr}; /// name without "r#". #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Name(Repr); +assert_eq_size!(Name, 24); /// Wrapper of `Name` to print the name without "r#" even when it is a raw identifier. #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c50be5f11419d..c332ab0050cfb 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -24,12 +24,12 @@ mod semantics; mod source_analyzer; -mod from_id; mod attrs; +mod from_id; mod has_source; -pub mod diagnostics; pub mod db; +pub mod diagnostics; pub mod symbols; mod display; @@ -70,13 +70,12 @@ use hir_ty::{ primitive::UintTy, traits::FnTrait, AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, - GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution, - TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId, - WhereClause, + GenericArgData, InferenceDiagnostic, Interner, ParamKind, QuantifiedWhereClause, Scalar, + Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, + ValueTyDefId, WhereClause, }; use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; -use once_cell::unsync::Lazy; use rustc_hash::FxHashSet; use stdx::{impl_from, never}; use syntax::{ @@ -1592,53 +1591,46 @@ impl DefWithBody { } for diag in source_map.diagnostics() { - match diag { - BodyDiagnostic::InactiveCode { node, cfg, opts } => acc.push( - InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into(), - ), - BodyDiagnostic::MacroError { node, message } => acc.push( - MacroError { - node: (*node).map(|it| it.into()), - precise_location: None, - message: message.to_string(), - } - .into(), - ), - BodyDiagnostic::UnresolvedProcMacro { node, krate } => acc.push( - UnresolvedProcMacro { - node: (*node).map(|it| it.into()), - precise_location: None, - macro_name: None, - kind: MacroKind::ProcMacro, - krate: *krate, - } - .into(), - ), - BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push( - UnresolvedMacroCall { - macro_call: (*node).map(|ast_ptr| ast_ptr.into()), - precise_location: None, - path: path.clone(), - is_bang: true, - } - .into(), - ), + acc.push(match diag { + BodyDiagnostic::InactiveCode { node, cfg, opts } => { + InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into() + } + BodyDiagnostic::MacroError { node, message } => MacroError { + node: (*node).map(|it| it.into()), + precise_location: None, + message: message.to_string(), + } + .into(), + BodyDiagnostic::UnresolvedProcMacro { node, krate } => UnresolvedProcMacro { + node: (*node).map(|it| it.into()), + precise_location: None, + macro_name: None, + kind: MacroKind::ProcMacro, + krate: *krate, + } + .into(), + BodyDiagnostic::UnresolvedMacroCall { node, path } => UnresolvedMacroCall { + macro_call: (*node).map(|ast_ptr| ast_ptr.into()), + precise_location: None, + path: path.clone(), + is_bang: true, + } + .into(), BodyDiagnostic::UnreachableLabel { node, name } => { - acc.push(UnreachableLabel { node: *node, name: name.clone() }.into()) + UnreachableLabel { node: *node, name: name.clone() }.into() } BodyDiagnostic::UndeclaredLabel { node, name } => { - acc.push(UndeclaredLabel { node: *node, name: name.clone() }.into()) + UndeclaredLabel { node: *node, name: name.clone() }.into() } - } + }); } let infer = db.infer(self.into()); - let source_map = Lazy::new(|| db.body_with_source_map(self.into()).1); let expr_syntax = |expr| source_map.expr_syntax(expr).expect("unexpected synthetic"); let pat_syntax = |pat| source_map.pat_syntax(pat).expect("unexpected synthetic"); for d in &infer.diagnostics { - match d { - &hir_ty::InferenceDiagnostic::NoSuchField { field: expr, private } => { + acc.push(match d { + &InferenceDiagnostic::NoSuchField { field: expr, private } => { let expr_or_pat = match expr { ExprOrPatId::ExprId(expr) => { source_map.field_syntax(expr).map(AstPtr::wrap_left) @@ -1647,57 +1639,48 @@ impl DefWithBody { source_map.pat_field_syntax(pat).map(AstPtr::wrap_right) } }; - acc.push(NoSuchField { field: expr_or_pat, private }.into()) + NoSuchField { field: expr_or_pat, private }.into() } - &hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { - acc.push( - MismatchedArgCount { call_expr: expr_syntax(call_expr), expected, found } - .into(), - ) + &InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { + MismatchedArgCount { call_expr: expr_syntax(call_expr), expected, found }.into() } - &hir_ty::InferenceDiagnostic::PrivateField { expr, field } => { + &InferenceDiagnostic::PrivateField { expr, field } => { let expr = expr_syntax(expr); let field = field.into(); - acc.push(PrivateField { expr, field }.into()) + PrivateField { expr, field }.into() } - &hir_ty::InferenceDiagnostic::PrivateAssocItem { id, item } => { + &InferenceDiagnostic::PrivateAssocItem { id, item } => { let expr_or_pat = match id { ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), }; let item = item.into(); - acc.push(PrivateAssocItem { expr_or_pat, item }.into()) + PrivateAssocItem { expr_or_pat, item }.into() } - hir_ty::InferenceDiagnostic::ExpectedFunction { call_expr, found } => { + InferenceDiagnostic::ExpectedFunction { call_expr, found } => { let call_expr = expr_syntax(*call_expr); - - acc.push( - ExpectedFunction { - call: call_expr, - found: Type::new(db, DefWithBodyId::from(self), found.clone()), - } - .into(), - ) + ExpectedFunction { + call: call_expr, + found: Type::new(db, DefWithBodyId::from(self), found.clone()), + } + .into() } - hir_ty::InferenceDiagnostic::UnresolvedField { + InferenceDiagnostic::UnresolvedField { expr, receiver, name, method_with_same_name_exists, } => { let expr = expr_syntax(*expr); - - acc.push( - UnresolvedField { - expr, - name: name.clone(), - receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), - method_with_same_name_exists: *method_with_same_name_exists, - } - .into(), - ) + UnresolvedField { + expr, + name: name.clone(), + receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), + method_with_same_name_exists: *method_with_same_name_exists, + } + .into() } - hir_ty::InferenceDiagnostic::UnresolvedMethodCall { + InferenceDiagnostic::UnresolvedMethodCall { expr, receiver, name, @@ -1705,50 +1688,38 @@ impl DefWithBody { assoc_func_with_same_name, } => { let expr = expr_syntax(*expr); - - acc.push( - UnresolvedMethodCall { - expr, - name: name.clone(), - receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), - field_with_same_name: field_with_same_name - .clone() - .map(|ty| Type::new(db, DefWithBodyId::from(self), ty)), - assoc_func_with_same_name: *assoc_func_with_same_name, - } - .into(), - ) + UnresolvedMethodCall { + expr, + name: name.clone(), + receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), + field_with_same_name: field_with_same_name + .clone() + .map(|ty| Type::new(db, DefWithBodyId::from(self), ty)), + assoc_func_with_same_name: *assoc_func_with_same_name, + } + .into() } - &hir_ty::InferenceDiagnostic::UnresolvedAssocItem { id } => { + &InferenceDiagnostic::UnresolvedAssocItem { id } => { let expr_or_pat = match id { ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), }; - acc.push(UnresolvedAssocItem { expr_or_pat }.into()) + UnresolvedAssocItem { expr_or_pat }.into() } - &hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { - expr, - is_break, - bad_value_break, - } => { + &InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break, bad_value_break } => { let expr = expr_syntax(expr); - acc.push(BreakOutsideOfLoop { expr, is_break, bad_value_break }.into()) + BreakOutsideOfLoop { expr, is_break, bad_value_break }.into() } - hir_ty::InferenceDiagnostic::TypedHole { expr, expected } => { + InferenceDiagnostic::TypedHole { expr, expected } => { let expr = expr_syntax(*expr); - acc.push( - TypedHole { - expr, - expected: Type::new(db, DefWithBodyId::from(self), expected.clone()), - } - .into(), - ) + + TypedHole { + expr, + expected: Type::new(db, DefWithBodyId::from(self), expected.clone()), + } + .into() } - &hir_ty::InferenceDiagnostic::MismatchedTupleStructPatArgCount { - pat, - expected, - found, - } => { + &InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => { let expr_or_pat = match pat { ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), ExprOrPatId::PatId(pat) => { @@ -1762,11 +1733,9 @@ impl DefWithBody { InFile { file_id, value: ptr } } }; - acc.push( - MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into(), - ) + MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into() } - } + }); } for (pat_or_expr, mismatch) in infer.type_mismatches() { let expr_or_pat = match pat_or_expr { @@ -1805,8 +1774,6 @@ impl DefWithBody { } } - let hir_body = db.body(self.into()); - if let Ok(borrowck_results) = db.borrowck(self.into()) { for borrowck_result in borrowck_results.iter() { let mir_body = &borrowck_result.mir_body; @@ -1828,7 +1795,7 @@ impl DefWithBody { ) } let mol = &borrowck_result.mutability_of_locals; - for (binding_id, binding_data) in hir_body.bindings.iter() { + for (binding_id, binding_data) in body.bindings.iter() { if binding_data.problems.is_some() { // We should report specific diagnostics for these problems, not `need-mut` and `unused-mut`. continue; diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index 8b57d7eeaf588..4513732902db7 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs @@ -234,7 +234,7 @@ where let mut stack = NonEmptyVec::new(entry); while let Some((token, abs_range)) = conv.bump() { - let tt::Subtree { delimiter, token_trees: result } = stack.last_mut(); + let tt::Subtree { delimiter, token_trees } = stack.last_mut(); let tt = match token.as_leaf() { Some(leaf) => tt::TokenTree::Leaf(leaf.clone()), @@ -243,7 +243,7 @@ where COMMENT => { let span = conv.span_for(abs_range); if let Some(tokens) = conv.convert_doc_comment(&token, span) { - result.extend(tokens); + token_trees.extend(tokens); } continue; } @@ -317,7 +317,7 @@ where span: conv .span_for(TextRange::at(abs_range.start(), TextSize::of('\''))), }); - result.push(apostrophe.into()); + token_trees.push(apostrophe.into()); let ident = tt::Leaf::from(tt::Ident { text: SmolStr::new(&token.to_text(conv)[1..]), @@ -326,7 +326,7 @@ where abs_range.end(), )), }); - result.push(ident.into()); + token_trees.push(ident.into()); continue; } _ => continue, @@ -337,7 +337,7 @@ where }, }; - result.push(tt); + token_trees.push(tt); } // If we get here, we've consumed all input tokens. diff --git a/crates/span/src/lib.rs b/crates/span/src/lib.rs index f6569050b4a00..426e4cb55a4c6 100644 --- a/crates/span/src/lib.rs +++ b/crates/span/src/lib.rs @@ -1,10 +1,8 @@ //! File and span related types. -// FIXME: This should be moved into its own crate to get rid of the dependency inversion, base-db -// has business depending on tt, tt should depend on a span crate only (which unforunately will have -// to depend on salsa) use std::fmt::{self, Write}; use salsa::InternId; +use stdx::assert_eq_size; mod map; @@ -38,6 +36,7 @@ pub const FIXUP_ERASED_FILE_AST_ID_MARKER: ErasedFileAstId = la_arena::Idx::from_raw(la_arena::RawIdx::from_u32(!0 - 1)); pub type Span = SpanData; +assert_eq_size!(Span, 20); #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub struct SpanData { diff --git a/crates/stdx/src/macros.rs b/crates/stdx/src/macros.rs index d71e418c89bc6..9f7b7dbc1af8e 100644 --- a/crates/stdx/src/macros.rs +++ b/crates/stdx/src/macros.rs @@ -59,3 +59,12 @@ macro_rules! impl_from { )* } } + +#[macro_export] +macro_rules! assert_eq_size { + ($($ty:ty,)+ $val:expr $(,)?) => { + const _: () = { + $(core::mem::transmute::<[u8; $val], $ty>;)+ + }; + }; +} diff --git a/editors/code/language-configuration.json b/editors/code/language-configuration.json index 1c348b63f1a23..a2af8b51a908b 100644 --- a/editors/code/language-configuration.json +++ b/editors/code/language-configuration.json @@ -6,7 +6,9 @@ "brackets": [ ["{", "}"], ["[", "]"], - ["(", ")"] + ["(", ")"], + ["#[", "]"], + ["#![", "]"] ], "colorizedBracketPairs": [ ["{", "}"], @@ -17,6 +19,8 @@ { "open": "{", "close": "}" }, { "open": "[", "close": "]" }, { "open": "(", "close": ")" }, + { "open": "#[", "close": "]" }, + { "open": "#![", "close": "]" }, { "open": "\"", "close": "\"", "notIn": ["string"] }, { "open": "/*", "close": " */" }, { "open": "`", "close": "`", "notIn": ["string"] } From 6cf7b5f8d7e488ff6b14f8ed552b470ee5ec9cbf Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 26 Jan 2024 19:45:46 +0100 Subject: [PATCH 072/246] Don't parse intra doc links as syntax trees --- crates/hir-def/src/visibility.rs | 2 - crates/hir-expand/src/lib.rs | 3 - crates/hir-expand/src/mod_path.rs | 2 - crates/hir-expand/src/name.rs | 2 - crates/hir/src/attrs.rs | 66 ++++++++++---------- crates/proc-macro-srv/src/server/token_id.rs | 2 +- crates/span/src/lib.rs | 2 - crates/stdx/src/macros.rs | 9 --- 8 files changed, 33 insertions(+), 55 deletions(-) diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs index 8d27884c26969..3294ce29a4a05 100644 --- a/crates/hir-def/src/visibility.rs +++ b/crates/hir-def/src/visibility.rs @@ -4,7 +4,6 @@ use std::iter; use hir_expand::{span_map::SpanMapRef, InFile}; use la_arena::ArenaMap; -use stdx::assert_eq_size; use syntax::ast; use triomphe::Arc; @@ -25,7 +24,6 @@ pub enum RawVisibility { /// `pub`. Public, } -assert_eq_size!(RawVisibility, 48); impl RawVisibility { pub(crate) const fn private() -> RawVisibility { diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index 37b41c09c5f63..05f12527a4400 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -26,7 +26,6 @@ pub mod span_map; mod fixup; use attrs::collect_attrs; -use stdx::assert_eq_size; use triomphe::Arc; use std::{fmt, hash::Hash}; @@ -176,7 +175,6 @@ pub struct MacroCallLoc { pub kind: MacroCallKind, pub call_site: Span, } -assert_eq_size!(MacroCallLoc, 104); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroDefId { @@ -187,7 +185,6 @@ pub struct MacroDefId { pub allow_internal_unsafe: bool, pub span: Span, } -assert_eq_size!(MacroDefId, 44); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum MacroDefKind { diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 6dc01fba91b75..0eb1fc1eb5009 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -15,7 +15,6 @@ use crate::{ use base_db::CrateId; use smallvec::SmallVec; use span::SyntaxContextId; -use stdx::assert_eq_size; use syntax::{ast, AstNode}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -23,7 +22,6 @@ pub struct ModPath { pub kind: PathKind, segments: SmallVec<[Name; 1]>, } -assert_eq_size!(ModPath, 40); #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct UnescapedModPath<'a>(&'a ModPath); diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 6ebefde32c4ae..91c362399e773 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -2,7 +2,6 @@ use std::fmt; -use stdx::assert_eq_size; use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr}; /// `Name` is a wrapper around string, which is used in hir for both references @@ -14,7 +13,6 @@ use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr}; /// name without "r#". #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Name(Repr); -assert_eq_size!(Name, 24); /// Wrapper of `Name` to print the name without "r#" even when it is a raw identifier. #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 7b9f895bc73eb..fc0a196df7cbe 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -2,7 +2,6 @@ use std::ops::ControlFlow; -use base_db::FileId; use hir_def::{ attr::AttrsWithOwner, item_scope::ItemInNs, @@ -11,12 +10,8 @@ use hir_def::{ resolver::{HasResolver, Resolver, TypeNs}, AssocItemId, AttrDefId, ModuleDefId, }; -use hir_expand::{ - name::Name, - span_map::{RealSpanMap, SpanMapRef}, -}; +use hir_expand::{mod_path::PathKind, name::Name}; use hir_ty::{db::HirDatabase, method_resolution}; -use syntax::{ast, AstNode}; use crate::{ Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, @@ -129,7 +124,7 @@ fn resolve_doc_path_on_( AttrDefId::GenericParamId(_) => return None, }; - let mut modpath = modpath_from_str(db, link)?; + let mut modpath = modpath_from_str(link)?; let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath); if resolved.is_none() { @@ -305,34 +300,37 @@ fn as_module_def_if_namespace_matches( (ns.unwrap_or(expected_ns) == expected_ns).then(|| DocLinkDef::ModuleDef(def)) } -fn modpath_from_str(db: &dyn HirDatabase, link: &str) -> Option { +fn modpath_from_str(link: &str) -> Option { // FIXME: this is not how we should get a mod path here. let try_get_modpath = |link: &str| { - let ast_path = ast::SourceFile::parse(&format!("type T = {link};")) - .syntax_node() - .descendants() - .find_map(ast::Path::cast)?; - if ast_path.syntax().text() != link { - return None; - } - ModPath::from_src( - db.upcast(), - ast_path, - SpanMapRef::RealSpanMap(&RealSpanMap::absolute(FileId::BOGUS)), - ) + let mut parts = link.split("::"); + let mut first_segment = None; + let kind = match parts.next()? { + "" => PathKind::Abs, + "crate" => PathKind::Crate, + "self" => PathKind::Super(0), + "super" => { + let mut deg = 1; + while let Some(segment) = parts.next() { + if segment == "super" { + deg += 1; + } else { + first_segment = Some(segment); + break; + } + } + PathKind::Super(deg) + } + segment => { + first_segment = Some(segment); + PathKind::Plain + } + }; + let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() { + Ok(idx) => Name::new_tuple_field(idx), + Err(_) => Name::new_text_dont_use(segment.into()), + }); + Some(ModPath::from_segments(kind, parts)) }; - - let full = try_get_modpath(link); - if full.is_some() { - return full; - } - - // Tuple field names cannot be a part of `ModPath` usually, but rustdoc can - // resolve doc paths like `TupleStruct::0`. - // FIXME: Find a better way to handle these. - let (base, maybe_tuple_field) = link.rsplit_once("::")?; - let tuple_field = Name::new_tuple_field(maybe_tuple_field.parse().ok()?); - let mut modpath = try_get_modpath(base)?; - modpath.push_segment(tuple_field); - Some(modpath) + try_get_modpath(link) } diff --git a/crates/proc-macro-srv/src/server/token_id.rs b/crates/proc-macro-srv/src/server/token_id.rs index f3da01cb104b2..c83e09af0d6e1 100644 --- a/crates/proc-macro-srv/src/server/token_id.rs +++ b/crates/proc-macro-srv/src/server/token_id.rs @@ -206,7 +206,7 @@ impl server::TokenStream for TokenIdServer { stream: if subtree.token_trees.is_empty() { None } else { - Some(subtree.token_trees) + Some(TokenStream { token_trees: subtree.token_trees }) }, span: bridge::DelimSpan::from_single(subtree.delimiter.open), }), diff --git a/crates/span/src/lib.rs b/crates/span/src/lib.rs index 426e4cb55a4c6..6796dc41886f5 100644 --- a/crates/span/src/lib.rs +++ b/crates/span/src/lib.rs @@ -2,7 +2,6 @@ use std::fmt::{self, Write}; use salsa::InternId; -use stdx::assert_eq_size; mod map; @@ -36,7 +35,6 @@ pub const FIXUP_ERASED_FILE_AST_ID_MARKER: ErasedFileAstId = la_arena::Idx::from_raw(la_arena::RawIdx::from_u32(!0 - 1)); pub type Span = SpanData; -assert_eq_size!(Span, 20); #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub struct SpanData { diff --git a/crates/stdx/src/macros.rs b/crates/stdx/src/macros.rs index 9f7b7dbc1af8e..d71e418c89bc6 100644 --- a/crates/stdx/src/macros.rs +++ b/crates/stdx/src/macros.rs @@ -59,12 +59,3 @@ macro_rules! impl_from { )* } } - -#[macro_export] -macro_rules! assert_eq_size { - ($($ty:ty,)+ $val:expr $(,)?) => { - const _: () = { - $(core::mem::transmute::<[u8; $val], $ty>;)+ - }; - }; -} From 40f5e6899d00484f05a3f1b227180a69a43bea0f Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 28 Dec 2023 16:20:02 -0800 Subject: [PATCH 073/246] Build Fuchsia on 8 cores instead of 16 --- .github/workflows/ci.yml | 2 +- src/ci/github-actions/ci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index caf97abf78d9e..e8e103df68b3b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -291,7 +291,7 @@ jobs: - name: x86_64-gnu-integration env: CI_ONLY_WHEN_CHANNEL: nightly - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb - name: x86_64-gnu-debug os: ubuntu-20.04-8core-32gb env: {} diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 68a3afc910f22..659d048cc1d9a 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -476,7 +476,7 @@ jobs: # nightly features to compile, and this job would fail if # executed on beta and stable. CI_ONLY_WHEN_CHANNEL: nightly - <<: *job-linux-16c + <<: *job-linux-8c - name: x86_64-gnu-debug <<: *job-linux-8c From 53bf511af2b9b54702943eb4fe6e4f17d9fc96c6 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 28 Dec 2023 16:44:49 -0800 Subject: [PATCH 074/246] Skip building cranelift for Fuchsia This refactors run.sh to never override an explicit $CODEGEN_BACKENDS if set in the build. --- .../docker/host-x86_64/x86_64-gnu-integration/Dockerfile | 3 +++ src/ci/run.sh | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile index ba65ba9bed460..3132f9e0098b3 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile @@ -51,6 +51,9 @@ RUN sh /scripts/sccache.sh ENV RUST_INSTALL_DIR /checkout/obj/install RUN mkdir -p $RUST_INSTALL_DIR/etc +# Fuchsia only supports LLVM. +ENV CODEGEN_BACKENDS llvm + ENV RUST_CONFIGURE_ARGS \ --prefix=$RUST_INSTALL_DIR \ --sysconfdir=etc \ diff --git a/src/ci/run.sh b/src/ci/run.sh index 420545172e6d5..1cdcffc1a7544 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -119,7 +119,8 @@ if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.verify-llvm-ir" fi - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-backends=${CODEGEN_BACKENDS:-llvm}" + CODEGEN_BACKENDS="${CODEGEN_BACKENDS:-llvm}" + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-backends=$CODEGEN_BACKENDS" else # We almost always want debug assertions enabled, but sometimes this takes too # long for too little benefit, so we just turn them off. @@ -144,11 +145,12 @@ else # tests as it will fail them. if [[ "${ENABLE_GCC_CODEGEN}" == "1" ]]; then # Test the Cranelift and GCC backends in CI. Bootstrap knows which targets to run tests on. - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-backends=llvm,cranelift,gcc" + CODEGEN_BACKENDS="${CODEGEN_BACKENDS:-llvm,cranelift,gcc}" else # Test the Cranelift backend in CI. Bootstrap knows which targets to run tests on. - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-backends=llvm,cranelift" + CODEGEN_BACKENDS="${CODEGEN_BACKENDS:-llvm,cranelift}" fi + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-backends=$CODEGEN_BACKENDS" # We enable this for non-dist builders, since those aren't trying to produce # fresh binaries. We currently don't entirely support distributing a fresh From afd5edc8c995662760ed9cccce687637af86967f Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 25 Jan 2024 16:40:15 -0800 Subject: [PATCH 075/246] Bump Fuchsia (includes building tests) This includes a change to the upstream build_fuchsia_from_rust_ci script that builds a minimal set of tests, to improve coverage on this builder. --- src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile | 1 + .../docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile index 3132f9e0098b3..bec1c89733775 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile @@ -44,6 +44,7 @@ ENV CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS \ ENV TARGETS=x86_64-fuchsia ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnu +ENV TARGETS=$TARGETS,wasm32-unknown-unknown COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh index 4a246f591d717..d6de992913bf5 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh @@ -5,7 +5,7 @@ set -euf -o pipefail -INTEGRATION_SHA=66793c4894bf6204579bbee3b79956335f31c768 +INTEGRATION_SHA=56310bca298872ffb5ea02e665956d9b6dc41171 PICK_REFS=() checkout=fuchsia From ad5e2cfa3b9fe079e962e806e59cf92f030984d1 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 27 Jan 2024 02:00:36 +0200 Subject: [PATCH 076/246] Do not return code lens data after resolving --- crates/rust-analyzer/src/handlers/request.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index f3c2df24d951b..1a55dcebc1350 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -1319,6 +1319,9 @@ pub(crate) fn handle_code_lens_resolve( snap: GlobalStateSnapshot, code_lens: CodeLens, ) -> anyhow::Result { + if code_lens.data.is_none() { + return Ok(code_lens); + } let Some(annotation) = from_proto::annotation(&snap, code_lens.clone())? else { return Ok(code_lens); }; @@ -1327,13 +1330,14 @@ pub(crate) fn handle_code_lens_resolve( let mut acc = Vec::new(); to_proto::code_lens(&mut acc, &snap, annotation)?; - let res = match acc.pop() { + let mut res = match acc.pop() { Some(it) if acc.is_empty() => it, _ => { never!(); code_lens } }; + res.data = None; Ok(res) } From 8a5829cf286c8361d93aab090bbf4fc599e37fef Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 26 Jan 2024 20:08:10 +0100 Subject: [PATCH 077/246] Re-order mod declarations --- crates/base-db/src/lib.rs | 2 +- crates/hir-def/src/body.rs | 4 +- crates/hir-def/src/hir.rs | 2 +- .../hir-def/src/macro_expansion_tests/mbe.rs | 2 +- .../hir-def/src/macro_expansion_tests/mod.rs | 4 +- crates/hir-def/src/nameres.rs | 4 +- crates/hir-expand/src/declarative.rs | 1 + crates/hir-ty/src/diagnostics.rs | 2 +- crates/hir-ty/src/lib.rs | 4 +- crates/hir-ty/src/mir.rs | 4 +- crates/hir-ty/src/tests.rs | 14 +++---- crates/ide-assists/src/lib.rs | 38 +++++++++---------- crates/ide-assists/src/utils.rs | 2 +- crates/ide-completion/src/completions.rs | 4 +- .../src/completions/attribute.rs | 2 +- crates/ide-completion/src/lib.rs | 2 +- crates/ide-completion/src/render.rs | 8 ++-- crates/ide-completion/src/tests.rs | 2 +- crates/ide-db/src/lib.rs | 8 ++-- crates/ide-diagnostics/src/lib.rs | 14 +++---- crates/ide-ssr/src/lib.rs | 2 +- crates/ide/src/inlay_hints.rs | 4 +- crates/ide/src/lib.rs | 14 +++---- crates/ide/src/syntax_highlighting.rs | 6 +-- crates/mbe/src/lib.rs | 4 +- crates/parser/src/grammar.rs | 4 +- crates/parser/src/grammar/items.rs | 2 +- crates/parser/src/lib.rs | 8 ++-- crates/parser/src/tests.rs | 2 +- crates/proc-macro-srv/src/lib.rs | 2 +- crates/proc-macro-srv/src/server.rs | 2 +- crates/profile/src/lib.rs | 4 +- crates/project-model/src/lib.rs | 8 ++-- crates/rust-analyzer/src/cli.rs | 12 +++--- crates/rust-analyzer/src/lsp.rs | 4 +- crates/stdx/src/lib.rs | 6 +-- crates/syntax/src/ast.rs | 12 +++--- crates/syntax/src/lib.rs | 12 +++--- lib/lsp-server/src/lib.rs | 6 +-- xtask/src/main.rs | 6 +-- 40 files changed, 122 insertions(+), 121 deletions(-) diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index 92d2b9c3f57c9..90da7efd4a8b2 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -2,8 +2,8 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod input; mod change; +mod input; use std::panic; diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index 81132d738539f..e4308c6b7f1f2 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -1,10 +1,10 @@ //! Defines `Body`: a lowered representation of bodies of functions, statics and //! consts. mod lower; +mod pretty; +pub mod scope; #[cfg(test)] mod tests; -pub mod scope; -mod pretty; use std::ops::Index; diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index 1a33868a78cd9..ac44d379415c0 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -12,8 +12,8 @@ //! //! See also a neighboring `body` module. -pub mod type_ref; pub mod format_args; +pub mod type_ref; use std::fmt; diff --git a/crates/hir-def/src/macro_expansion_tests/mbe.rs b/crates/hir-def/src/macro_expansion_tests/mbe.rs index 6d365bd93c0a4..d0ae1f59f7ca6 100644 --- a/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -1,11 +1,11 @@ //! Tests specific to declarative macros, aka macros by example. This covers //! both stable `macro_rules!` macros as well as unstable `macro` macros. -mod tt_conversion; mod matching; mod meta_syntax; mod metavar_expr; mod regression; +mod tt_conversion; use expect_test::expect; diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs index 550ce35f12760..ec2994053877e 100644 --- a/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -9,9 +9,9 @@ //! write unit-tests (in fact, we used to do that), but that makes tests brittle //! and harder to understand. -mod mbe; -mod builtin_fn_macro; mod builtin_derive_macro; +mod builtin_fn_macro; +mod mbe; mod proc_macros; use std::{iter, ops::Range, sync}; diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 7eb2f3adddbf9..2295df16fdcc4 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -48,11 +48,11 @@ //! the result pub mod attr_resolution; -pub mod proc_macro; -pub mod diagnostics; mod collector; +pub mod diagnostics; mod mod_resolution; mod path_resolution; +pub mod proc_macro; #[cfg(test)] mod tests; diff --git a/crates/hir-expand/src/declarative.rs b/crates/hir-expand/src/declarative.rs index ff1a9625e111b..37084ee8b93c9 100644 --- a/crates/hir-expand/src/declarative.rs +++ b/crates/hir-expand/src/declarative.rs @@ -1,3 +1,4 @@ +//! Compiled declarative macro expanders (`macro_rules!`` and `macro`) use std::sync::OnceLock; use base_db::{CrateId, Edition, VersionReq}; diff --git a/crates/hir-ty/src/diagnostics.rs b/crates/hir-ty/src/diagnostics.rs index c1b3619009bd4..af4d2c9fc0461 100644 --- a/crates/hir-ty/src/diagnostics.rs +++ b/crates/hir-ty/src/diagnostics.rs @@ -1,8 +1,8 @@ //! Type inference-based diagnostics. +mod decl_check; mod expr; mod match_check; mod unsafe_check; -mod decl_check; pub use crate::diagnostics::{ decl_check::{incorrect_case, CaseType, IncorrectCase}, diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 8d180f986178d..54e91e7b29a66 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -41,10 +41,10 @@ pub mod mir; pub mod primitive; pub mod traits; -#[cfg(test)] -mod tests; #[cfg(test)] mod test_db; +#[cfg(test)] +mod tests; use std::{ collections::hash_map::Entry, diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs index 952a97e3d0f6c..494f1850b88ab 100644 --- a/crates/hir-ty/src/mir.rs +++ b/crates/hir-ty/src/mir.rs @@ -21,11 +21,11 @@ use hir_def::{ }; use la_arena::{Arena, ArenaMap, Idx, RawIdx}; +mod borrowck; mod eval; mod lower; -mod borrowck; -mod pretty; mod monomorphization; +mod pretty; pub use borrowck::{borrowck_query, BorrowckResult, MutabilityReason}; pub use eval::{ diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs index 671fd9ec3a451..9804910c878d4 100644 --- a/crates/hir-ty/src/tests.rs +++ b/crates/hir-ty/src/tests.rs @@ -1,14 +1,14 @@ -mod never_type; mod coercion; +mod diagnostics; +mod display_source_code; +mod incremental; +mod macros; +mod method_resolution; +mod never_type; +mod patterns; mod regression; mod simple; -mod patterns; mod traits; -mod method_resolution; -mod macros; -mod display_source_code; -mod incremental; -mod diagnostics; use std::{collections::HashMap, env}; diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index 1eb4903ab2033..edcf52a9b38eb 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -111,6 +111,8 @@ mod handlers { mod add_label_to_loop; mod add_lifetime_to_type; mod add_missing_impl_members; + mod add_missing_match_arms; + mod add_return_type; mod add_turbo_fish; mod apply_demorgan; mod auto_import; @@ -124,15 +126,15 @@ mod handlers { mod convert_iter_for_each_to_for; mod convert_let_else_to_match; mod convert_match_to_let_else; + mod convert_named_struct_to_tuple_struct; mod convert_nested_function_to_closure; + mod convert_to_guarded_return; mod convert_tuple_return_type_to_struct; mod convert_tuple_struct_to_named_struct; - mod convert_named_struct_to_tuple_struct; - mod convert_to_guarded_return; mod convert_two_arm_bool_match_to_matches_macro; mod convert_while_to_loop; - mod desugar_doc_comment; mod destructure_tuple_binding; + mod desugar_doc_comment; mod expand_glob_import; mod extract_expressions_from_format_string; mod extract_function; @@ -140,7 +142,6 @@ mod handlers { mod extract_struct_from_enum_variant; mod extract_type_alias; mod extract_variable; - mod add_missing_match_arms; mod fix_visibility; mod flip_binexpr; mod flip_comma; @@ -148,6 +149,7 @@ mod handlers { mod generate_constant; mod generate_default_from_enum_variant; mod generate_default_from_new; + mod generate_delegate_methods; mod generate_delegate_trait; mod generate_deref; mod generate_derive; @@ -162,62 +164,60 @@ mod handlers { mod generate_is_empty_from_len; mod generate_mut_trait_impl; mod generate_new; - mod generate_delegate_methods; mod generate_trait_from_impl; - mod add_return_type; mod inline_call; mod inline_const_as_literal; mod inline_local_variable; mod inline_macro; mod inline_type_alias; + mod into_to_qualified_from; + mod introduce_named_generic; mod introduce_named_lifetime; mod invert_if; mod merge_imports; mod merge_match_arms; + mod merge_nested_if; mod move_bounds; mod move_const_to_impl; + mod move_from_mod_rs; mod move_guard; mod move_module_to_file; mod move_to_mod_rs; - mod move_from_mod_rs; mod number_representation; mod promote_local_to_const; mod pull_assignment_up; - mod qualify_path; mod qualify_method_call; + mod qualify_path; mod raw_string; mod remove_dbg; mod remove_mut; + mod remove_parentheses; mod remove_unused_imports; mod remove_unused_param; - mod remove_parentheses; mod reorder_fields; mod reorder_impl_items; - mod replace_try_expr_with_match; + mod replace_arith_op; mod replace_derive_with_manual_impl; mod replace_if_let_with_match; mod replace_is_method_with_if_let_method; - mod replace_method_eager_lazy; - mod replace_arith_op; - mod introduce_named_generic; mod replace_let_with_if_let; + mod replace_method_eager_lazy; mod replace_named_generic_with_impl; mod replace_qualified_name_with_use; mod replace_string_with_char; + mod replace_try_expr_with_match; mod replace_turbofish_with_explicit_type; - mod split_import; - mod unmerge_match_arm; - mod unwrap_tuple; mod sort_items; + mod split_import; mod toggle_ignore; + mod unmerge_match_arm; mod unmerge_use; mod unnecessary_async; + mod unqualify_method_call; mod unwrap_block; mod unwrap_result_return_type; - mod unqualify_method_call; + mod unwrap_tuple; mod wrap_return_type_in_result; - mod into_to_qualified_from; - mod merge_nested_if; pub(crate) fn all() -> &'static [Handler] { &[ diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs index 2420945f75607..eeb3d80d07bd1 100644 --- a/crates/ide-assists/src/utils.rs +++ b/crates/ide-assists/src/utils.rs @@ -23,8 +23,8 @@ use syntax::{ use crate::assist_context::{AssistContext, SourceChangeBuilder}; -pub(crate) mod suggest_name; mod gen_trait_fn_body; +pub(crate) mod suggest_name; pub(crate) fn unwrap_trivial_block(block_expr: ast::BlockExpr) -> ast::Expr { extract_trivial_expression(&block_expr) diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index 4d3d0b4d1a6f5..ba3c0cf3fd60e 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -2,8 +2,10 @@ pub(crate) mod attribute; pub(crate) mod dot; +pub(crate) mod env_vars; pub(crate) mod expr; pub(crate) mod extern_abi; +pub(crate) mod extern_crate; pub(crate) mod field; pub(crate) mod flyimport; pub(crate) mod fn_param; @@ -19,8 +21,6 @@ pub(crate) mod snippet; pub(crate) mod r#type; pub(crate) mod use_; pub(crate) mod vis; -pub(crate) mod env_vars; -pub(crate) mod extern_crate; use std::iter; diff --git a/crates/ide-completion/src/completions/attribute.rs b/crates/ide-completion/src/completions/attribute.rs index 8f7c3b5070bfd..a7a6cdebd361e 100644 --- a/crates/ide-completion/src/completions/attribute.rs +++ b/crates/ide-completion/src/completions/attribute.rs @@ -25,8 +25,8 @@ use crate::{ mod cfg; mod derive; mod lint; -mod repr; mod macro_use; +mod repr; pub(crate) use self::derive::complete_derive_path; diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs index 6a98e109f6dff..d26b6f431b5b4 100644 --- a/crates/ide-completion/src/lib.rs +++ b/crates/ide-completion/src/lib.rs @@ -8,9 +8,9 @@ mod context; mod item; mod render; +mod snippet; #[cfg(test)] mod tests; -mod snippet; use ide_db::{ base_db::FilePosition, diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index 6fd988bfc0fc6..ad26280ae748f 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -1,14 +1,14 @@ //! `render` module provides utilities for rendering completion suggestions //! into code pieces that will be presented to user. -pub(crate) mod macro_; -pub(crate) mod function; pub(crate) mod const_; +pub(crate) mod function; +pub(crate) mod literal; +pub(crate) mod macro_; pub(crate) mod pattern; pub(crate) mod type_alias; -pub(crate) mod variant; pub(crate) mod union_literal; -pub(crate) mod literal; +pub(crate) mod variant; use hir::{AsAssocItem, HasAttrs, HirDisplay, ModuleDef, ScopeDef, Type}; use ide_db::{ diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs index f13754e2ded05..c421be51a0d07 100644 --- a/crates/ide-completion/src/tests.rs +++ b/crates/ide-completion/src/tests.rs @@ -12,8 +12,8 @@ mod attribute; mod expression; mod flyimport; mod fn_param; -mod item_list; mod item; +mod item_list; mod pattern; mod predicate; mod proc_macros; diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index 1cc1e36329909..2881748dd477e 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -9,6 +9,7 @@ mod apply_change; pub mod active_parameter; pub mod assists; pub mod defs; +pub mod documentation; pub mod famous_defs; pub mod helpers; pub mod items_locator; @@ -22,7 +23,6 @@ pub mod symbol_index; pub mod traits; pub mod ty_filter; pub mod use_trivial_constructor; -pub mod documentation; pub mod imports { pub mod import_assets; @@ -35,10 +35,10 @@ pub mod generated { } pub mod syntax_helpers { - pub mod node_ext; - pub mod insert_whitespace_into_node; pub mod format_string; pub mod format_string_exprs; + pub mod insert_whitespace_into_node; + pub mod node_ext; pub use parser::LexedStr; } @@ -414,6 +414,6 @@ impl SnippetCap { #[cfg(test)] mod tests { - mod sourcegen_lints; mod line_index; + mod sourcegen_lints; } diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 7743b060c8626..f35fc5b533a66 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -44,30 +44,30 @@ mod handlers { pub(crate) mod private_assoc_item; pub(crate) mod private_field; pub(crate) mod replace_filter_map_next_with_find_map; - pub(crate) mod trait_impl_orphan; pub(crate) mod trait_impl_incorrect_safety; pub(crate) mod trait_impl_missing_assoc_item; + pub(crate) mod trait_impl_orphan; pub(crate) mod trait_impl_redundant_assoc_item; - pub(crate) mod typed_hole; pub(crate) mod type_mismatch; + pub(crate) mod typed_hole; + pub(crate) mod undeclared_label; pub(crate) mod unimplemented_builtin_macro; + pub(crate) mod unreachable_label; pub(crate) mod unresolved_assoc_item; pub(crate) mod unresolved_extern_crate; pub(crate) mod unresolved_field; - pub(crate) mod unresolved_method; pub(crate) mod unresolved_import; pub(crate) mod unresolved_macro_call; + pub(crate) mod unresolved_method; pub(crate) mod unresolved_module; pub(crate) mod unresolved_proc_macro; - pub(crate) mod undeclared_label; - pub(crate) mod unreachable_label; pub(crate) mod unused_variables; // The handlers below are unusual, the implement the diagnostics as well. pub(crate) mod field_shorthand; - pub(crate) mod useless_braces; - pub(crate) mod unlinked_file; pub(crate) mod json_is_not_rust; + pub(crate) mod unlinked_file; + pub(crate) mod useless_braces; } #[cfg(test)] diff --git a/crates/ide-ssr/src/lib.rs b/crates/ide-ssr/src/lib.rs index d756e7a63eb9b..b5bf510aeed48 100644 --- a/crates/ide-ssr/src/lib.rs +++ b/crates/ide-ssr/src/lib.rs @@ -69,11 +69,11 @@ // // foo($a, $b) ==>> ($a).foo($b) // ``` +mod fragments; mod from_comment; mod matching; mod nester; mod parsing; -mod fragments; mod replacing; mod resolving; mod search; diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 79fff15f050b8..46e5901852ae5 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -25,13 +25,13 @@ mod bind_pat; mod binding_mode; mod chaining; mod closing_brace; -mod closure_ret; mod closure_captures; +mod closure_ret; mod discriminant; mod fn_lifetime_fn; +mod implicit_drop; mod implicit_static; mod param_name; -mod implicit_drop; mod range_exclusive; #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index a50aa2e6dfbc6..e9f42d478554f 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -21,24 +21,25 @@ macro_rules! eprintln { mod fixture; mod markup; -mod prime_caches; mod navigation_target; +mod prime_caches; mod annotations; mod call_hierarchy; -mod signature_help; mod doc_links; -mod highlight_related; mod expand_macro; mod extend_selection; +mod fetch_crates; mod file_structure; mod folding_ranges; mod goto_declaration; mod goto_definition; mod goto_implementation; mod goto_type_definition; +mod highlight_related; mod hover; mod inlay_hints; +mod interpret_function; mod join_lines; mod markdown_remove; mod matching_brace; @@ -48,6 +49,8 @@ mod parent_module; mod references; mod rename; mod runnables; +mod shuffle_crate_graph; +mod signature_help; mod ssr; mod static_index; mod status; @@ -56,12 +59,9 @@ mod syntax_tree; mod typing; mod view_crate_graph; mod view_hir; -mod view_mir; -mod interpret_function; mod view_item_tree; -mod shuffle_crate_graph; -mod fetch_crates; mod view_memory_layout; +mod view_mir; use std::ffi::OsStr; diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 3607c486d7d39..8c6f5e2e9cb50 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -3,11 +3,11 @@ pub(crate) mod tags; mod highlights; mod injector; -mod highlight; +mod escape; mod format; -mod macro_; +mod highlight; mod inject; -mod escape; +mod macro_; mod html; #[cfg(test)] diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index f968a89a441f2..62fdce36892f2 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs @@ -8,11 +8,11 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod parser; mod expander; +mod parser; mod syntax_bridge; -mod tt_iter; mod to_parser_input; +mod tt_iter; #[cfg(test)] mod benchmark; diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs index 19da297b58ccc..53fda3ae4fd26 100644 --- a/crates/parser/src/grammar.rs +++ b/crates/parser/src/grammar.rs @@ -30,12 +30,12 @@ mod attributes; mod expressions; +mod generic_args; +mod generic_params; mod items; mod params; mod paths; mod patterns; -mod generic_args; -mod generic_params; mod types; use crate::{ diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs index caf2a005a7d8b..243a219525a8a 100644 --- a/crates/parser/src/grammar/items.rs +++ b/crates/parser/src/grammar/items.rs @@ -1,5 +1,5 @@ -mod consts; mod adt; +mod consts; mod traits; mod use_item; diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index ed0aec3cab32a..3ca285e787e81 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -26,15 +26,15 @@ extern crate ra_ap_rustc_lexer as rustc_lexer; #[cfg(feature = "in-rust-tree")] extern crate rustc_lexer; -mod lexed_str; -mod token_set; -mod syntax_kind; mod event; -mod parser; mod grammar; mod input; +mod lexed_str; mod output; +mod parser; mod shortcuts; +mod syntax_kind; +mod token_set; #[cfg(test)] mod tests; diff --git a/crates/parser/src/tests.rs b/crates/parser/src/tests.rs index 2fec765bd7871..c65219b28dce6 100644 --- a/crates/parser/src/tests.rs +++ b/crates/parser/src/tests.rs @@ -1,6 +1,6 @@ +mod prefix_entries; mod sourcegen_inline_tests; mod top_entries; -mod prefix_entries; use std::{ fmt::Write, diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs index 67b9f57a1636c..460a96c07f367 100644 --- a/crates/proc-macro-srv/src/lib.rs +++ b/crates/proc-macro-srv/src/lib.rs @@ -21,8 +21,8 @@ extern crate proc_macro; extern crate rustc_driver as _; mod dylib; -mod server; mod proc_macros; +mod server; use std::{ collections::{hash_map::Entry, HashMap}, diff --git a/crates/proc-macro-srv/src/server.rs b/crates/proc-macro-srv/src/server.rs index 1854322ddb5c3..ff8fd295d884a 100644 --- a/crates/proc-macro-srv/src/server.rs +++ b/crates/proc-macro-srv/src/server.rs @@ -13,9 +13,9 @@ use proc_macro::bridge; mod token_stream; pub use token_stream::TokenStream; -pub mod token_id; pub mod rust_analyzer_span; mod symbol; +pub mod token_id; pub use symbol::*; use tt::Spacing; diff --git a/crates/profile/src/lib.rs b/crates/profile/src/lib.rs index fdd724e2aab45..d86aa0c414406 100644 --- a/crates/profile/src/lib.rs +++ b/crates/profile/src/lib.rs @@ -2,11 +2,11 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod stop_watch; -mod memory_usage; #[cfg(feature = "cpu_profiler")] mod google_cpu_profiler; mod hprof; +mod memory_usage; +mod stop_watch; mod tree; use std::cell::RefCell; diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs index 5f9b708289d16..5114c9c016ded 100644 --- a/crates/project-model/src/lib.rs +++ b/crates/project-model/src/lib.rs @@ -17,15 +17,15 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod manifest_path; +mod build_scripts; mod cargo_workspace; mod cfg_flag; +mod manifest_path; mod project_json; -mod sysroot; -mod workspace; mod rustc_cfg; -mod build_scripts; +mod sysroot; pub mod target_data_layout; +mod workspace; #[cfg(test)] mod tests; diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs index de00c4192b46a..00670f2cb4c8d 100644 --- a/crates/rust-analyzer/src/cli.rs +++ b/crates/rust-analyzer/src/cli.rs @@ -1,16 +1,16 @@ //! Various batch processing tasks, intended primarily for debugging. -pub mod flags; -mod parse; -mod symbols; -mod highlight; mod analysis_stats; mod diagnostics; -mod ssr; +pub mod flags; +mod highlight; mod lsif; -mod scip; +mod parse; mod run_tests; mod rustc_tests; +mod scip; +mod ssr; +mod symbols; mod progress_report; diff --git a/crates/rust-analyzer/src/lsp.rs b/crates/rust-analyzer/src/lsp.rs index ac7e1a95e622f..9e0d42faed43f 100644 --- a/crates/rust-analyzer/src/lsp.rs +++ b/crates/rust-analyzer/src/lsp.rs @@ -2,11 +2,11 @@ use core::fmt; -pub(crate) mod utils; -pub(crate) mod semantic_tokens; pub mod ext; pub(crate) mod from_proto; +pub(crate) mod semantic_tokens; pub(crate) mod to_proto; +pub(crate) mod utils; #[derive(Debug)] pub(crate) struct LspError { diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index cd5285295a2f4..07b7827228182 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs @@ -6,13 +6,13 @@ use std::io as sio; use std::process::Command; use std::{cmp::Ordering, ops, time::Instant}; +pub mod anymap; mod macros; -pub mod process; -pub mod panic_context; pub mod non_empty_vec; +pub mod panic_context; +pub mod process; pub mod rand; pub mod thread; -pub mod anymap; pub use always_assert::{always, never}; pub use itertools; diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index cc90d2dd1d55b..e9ab7a4320b0c 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs @@ -1,15 +1,15 @@ //! Abstract Syntax Tree, layered on top of untyped `SyntaxNode`s -mod generated; -mod traits; -mod token_ext; -mod node_ext; -mod expr_ext; -mod operators; pub mod edit; pub mod edit_in_place; +mod expr_ext; +mod generated; pub mod make; +mod node_ext; +mod operators; pub mod prec; +mod token_ext; +mod traits; use std::marker::PhantomData; diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index 21ed1310f56b7..62a0261d7a459 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -32,22 +32,22 @@ macro_rules! eprintln { ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; } -mod syntax_node; -mod syntax_error; mod parsing; -mod validation; mod ptr; -mod token_text; +mod syntax_error; +mod syntax_node; #[cfg(test)] mod tests; +mod token_text; +mod validation; pub mod algo; pub mod ast; #[doc(hidden)] pub mod fuzz; -pub mod utils; -pub mod ted; pub mod hacks; +pub mod ted; +pub mod utils; use std::marker::PhantomData; diff --git a/lib/lsp-server/src/lib.rs b/lib/lsp-server/src/lib.rs index f717f8e0d4ba6..e476f8c2d1345 100644 --- a/lib/lsp-server/src/lib.rs +++ b/lib/lsp-server/src/lib.rs @@ -6,11 +6,11 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod msg; -mod stdio; mod error; -mod socket; +mod msg; mod req_queue; +mod socket; +mod stdio; use std::{ io, diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 49f8ae79baf0e..2d40ceb737dff 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -12,11 +12,11 @@ mod flags; -mod install; -mod release; mod dist; -mod publish; +mod install; mod metrics; +mod publish; +mod release; use anyhow::bail; use std::{ From da798bccf71db9db6e778d023c25dd2077f15181 Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sat, 20 Jan 2024 18:33:44 +0300 Subject: [PATCH 078/246] make `ast::UseTree::wrap_in_tree_list` more robust --- crates/syntax/src/ast/edit_in_place.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index 247dfe0b459a5..18cda7dde7353 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs @@ -538,9 +538,13 @@ impl ast::UseTree { /// `foo::bar` -> `{foo::bar}` /// /// `{foo::bar}` -> `{foo::bar}` - pub fn wrap_in_tree_list(&self) { - if self.path().is_none() { - return; + pub fn wrap_in_tree_list(&self) -> Option<()> { + if self.use_tree_list().is_some() + && self.path().is_none() + && self.star_token().is_none() + && self.rename().is_none() + { + return None; } let subtree = self.clone_subtree().clone_for_update(); ted::remove_all_iter(self.syntax().children_with_tokens()); @@ -548,6 +552,7 @@ impl ast::UseTree { self.syntax(), make::use_tree_list(once(subtree)).clone_for_update().syntax(), ); + Some(()) } } From 57934ac47a4e0a14237103a1745c49187af7f048 Mon Sep 17 00:00:00 2001 From: Alain Siegrist Date: Sun, 8 Oct 2023 23:15:04 +0200 Subject: [PATCH 079/246] Add postfix completion for let else --- .../ide-completion/src/completions/postfix.rs | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs index a846ffe10e636..e07154714145b 100644 --- a/crates/ide-completion/src/completions/postfix.rs +++ b/crates/ide-completion/src/completions/postfix.rs @@ -75,6 +75,11 @@ pub(crate) fn complete_postfix( let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty.strip_references()); if let Some(try_enum) = &try_enum { + let in_loop = dot_receiver + .syntax() + .ancestors() + .any(|n| matches!(n.kind(), WHILE_EXPR | LOOP_EXPR | FOR_EXPR)); + match try_enum { TryEnum::Result => { postfix_snippet( @@ -84,6 +89,17 @@ pub(crate) fn complete_postfix( ) .add_to(acc, ctx.db); + postfix_snippet( + "lete", + "let Ok else {}", + &if in_loop { + format!("let Ok($1) = {receiver_text} else {{\n ${{2|continue,break,return|}};\n}};\n$0") + } else { + format!("let Ok($1) = {receiver_text} else {{\n return;\n}};\n$0") + }, + ) + .add_to(acc, ctx.db); + postfix_snippet( "while", "while let Ok {}", @@ -99,6 +115,17 @@ pub(crate) fn complete_postfix( ) .add_to(acc, ctx.db); + postfix_snippet( + "lete", + "let Some else {}", + &if in_loop { + format!("let Some($1) = {receiver_text} else {{\n ${{2|continue,break,return|}};\n}};\n$0") + } else { + format!("let Some($1) = {receiver_text} else {{\n return;\n}};\n$0") + }, + ) + .add_to(acc, ctx.db); + postfix_snippet( "while", "while let Some {}", @@ -469,6 +496,56 @@ fn main() { ); } + #[test] + fn option_letelse() { + check_edit( + "lete", + r#" +//- minicore: option +fn main() { + let bar = Some(true); + bar.$0 +} +"#, + r#" +fn main() { + let bar = Some(true); + let Some($1) = bar else { + return; +}; +$0 +} +"#, + ); + } + + #[test] + fn option_letelse_loop() { + check_edit( + "lete", + r#" +//- minicore: option +fn main() { + let bar = Some(true); + loop { + bar.$0 + } +} +"#, + r#" +fn main() { + let bar = Some(true); + loop { + let Some($1) = bar else { + ${2|continue,break,return|}; +}; +$0 + } +} +"#, + ); + } + #[test] fn result_match() { check_edit( From 51d57b9bb62df7caee53e1a378191434590e765a Mon Sep 17 00:00:00 2001 From: Alain Siegrist Date: Mon, 9 Oct 2023 18:21:33 +0200 Subject: [PATCH 080/246] Make return a snippet --- crates/ide-completion/src/completions/postfix.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs index e07154714145b..e062578b2b8be 100644 --- a/crates/ide-completion/src/completions/postfix.rs +++ b/crates/ide-completion/src/completions/postfix.rs @@ -95,7 +95,7 @@ pub(crate) fn complete_postfix( &if in_loop { format!("let Ok($1) = {receiver_text} else {{\n ${{2|continue,break,return|}};\n}};\n$0") } else { - format!("let Ok($1) = {receiver_text} else {{\n return;\n}};\n$0") + format!("let Ok($1) = {receiver_text} else {{\n ${{2:return}};\n}};\n$0") }, ) .add_to(acc, ctx.db); @@ -121,7 +121,7 @@ pub(crate) fn complete_postfix( &if in_loop { format!("let Some($1) = {receiver_text} else {{\n ${{2|continue,break,return|}};\n}};\n$0") } else { - format!("let Some($1) = {receiver_text} else {{\n return;\n}};\n$0") + format!("let Some($1) = {receiver_text} else {{\n ${{2:return}};\n}};\n$0") }, ) .add_to(acc, ctx.db); @@ -511,7 +511,7 @@ fn main() { fn main() { let bar = Some(true); let Some($1) = bar else { - return; + ${2:return}; }; $0 } From 7ec32d091a05b9cfc3a9a8fb0f14be423e455f41 Mon Sep 17 00:00:00 2001 From: Alain Siegrist Date: Sat, 27 Jan 2024 14:28:50 +0100 Subject: [PATCH 081/246] Remove letelse control flow snippets --- .../ide-completion/src/completions/postfix.rs | 46 ++----------------- 1 file changed, 3 insertions(+), 43 deletions(-) diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs index e062578b2b8be..af83d4104f76e 100644 --- a/crates/ide-completion/src/completions/postfix.rs +++ b/crates/ide-completion/src/completions/postfix.rs @@ -75,11 +75,6 @@ pub(crate) fn complete_postfix( let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty.strip_references()); if let Some(try_enum) = &try_enum { - let in_loop = dot_receiver - .syntax() - .ancestors() - .any(|n| matches!(n.kind(), WHILE_EXPR | LOOP_EXPR | FOR_EXPR)); - match try_enum { TryEnum::Result => { postfix_snippet( @@ -92,11 +87,7 @@ pub(crate) fn complete_postfix( postfix_snippet( "lete", "let Ok else {}", - &if in_loop { - format!("let Ok($1) = {receiver_text} else {{\n ${{2|continue,break,return|}};\n}};\n$0") - } else { - format!("let Ok($1) = {receiver_text} else {{\n ${{2:return}};\n}};\n$0") - }, + &format!("let Ok($1) = {receiver_text} else {{\n $2\n}};\n$0"), ) .add_to(acc, ctx.db); @@ -118,11 +109,7 @@ pub(crate) fn complete_postfix( postfix_snippet( "lete", "let Some else {}", - &if in_loop { - format!("let Some($1) = {receiver_text} else {{\n ${{2|continue,break,return|}};\n}};\n$0") - } else { - format!("let Some($1) = {receiver_text} else {{\n ${{2:return}};\n}};\n$0") - }, + &format!("let Some($1) = {receiver_text} else {{\n $2\n}};\n$0"), ) .add_to(acc, ctx.db); @@ -511,36 +498,9 @@ fn main() { fn main() { let bar = Some(true); let Some($1) = bar else { - ${2:return}; -}; -$0 -} -"#, - ); - } - - #[test] - fn option_letelse_loop() { - check_edit( - "lete", - r#" -//- minicore: option -fn main() { - let bar = Some(true); - loop { - bar.$0 - } -} -"#, - r#" -fn main() { - let bar = Some(true); - loop { - let Some($1) = bar else { - ${2|continue,break,return|}; + $2 }; $0 - } } "#, ); From b22e772cab8ea0673f25fdacf3e1af472b242818 Mon Sep 17 00:00:00 2001 From: YangzeLuo Date: Sat, 27 Jan 2024 23:36:01 +0800 Subject: [PATCH 082/246] feat: Support for GOTO def from *inside* files included with include! macro --- Cargo.lock | 1 + crates/hir-def/src/db.rs | 19 +++++- crates/hir-def/src/item_scope.rs | 6 ++ crates/hir-expand/src/lib.rs | 18 ++++++ crates/hir/Cargo.toml | 3 +- crates/hir/src/semantics.rs | 101 +++++++++++++++++++++++++++--- crates/ide/src/goto_definition.rs | 27 ++++++++ 7 files changed, 163 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a743d1c870a5a..b626a16947bec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -483,6 +483,7 @@ dependencies = [ "profile", "rustc-hash", "smallvec", + "span", "stdx", "syntax", "triomphe", diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index c9789ceb207c5..f773fe4c6abfc 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -1,9 +1,10 @@ //! Defines database & queries for name resolution. -use base_db::{salsa, CrateId, SourceDatabase, Upcast}; +use base_db::{salsa, CrateId, FileId, SourceDatabase, Upcast}; use either::Either; use hir_expand::{db::ExpandDatabase, HirFileId, MacroDefId}; use intern::Interned; use la_arena::ArenaMap; +use span::MacroCallId; use syntax::{ast, AstPtr}; use triomphe::Arc; @@ -234,6 +235,22 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Option>; fn crate_supports_no_std(&self, crate_id: CrateId) -> bool; + + fn include_macro_invoc(&self, crate_id: CrateId) -> Vec<(MacroCallId, FileId)>; +} + +// return: macro call id and include file id +fn include_macro_invoc(db: &dyn DefDatabase, krate: CrateId) -> Vec<(MacroCallId, FileId)> { + db.crate_def_map(krate) + .modules + .values() + .flat_map(|m| m.scope.iter_macro_invoc()) + .filter_map(|invoc| { + db.lookup_intern_macro_call(*invoc.1) + .include_file_id(db.upcast(), *invoc.1) + .map(|x| (*invoc.1, x)) + }) + .collect() } fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc { diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 168ee4acffbef..6237ea7353fd2 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -336,6 +336,12 @@ impl ItemScope { pub(crate) fn macro_invoc(&self, call: AstId) -> Option { self.macro_invocations.get(&call).copied() } + + pub(crate) fn iter_macro_invoc( + &self, + ) -> impl Iterator, &MacroCallId)> { + self.macro_invocations.iter() + } } impl ItemScope { diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index bd216ccca8239..b7d59791b24ae 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -520,6 +520,24 @@ impl MacroCallLoc { } } } + + pub fn include_file_id( + &self, + db: &dyn ExpandDatabase, + macro_call_id: MacroCallId, + ) -> Option { + if self.def.is_include() { + if let Some(eager) = &self.eager { + if let Ok(it) = + builtin_fn_macro::include_input_to_file_id(db, macro_call_id, &eager.arg) + { + return Some(it); + } + } + } + + None + } } impl MacroCallKind { diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml index e4e4bcea6108d..668a14cd55e49 100644 --- a/crates/hir/Cargo.toml +++ b/crates/hir/Cargo.toml @@ -30,9 +30,10 @@ profile.workspace = true stdx.workspace = true syntax.workspace = true tt.workspace = true +span.workspace = true [features] in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index fdb94a6d5a74d..46f3997620abf 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -20,11 +20,12 @@ use hir_def::{ }; use hir_expand::{ attrs::collect_attrs, db::ExpandDatabase, files::InRealFile, name::AsName, ExpansionInfo, - InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, + HirFileIdExt, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, }; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; use smallvec::{smallvec, SmallVec}; +use span::Span; use stdx::TupleExt; use syntax::{ algo::skip_trivia_token, @@ -607,22 +608,97 @@ impl<'db> SemanticsImpl<'db> { res } - fn descend_into_macros_impl( + // return: + // SourceAnalyzer(file_id that original call include!) + // macro file id + // token in include! macro mapped from token in params + // span for the mapped token + fn is_from_include_file( &self, token: SyntaxToken, + ) -> Option<(SourceAnalyzer, HirFileId, SyntaxToken, Span)> { + let parent = token.parent()?; + let file_id = self.find_file(&parent).file_id.file_id()?; + + // iterate related crates and find all include! invocations that include_file_id matches + for (invoc, _) in self + .db + .relevant_crates(file_id) + .iter() + .flat_map(|krate| self.db.include_macro_invoc(*krate)) + .filter(|(_, include_file_id)| *include_file_id == file_id) + { + // find file_id which original calls include! + let Some(callnode) = invoc.as_file().original_call_node(self.db.upcast()) else { + continue; + }; + + // call .parse to avoid panic in .find_file + let _ = self.parse(callnode.file_id); + let Some(sa) = self.analyze_no_infer(&callnode.value) else { continue }; + + let expinfo = invoc.as_macro_file().expansion_info(self.db.upcast()); + { + let InMacroFile { file_id, value } = expinfo.expanded(); + self.cache(value, file_id.into()); + } + + // map token to the corresponding span in include! macro file + let Some((_, span)) = + expinfo.exp_map.iter().find(|(_, x)| x.range == token.text_range()) + else { + continue; + }; + + // get mapped token in the include! macro file + let Some(InMacroFile { file_id: _, value: mapped_tokens }) = + expinfo.map_range_down(span) + else { + continue; + }; + + // if we find one, then return + if let Some(t) = mapped_tokens.into_iter().next() { + return Some((sa, invoc.as_file(), t, span)); + }; + } + + None + } + + fn descend_into_macros_impl( + &self, + mut token: SyntaxToken, f: &mut dyn FnMut(InFile) -> ControlFlow<()>, ) { let _p = profile::span("descend_into_macros"); + + let mut include_macro_file_id_and_span = None; + let sa = match token.parent().and_then(|parent| self.analyze_no_infer(&parent)) { Some(it) => it, - None => return, + None => { + // if we cannot find a source analyzer for this token, then we try to find out whether this file is included from other file + let Some((it, macro_file_id, mapped_token, s)) = self.is_from_include_file(token) + else { + return; + }; + + include_macro_file_id_and_span = Some((macro_file_id, s)); + token = mapped_token; + it + } }; - let span = match sa.file_id.file_id() { - Some(file_id) => self.db.real_span_map(file_id).span_for_range(token.text_range()), - None => { - stdx::never!(); - return; + let span = if let Some((_, s)) = include_macro_file_id_and_span { + s + } else { + match sa.file_id.file_id() { + Some(file_id) => self.db.real_span_map(file_id).span_for_range(token.text_range()), + None => { + stdx::never!(); + return; + } } }; @@ -630,6 +706,13 @@ impl<'db> SemanticsImpl<'db> { let mut mcache = self.macro_call_cache.borrow_mut(); let def_map = sa.resolver.def_map(); + let mut stack: Vec<(_, SmallVec<[_; 2]>)> = + if let Some((macro_file_id, _)) = include_macro_file_id_and_span { + vec![(macro_file_id, smallvec![token])] + } else { + vec![(sa.file_id, smallvec![token])] + }; + let mut process_expansion_for_token = |stack: &mut Vec<_>, macro_file| { let expansion_info = cache .entry(macro_file) @@ -651,8 +734,6 @@ impl<'db> SemanticsImpl<'db> { res }; - let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![(sa.file_id, smallvec![token])]; - while let Some((file_id, mut tokens)) = stack.pop() { while let Some(token) = tokens.pop() { let was_not_remapped = (|| { diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index d64295bdd6907..073e0036182c5 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -226,6 +226,7 @@ mod tests { .map(|(FileRange { file_id, range }, _)| FileRange { file_id, range }) .sorted_by_key(cmp) .collect::>(); + assert_eq!(expected, navs); } @@ -236,6 +237,32 @@ mod tests { assert!(navs.is_empty(), "didn't expect this to resolve anywhere: {navs:?}") } + #[test] + fn goto_def_in_included_file() { + check( + r#" +//- /main.rs +#[rustc_builtin_macro] +macro_rules! include {} + +include!("a.rs"); + +fn main() { + foo(); +} + +//- /a.rs +fn func_in_include() { + //^^^^^^^^^^^^^^^ +} + +fn foo() { + func_in_include$0(); +} +"#, + ); + } + #[test] fn goto_def_if_items_same_name() { check( From 4c010259ef3c9eec239f5006dfdeffc73548cf07 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 27 Jan 2024 18:55:21 +0000 Subject: [PATCH 083/246] std: thread_local::register_dtor fix proposal for FreeBSD. following-up 5d3d347 commit, rust started to spin __cxa_thread_call_dtors warnings even without any TLS usage. using instead home made TLS destructor handler `register_dtor_fallback`. close #120413 --- library/std/src/sys/pal/unix/thread_local_dtor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/pal/unix/thread_local_dtor.rs b/library/std/src/sys/pal/unix/thread_local_dtor.rs index 7e19e6eb9ebbd..4bf8f20670dbe 100644 --- a/library/std/src/sys/pal/unix/thread_local_dtor.rs +++ b/library/std/src/sys/pal/unix/thread_local_dtor.rs @@ -18,7 +18,6 @@ target_os = "fuchsia", target_os = "redox", target_os = "hurd", - target_os = "freebsd", target_os = "netbsd", target_os = "dragonfly" ))] @@ -118,7 +117,8 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { target_os = "vxworks", target_os = "horizon", target_os = "emscripten", - target_os = "aix" + target_os = "aix", + target_os = "freebsd", ))] #[cfg_attr(target_family = "wasm", allow(unused))] // might remain unused depending on target details (e.g. wasm32-unknown-emscripten) pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { From 8fab92feb270f1725f25dc3b7529f8d3555eb404 Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sat, 20 Jan 2024 15:37:46 +0300 Subject: [PATCH 084/246] normalize use trees when merging imports --- .../ide-assists/src/handlers/merge_imports.rs | 24 +- crates/ide-completion/src/tests/flyimport.rs | 2 +- crates/ide-db/src/imports/insert_use.rs | 10 + crates/ide-db/src/imports/insert_use/tests.rs | 22 +- crates/ide-db/src/imports/merge_imports.rs | 318 +++++++++++++++++- 5 files changed, 350 insertions(+), 26 deletions(-) diff --git a/crates/ide-assists/src/handlers/merge_imports.rs b/crates/ide-assists/src/handlers/merge_imports.rs index 2beab26dce738..02dbde803e5b2 100644 --- a/crates/ide-assists/src/handlers/merge_imports.rs +++ b/crates/ide-assists/src/handlers/merge_imports.rs @@ -201,7 +201,7 @@ use std::fmt$0::{Display, Debug}; use std::fmt::{Display, Debug}; ", r" -use std::fmt::{Display, Debug}; +use std::fmt::{Debug, Display}; ", ); @@ -214,7 +214,7 @@ use std::fmt::{Display, Debug}; check_assist_import_one_variations!( "std::fmt$0::{Display, Debug}", "std::fmt::{Display, Debug}", - "use {std::fmt::{Display, Debug}};" + "use {std::fmt::{Debug, Display}};" ); } @@ -419,13 +419,13 @@ use std$0::{fmt::{Write, Display}}; use std::{fmt::{self, Debug}}; ", r" -use std::{fmt::{self, Debug, Display, Write}}; +use std::fmt::{self, Debug, Display, Write}; ", ); check_assist_import_one_variations!( "std$0::{fmt::{Write, Display}}", "std::{fmt::{self, Debug}}", - "use {std::{fmt::{self, Debug, Display, Write}}};" + "use {std::fmt::{self, Debug, Display, Write}};" ); } @@ -438,13 +438,13 @@ use std$0::{fmt::{self, Debug}}; use std::{fmt::{Write, Display}}; ", r" -use std::{fmt::{self, Debug, Display, Write}}; +use std::fmt::{self, Debug, Display, Write}; ", ); check_assist_import_one_variations!( "std$0::{fmt::{self, Debug}}", "std::{fmt::{Write, Display}}", - "use {std::{fmt::{self, Debug, Display, Write}}};" + "use {std::fmt::{self, Debug, Display, Write}};" ); } @@ -470,13 +470,13 @@ use foo::$0{bar::{self}}; use foo::{bar}; ", r" -use foo::{bar::{self}}; +use foo::bar; ", ); check_assist_import_one_variations!( "foo::$0{bar::{self}}", "foo::{bar}", - "use {foo::{bar::{self}}};" + "use {foo::bar};" ); } @@ -489,13 +489,13 @@ use foo::$0{bar}; use foo::{bar::{self}}; ", r" -use foo::{bar::{self}}; +use foo::bar; ", ); check_assist_import_one_variations!( "foo::$0{bar}", "foo::{bar::{self}}", - "use {foo::{bar::{self}}};" + "use {foo::bar};" ); } @@ -508,13 +508,13 @@ use std$0::{fmt::*}; use std::{fmt::{self, Display}}; ", r" -use std::{fmt::{self, Display, *}}; +use std::fmt::{self, Display, *}; ", ); check_assist_import_one_variations!( "std$0::{fmt::*}", "std::{fmt::{self, Display}}", - "use {std::{fmt::{self, Display, *}}};" + "use {std::fmt::{self, Display, *}};" ); } diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs index 1af16ef857d03..eaa1bebc03c7e 100644 --- a/crates/ide-completion/src/tests/flyimport.rs +++ b/crates/ide-completion/src/tests/flyimport.rs @@ -106,7 +106,7 @@ fn main() { } "#, r#" -use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}}; +use dep::{some_module::{SecondStruct, ThirdStruct}, FirstStruct}; fn main() { ThirdStruct diff --git a/crates/ide-db/src/imports/insert_use.rs b/crates/ide-db/src/imports/insert_use.rs index 09b4a1c1baac0..5f5ec44687096 100644 --- a/crates/ide-db/src/imports/insert_use.rs +++ b/crates/ide-db/src/imports/insert_use.rs @@ -17,6 +17,7 @@ use syntax::{ use crate::{ imports::merge_imports::{ common_prefix, eq_attrs, eq_visibility, try_merge_imports, use_tree_cmp, MergeBehavior, + NormalizationStyle, }, RootDatabase, }; @@ -40,6 +41,15 @@ pub enum ImportGranularity { One, } +impl From for NormalizationStyle { + fn from(granularity: ImportGranularity) -> Self { + match granularity { + ImportGranularity::One => NormalizationStyle::One, + _ => NormalizationStyle::Default, + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct InsertUseConfig { pub granularity: ImportGranularity, diff --git a/crates/ide-db/src/imports/insert_use/tests.rs b/crates/ide-db/src/imports/insert_use/tests.rs index 2ed6069887138..6b0fecae26758 100644 --- a/crates/ide-db/src/imports/insert_use/tests.rs +++ b/crates/ide-db/src/imports/insert_use/tests.rs @@ -635,7 +635,7 @@ use std::io;", check_one( "std::io", r"use {std::fmt::{Result, Display}};", - r"use {std::{fmt::{Result, Display}, io}};", + r"use {std::{fmt::{Display, Result}, io}};", ); } @@ -650,12 +650,12 @@ fn merge_groups_full() { check_crate( "std::io", r"use std::fmt::{Result, Display};", - r"use std::{fmt::{Result, Display}, io};", + r"use std::{fmt::{Display, Result}, io};", ); check_one( "std::io", r"use {std::fmt::{Result, Display}};", - r"use {std::{fmt::{Result, Display}, io}};", + r"use {std::{fmt::{Display, Result}, io}};", ); } @@ -749,12 +749,12 @@ fn merge_groups_full_nested_deep() { check_crate( "std::foo::bar::quux::Baz", r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};", - r"use std::foo::bar::{Qux, quux::{Baz, Fez, Fizz}};", + r"use std::foo::bar::{quux::{Baz, Fez, Fizz}, Qux};", ); check_one( "std::foo::bar::quux::Baz", r"use {std::foo::bar::{Qux, quux::{Fez, Fizz}}};", - r"use {std::foo::bar::{Qux, quux::{Baz, Fez, Fizz}}};", + r"use {std::foo::bar::{quux::{Baz, Fez, Fizz}, Qux}};", ); } @@ -763,7 +763,7 @@ fn merge_groups_full_nested_long() { check_crate( "std::foo::bar::Baz", r"use std::{foo::bar::Qux};", - r"use std::{foo::bar::{Baz, Qux}};", + r"use std::foo::bar::{Baz, Qux};", ); } @@ -772,12 +772,12 @@ fn merge_groups_last_nested_long() { check_crate( "std::foo::bar::Baz", r"use std::{foo::bar::Qux};", - r"use std::{foo::bar::{Baz, Qux}};", + r"use std::foo::bar::{Baz, Qux};", ); check_one( "std::foo::bar::Baz", r"use {std::{foo::bar::Qux}};", - r"use {std::{foo::bar::{Baz, Qux}}};", + r"use {std::foo::bar::{Baz, Qux}};", ); } @@ -898,7 +898,7 @@ fn merge_glob() { r" use syntax::{SyntaxKind::*};", r" -use syntax::{SyntaxKind::{self, *}};", +use syntax::SyntaxKind::{self, *};", ) } @@ -907,7 +907,7 @@ fn merge_glob_nested() { check_crate( "foo::bar::quux::Fez", r"use foo::bar::{Baz, quux::*};", - r"use foo::bar::{Baz, quux::{Fez, *}};", + r"use foo::bar::{quux::{Fez, *}, Baz};", ) } @@ -1211,7 +1211,7 @@ fn insert_with_renamed_import_complex_use() { use self::foo::{self, Foo as _, Bar}; "#, r#" -use self::foo::{self, Foo, Bar}; +use self::foo::{self, Bar, Foo}; "#, &InsertUseConfig { granularity: ImportGranularity::Crate, diff --git a/crates/ide-db/src/imports/merge_imports.rs b/crates/ide-db/src/imports/merge_imports.rs index 7ec38c317df30..5c97ffaf4b4a5 100644 --- a/crates/ide-db/src/imports/merge_imports.rs +++ b/crates/ide-db/src/imports/merge_imports.rs @@ -7,9 +7,12 @@ use parser::T; use stdx::is_upper_snake_case; use syntax::{ algo, - ast::{self, make, AstNode, HasAttrs, HasName, HasVisibility, PathSegmentKind}, + ast::{ + self, edit_in_place::Removable, make, AstNode, HasAttrs, HasName, HasVisibility, + PathSegmentKind, + }, ted::{self, Position}, - Direction, + Direction, SyntaxElement, }; use crate::syntax_helpers::node_ext::vis_eq; @@ -58,6 +61,10 @@ pub fn try_merge_imports( let lhs_tree = lhs.use_tree()?; let rhs_tree = rhs.use_tree()?; try_merge_trees_mut(&lhs_tree, &rhs_tree, merge_behavior)?; + + // Ignore `None` result because normalization should not affect the merge result. + try_normalize_use_tree_mut(&lhs_tree, merge_behavior.into()); + Some(lhs) } @@ -71,6 +78,10 @@ pub fn try_merge_trees( let lhs = lhs.clone_subtree().clone_for_update(); let rhs = rhs.clone_subtree().clone_for_update(); try_merge_trees_mut(&lhs, &rhs, merge)?; + + // Ignore `None` result because normalization should not affect the merge result. + try_normalize_use_tree_mut(&lhs, merge.into()); + Some(lhs) } @@ -232,6 +243,309 @@ fn recursive_merge(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior) Some(()) } +/// Style to follow when normalizing a use tree. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum NormalizationStyle { + /// Merges all descendant use tree lists with only one child use tree into their parent use tree. + /// + /// Examples: + /// - `foo::{bar::{Qux}}` -> `foo::bar::Qux` + /// - `foo::{bar::{self}}` -> `foo::bar` + /// - `{foo::bar}` -> `foo::bar` + Default, + /// Same as default but wraps the root use tree in a use tree list. + /// + /// Examples: + /// - `foo::{bar::{Qux}}` -> `{foo::bar::Qux}` + /// - `foo::{bar::{self}}` -> `{foo::bar}` + /// - `{foo::bar}` -> `{foo::bar}` + One, +} + +impl From for NormalizationStyle { + fn from(mb: MergeBehavior) -> Self { + match mb { + MergeBehavior::One => NormalizationStyle::One, + _ => NormalizationStyle::Default, + } + } +} + +/// Normalizes a use item by: +/// - Ordering all use trees +/// - Merging use trees with common prefixes +/// - Removing redundant braces based on the specified normalization style +/// (see [`NormalizationStyle`] doc) +/// +/// Examples: +/// +/// Using the "Default" normalization style +/// +/// - `foo::{bar::Qux, bar::{self}}` -> `foo::bar::{self, Qux}` +/// - `foo::bar::{self}` -> `foo::bar` +/// - `{foo::bar}` -> `foo::bar` +/// +/// Using the "One" normalization style +/// +/// - `foo::{bar::Qux, bar::{self}}` -> `{foo::bar::{self, Qux}}` +/// - `foo::bar::{self}` -> `{foo::bar}` +/// - `foo::bar` -> `{foo::bar}` +pub fn try_normalize_import(use_item: &ast::Use, style: NormalizationStyle) -> Option { + let use_item = use_item.clone_subtree().clone_for_update(); + try_normalize_use_tree_mut(&use_item.use_tree()?, style)?; + Some(use_item) +} + +/// Normalizes a use tree (see [`try_normalize_import`] doc). +pub fn try_normalize_use_tree( + use_tree: &ast::UseTree, + style: NormalizationStyle, +) -> Option { + let use_tree = use_tree.clone_subtree().clone_for_update(); + try_normalize_use_tree_mut(&use_tree, style)?; + Some(use_tree) +} + +macro_rules! call_and_track_result { + ($call:expr, $tracker: ident) => { + let result = $call; + if !$tracker && result.is_some() { + $tracker = true; + } + }; +} + +pub fn try_normalize_use_tree_mut( + use_tree: &ast::UseTree, + style: NormalizationStyle, +) -> Option<()> { + if style == NormalizationStyle::One { + let mut modified = false; + call_and_track_result!(use_tree.wrap_in_tree_list(), modified); + call_and_track_result!(recursive_normalize(use_tree, style), modified); + if !modified { + // Either the use tree was already normalized or its semantically empty. + return None; + } + } else { + recursive_normalize(use_tree, NormalizationStyle::Default)?; + } + Some(()) +} + +/// Recursively normalizes a use tree and its subtrees (if any). +fn recursive_normalize(use_tree: &ast::UseTree, style: NormalizationStyle) -> Option<()> { + let use_tree_list = use_tree.use_tree_list()?; + let merge_subtree_into_parent_tree = |single_subtree: &ast::UseTree| { + let merged_path = match (use_tree.path(), single_subtree.path()) { + (None, None) => None, + (Some(outer), None) => Some(outer), + (None, Some(inner)) if path_is_self(&inner) => None, + (None, Some(inner)) => Some(inner), + (Some(outer), Some(inner)) if path_is_self(&inner) => Some(outer), + (Some(outer), Some(inner)) => Some(make::path_concat(outer, inner).clone_for_update()), + }; + if merged_path.is_some() + || single_subtree.use_tree_list().is_some() + || single_subtree.star_token().is_some() + { + ted::remove_all_iter(use_tree.syntax().children_with_tokens()); + if let Some(path) = merged_path { + ted::insert_raw(Position::first_child_of(use_tree.syntax()), path.syntax()); + if single_subtree.use_tree_list().is_some() || single_subtree.star_token().is_some() + { + ted::insert_raw( + Position::last_child_of(use_tree.syntax()), + make::token(T![::]), + ); + } + } + if let Some(inner_use_tree_list) = single_subtree.use_tree_list() { + ted::insert_raw( + Position::last_child_of(use_tree.syntax()), + inner_use_tree_list.syntax(), + ); + } else if single_subtree.star_token().is_some() { + ted::insert_raw(Position::last_child_of(use_tree.syntax()), make::token(T![*])); + } else if let Some(rename) = single_subtree.rename() { + ted::insert_raw( + Position::last_child_of(use_tree.syntax()), + make::tokens::single_space(), + ); + ted::insert_raw(Position::last_child_of(use_tree.syntax()), rename.syntax()); + } + Some(()) + } else { + // Bail on semantically empty use trees. + None + } + }; + let one_style_tree_list = |subtree: &ast::UseTree| match ( + subtree.path().is_none() && subtree.star_token().is_none() && subtree.rename().is_none(), + subtree.use_tree_list(), + ) { + (true, tree_list) => tree_list, + _ => None, + }; + let add_element_to_list = |elem: SyntaxElement, elements: &mut Vec| { + if !elements.is_empty() { + elements.push(make::token(T![,]).into()); + elements.push(make::tokens::single_space().into()); + } + elements.push(elem); + }; + if let Some((single_subtree,)) = use_tree_list.use_trees().collect_tuple() { + if style == NormalizationStyle::One { + // Only normalize descendant subtrees if the normalization style is "one". + recursive_normalize(&single_subtree, NormalizationStyle::Default)?; + } else { + // Otherwise, merge the single subtree into it's parent (if possible) + // and then normalize the result. + merge_subtree_into_parent_tree(&single_subtree)?; + recursive_normalize(use_tree, style); + } + } else { + // Tracks whether any changes have been made to the use tree. + let mut modified = false; + + // Recursively un-nests (if necessary) and then normalizes each subtree in the tree list. + for subtree in use_tree_list.use_trees() { + if let Some(one_tree_list) = one_style_tree_list(&subtree) { + let mut elements = Vec::new(); + let mut one_tree_list_iter = one_tree_list.use_trees(); + let mut prev_skipped = Vec::new(); + loop { + let mut prev_skipped_iter = prev_skipped.into_iter(); + let mut curr_skipped = Vec::new(); + + while let Some(sub_sub_tree) = + one_tree_list_iter.next().or(prev_skipped_iter.next()) + { + if let Some(sub_one_tree_list) = one_style_tree_list(&sub_sub_tree) { + curr_skipped.extend(sub_one_tree_list.use_trees()); + } else { + call_and_track_result!( + recursive_normalize(&sub_sub_tree, NormalizationStyle::Default), + modified + ); + add_element_to_list( + sub_sub_tree.syntax().clone().into(), + &mut elements, + ); + } + } + + if curr_skipped.is_empty() { + // Un-nesting is complete. + break; + } + prev_skipped = curr_skipped; + } + + // Either removes the subtree (if its semantically empty) or replaces it with + // the un-nested elements. + if elements.is_empty() { + subtree.remove(); + } else { + ted::replace_with_many(subtree.syntax(), elements); + } + modified = true; + } else { + call_and_track_result!( + recursive_normalize(&subtree, NormalizationStyle::Default), + modified + ); + } + } + + // Merge all merge-able subtrees. + let mut tree_list_iter = use_tree_list.use_trees(); + let mut anchor = tree_list_iter.next()?; + let mut prev_skipped = Vec::new(); + loop { + let mut has_merged = false; + let mut prev_skipped_iter = prev_skipped.into_iter(); + let mut next_anchor = None; + let mut curr_skipped = Vec::new(); + + while let Some(candidate) = tree_list_iter.next().or(prev_skipped_iter.next()) { + let result = try_merge_trees_mut(&anchor, &candidate, MergeBehavior::Crate); + if result.is_some() { + // Remove merged subtree. + candidate.remove(); + has_merged = true; + } else if next_anchor.is_none() { + next_anchor = Some(candidate); + } else { + curr_skipped.push(candidate); + } + } + + if has_merged { + // Normalize the merge result. + recursive_normalize(&anchor, NormalizationStyle::Default); + modified = true; + } + + let (Some(next_anchor), true) = (next_anchor, !curr_skipped.is_empty()) else { + // Merging is complete. + break; + }; + + // Try to merge the remaining subtrees in the next iteration. + anchor = next_anchor; + prev_skipped = curr_skipped; + } + + let mut subtrees: Vec<_> = use_tree_list.use_trees().collect(); + // Merge the remaining subtree into its parent, if its only one and + // the normalization style is not "one". + if subtrees.len() == 1 && style != NormalizationStyle::One { + call_and_track_result!(merge_subtree_into_parent_tree(&subtrees[0]), modified); + } + // Order the remaining subtrees (if necessary). + if subtrees.len() > 1 { + let mut did_sort = false; + subtrees.sort_unstable_by(|a, b| { + let order = use_tree_cmp_bin_search(a, b); + if !did_sort && order == Ordering::Less { + did_sort = true; + } + order + }); + if did_sort { + let start = use_tree_list + .l_curly_token() + .and_then(|l_curly| algo::non_trivia_sibling(l_curly.into(), Direction::Next)) + .filter(|it| it.kind() != T!['}']); + let end = use_tree_list + .r_curly_token() + .and_then(|r_curly| algo::non_trivia_sibling(r_curly.into(), Direction::Prev)) + .filter(|it| it.kind() != T!['{']); + if let Some((start, end)) = start.zip(end) { + // Attempt to insert elements while preserving preceding and trailing trivia. + let mut elements = Vec::new(); + for subtree in subtrees { + add_element_to_list(subtree.syntax().clone().into(), &mut elements); + } + ted::replace_all(start..=end, elements); + } else { + let new_use_tree_list = + make::use_tree_list(subtrees.into_iter()).clone_for_update(); + ted::replace(use_tree_list.syntax(), new_use_tree_list.syntax()); + } + modified = true; + } + } + + if !modified { + // Either the use tree was already normalized or its semantically empty. + return None; + } + } + Some(()) +} + /// Traverses both paths until they differ, returning the common prefix of both. pub fn common_prefix(lhs: &ast::Path, rhs: &ast::Path) -> Option<(ast::Path, ast::Path)> { let mut res = None; From 81d713ea9fdbe96df572268e250929d19b7e262f Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sat, 20 Jan 2024 16:20:09 +0300 Subject: [PATCH 085/246] remove ordered insert logic from recursive merge function --- crates/ide-db/src/imports/merge_imports.rs | 60 ++-------------------- 1 file changed, 5 insertions(+), 55 deletions(-) diff --git a/crates/ide-db/src/imports/merge_imports.rs b/crates/ide-db/src/imports/merge_imports.rs index 5c97ffaf4b4a5..029357c607bfc 100644 --- a/crates/ide-db/src/imports/merge_imports.rs +++ b/crates/ide-db/src/imports/merge_imports.rs @@ -1,6 +1,5 @@ //! Handle syntactic aspects of merging UseTrees. use std::cmp::Ordering; -use std::iter::empty; use itertools::{EitherOrBoth, Itertools}; use parser::T; @@ -184,59 +183,10 @@ fn recursive_merge(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior) } Err(insert_idx) => { use_trees.insert(insert_idx, rhs_t.clone()); - match lhs.use_tree_list() { - // Creates a new use tree list with the item. - None => lhs.get_or_create_use_tree_list().add_use_tree(rhs_t), - // Recreates the use tree list with sorted items (see `use_tree_cmp` doc). - Some(use_tree_list) => { - if use_tree_list.l_curly_token().is_none() { - ted::insert_raw( - Position::first_child_of(use_tree_list.syntax()), - make::token(T!['{']), - ); - } - if use_tree_list.r_curly_token().is_none() { - ted::insert_raw( - Position::last_child_of(use_tree_list.syntax()), - make::token(T!['}']), - ); - } - - let mut elements = Vec::new(); - for (idx, tree) in use_trees.iter().enumerate() { - if idx > 0 { - elements.push(make::token(T![,]).into()); - elements.push(make::tokens::single_space().into()); - } - elements.push(tree.syntax().clone().into()); - } - - let start = use_tree_list - .l_curly_token() - .and_then(|l_curly| { - algo::non_trivia_sibling(l_curly.into(), Direction::Next) - }) - .filter(|it| it.kind() != T!['}']); - let end = use_tree_list - .r_curly_token() - .and_then(|r_curly| { - algo::non_trivia_sibling(r_curly.into(), Direction::Prev) - }) - .filter(|it| it.kind() != T!['{']); - if let Some((start, end)) = start.zip(end) { - // Attempt to insert elements while preserving preceding and trailing trivia. - ted::replace_all(start..=end, elements); - } else { - let new_use_tree_list = make::use_tree_list(empty()).clone_for_update(); - let trees_pos = match new_use_tree_list.l_curly_token() { - Some(l_curly) => Position::after(l_curly), - None => Position::last_child_of(new_use_tree_list.syntax()), - }; - ted::insert_all_raw(trees_pos, elements); - ted::replace(use_tree_list.syntax(), new_use_tree_list.syntax()); - } - } - } + // We simply add the use tree to the end of tree list. Ordering of use trees + // and imports is done by the `try_normalize_*` functions. The sorted `use_trees` + // vec is only used for binary search. + lhs.get_or_create_use_tree_list().add_use_tree(rhs_t); } } } @@ -594,7 +544,7 @@ fn use_tree_cmp_bin_search(lhs: &ast::UseTree, rhs: &ast::UseTree) -> Ordering { /// and `crate` first, then identifier imports with lowercase ones first and upper snake case /// (e.g. UPPER_SNAKE_CASE) ones last, then glob imports, and at last list imports. /// -/// Example foo::{self, foo, baz, Baz, Qux, FOO_BAZ, *, {Bar}} +/// Example: `foo::{self, baz, foo, Baz, Qux, FOO_BAZ, *, {Bar}}` /// Ref: . pub(super) fn use_tree_cmp(a: &ast::UseTree, b: &ast::UseTree) -> Ordering { let a_is_simple_path = a.is_simple_path() && a.rename().is_none(); From a8a18f3ccf99a120e4dcbcdb0358a9ef701789f5 Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sat, 20 Jan 2024 19:49:16 +0300 Subject: [PATCH 086/246] add normalize import assist --- .../src/handlers/normalize_import.rs | 166 ++++++++++++++++++ crates/ide-assists/src/lib.rs | 2 + crates/ide-assists/src/tests/generated.rs | 13 ++ 3 files changed, 181 insertions(+) create mode 100644 crates/ide-assists/src/handlers/normalize_import.rs diff --git a/crates/ide-assists/src/handlers/normalize_import.rs b/crates/ide-assists/src/handlers/normalize_import.rs new file mode 100644 index 0000000000000..42076c4ff192e --- /dev/null +++ b/crates/ide-assists/src/handlers/normalize_import.rs @@ -0,0 +1,166 @@ +use ide_db::imports::merge_imports::try_normalize_import; +use syntax::{ast, AstNode}; + +use crate::{ + assist_context::{AssistContext, Assists}, + AssistId, AssistKind, +}; + +// Assist: normalize_import +// +// Normalizes an import. +// +// ``` +// use$0 std::{io, {fmt::Formatter}}; +// ``` +// -> +// ``` +// use std::{fmt::Formatter, io}; +// ``` +pub(crate) fn normalize_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let use_item = if ctx.has_empty_selection() { + ctx.find_node_at_offset()? + } else { + ctx.covering_element().ancestors().find_map(ast::Use::cast)? + }; + + let target = use_item.syntax().text_range(); + 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); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{ + check_assist, check_assist_import_one, check_assist_not_applicable, + check_assist_not_applicable_for_import_one, + }; + + use super::*; + + macro_rules! check_assist_variations { + ($fixture: literal, $expected: literal) => { + check_assist( + normalize_import, + concat!("use $0", $fixture, ";"), + concat!("use ", $expected, ";"), + ); + check_assist( + normalize_import, + concat!("$0use ", $fixture, ";"), + concat!("use ", $expected, ";"), + ); + + check_assist_import_one( + normalize_import, + concat!("use $0", $fixture, ";"), + concat!("use {", $expected, "};"), + ); + check_assist_import_one( + normalize_import, + concat!("$0use ", $fixture, ";"), + concat!("use {", $expected, "};"), + ); + + check_assist_import_one( + normalize_import, + concat!("use $0{", $fixture, "};"), + concat!("use {", $expected, "};"), + ); + check_assist_import_one( + normalize_import, + concat!("$0use {", $fixture, "};"), + concat!("use {", $expected, "};"), + ); + + check_assist( + normalize_import, + concat!("use $0", $fixture, "$0;"), + concat!("use ", $expected, ";"), + ); + check_assist( + normalize_import, + concat!("$0use ", $fixture, ";$0"), + concat!("use ", $expected, ";"), + ); + }; + } + + macro_rules! check_assist_not_applicable_variations { + ($fixture: literal) => { + check_assist_not_applicable(normalize_import, concat!("use $0", $fixture, ";")); + check_assist_not_applicable(normalize_import, concat!("$0use ", $fixture, ";")); + + check_assist_not_applicable_for_import_one( + normalize_import, + concat!("use $0{", $fixture, "};"), + ); + check_assist_not_applicable_for_import_one( + normalize_import, + concat!("$0use {", $fixture, "};"), + ); + }; + } + + #[test] + fn test_order() { + check_assist_variations!( + "foo::{*, Qux, bar::{Quux, Bar}, baz, FOO_BAZ, self, Baz}", + "foo::{self, bar::{Bar, Quux}, baz, Baz, Qux, FOO_BAZ, *}" + ); + } + + #[test] + fn test_redundant_braces() { + check_assist_variations!("foo::{bar::{baz, Qux}}", "foo::bar::{baz, Qux}"); + check_assist_variations!("foo::{bar::{self}}", "foo::bar"); + check_assist_variations!("foo::{bar::{*}}", "foo::bar::*"); + check_assist_variations!("foo::{bar::{Qux as Quux}}", "foo::bar::Qux as Quux"); + check_assist_variations!( + "foo::bar::{{FOO_BAZ, Qux, self}, {*, baz}}", + "foo::bar::{self, baz, Qux, FOO_BAZ, *}" + ); + check_assist_variations!( + "foo::bar::{{{FOO_BAZ}, {{Qux}, {self}}}, {{*}, {baz}}}", + "foo::bar::{self, baz, Qux, FOO_BAZ, *}" + ); + } + + #[test] + fn test_merge() { + check_assist_variations!( + "foo::{*, bar, {FOO_BAZ, qux}, bar::{*, baz}, {Quux}}", + "foo::{bar::{self, baz, *}, qux, Quux, FOO_BAZ, *}" + ); + check_assist_variations!( + "foo::{*, bar, {FOO_BAZ, qux}, bar::{*, baz}, {Quux, bar::{baz::Foo}}}", + "foo::{bar::{self, baz::{self, Foo}, *}, qux, Quux, FOO_BAZ, *}" + ); + } + + #[test] + fn not_applicable_to_normalized_import() { + check_assist_not_applicable_variations!("foo::bar"); + check_assist_not_applicable_variations!("foo::bar::*"); + check_assist_not_applicable_variations!("foo::bar::Qux as Quux"); + check_assist_not_applicable_variations!("foo::bar::{self, baz, Qux, FOO_BAZ, *}"); + check_assist_not_applicable_variations!( + "foo::{self, bar::{Bar, Quux}, baz, Baz, Qux, FOO_BAZ, *}" + ); + check_assist_not_applicable_variations!( + "foo::{bar::{self, baz, *}, qux, Quux, FOO_BAZ, *}" + ); + check_assist_not_applicable_variations!( + "foo::{bar::{self, baz::{self, Foo}, *}, qux, Quux, FOO_BAZ, *}" + ); + } +} diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index edcf52a9b38eb..2fec104323dc7 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -183,6 +183,7 @@ mod handlers { mod move_guard; mod move_module_to_file; mod move_to_mod_rs; + mod normalize_import; mod number_representation; mod promote_local_to_const; mod pull_assignment_up; @@ -300,6 +301,7 @@ mod handlers { move_module_to_file::move_module_to_file, move_to_mod_rs::move_to_mod_rs, move_from_mod_rs::move_from_mod_rs, + normalize_import::normalize_import, number_representation::reformat_number_literal, pull_assignment_up::pull_assignment_up, promote_local_to_const::promote_local_to_const, diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 0ce89ae0a9a5e..8d7c49d52c23d 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -2217,6 +2217,19 @@ fn t() {} ) } +#[test] +fn doctest_normalize_import() { + check_doc_test( + "normalize_import", + r#####" +use$0 std::{io, {fmt::Formatter}}; +"#####, + r#####" +use std::{fmt::Formatter, io}; +"#####, + ) +} + #[test] fn doctest_promote_local_to_const() { check_doc_test( From b241593f3640cb2cffc8d52a5bd3dc544e3dbeb2 Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sun, 21 Jan 2024 22:29:04 +0300 Subject: [PATCH 087/246] merge imports assist always applies to covering use item except for nested use tree selections --- .../ide-assists/src/handlers/merge_imports.rs | 99 +++++-------------- 1 file changed, 23 insertions(+), 76 deletions(-) diff --git a/crates/ide-assists/src/handlers/merge_imports.rs b/crates/ide-assists/src/handlers/merge_imports.rs index 02dbde803e5b2..ee6376f247c5a 100644 --- a/crates/ide-assists/src/handlers/merge_imports.rs +++ b/crates/ide-assists/src/handlers/merge_imports.rs @@ -32,24 +32,13 @@ use Edit::*; pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let (target, edits) = if ctx.has_empty_selection() { // Merge a neighbor - let mut tree: ast::UseTree = ctx.find_node_at_offset()?; - if ctx.config.insert_use.granularity == ImportGranularity::One - && tree.parent_use_tree_list().is_some() - { - cov_mark::hit!(resolve_top_use_tree_for_import_one); - tree = tree.top_use_tree(); - } + cov_mark::hit!(merge_with_use_item_neighbors); + let tree = ctx.find_node_at_offset::()?.top_use_tree(); let target = tree.syntax().text_range(); - let edits = if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) { - cov_mark::hit!(merge_with_use_item_neighbors); - let mut neighbor = next_prev().find_map(|dir| neighbor(&use_item, dir)).into_iter(); - use_item.try_merge_from(&mut neighbor, &ctx.config.insert_use) - } else { - cov_mark::hit!(merge_with_use_tree_neighbors); - let mut neighbor = next_prev().find_map(|dir| neighbor(&tree, dir)).into_iter(); - tree.clone().try_merge_from(&mut neighbor, &ctx.config.insert_use) - }; + let use_item = tree.syntax().parent().and_then(ast::Use::cast)?; + let mut neighbor = next_prev().find_map(|dir| neighbor(&use_item, dir)).into_iter(); + let edits = use_item.try_merge_from(&mut neighbor, &ctx.config.insert_use); (target, edits?) } else { // Merge selected @@ -159,10 +148,7 @@ impl Edit { #[cfg(test)] mod tests { - use crate::tests::{ - check_assist, check_assist_import_one, check_assist_not_applicable, - check_assist_not_applicable_for_import_one, - }; + use crate::tests::{check_assist, check_assist_import_one, check_assist_not_applicable}; use super::*; @@ -206,10 +192,7 @@ use std::fmt::{Debug, Display}; ); // The assist macro below calls `check_assist_import_one` 4 times with different input - // use item variations based on the first 2 input parameters, but only 2 calls - // contain `use {std::fmt$0::{Display, Debug}};` for which the top use tree will need - // to be resolved. - cov_mark::check_count!(resolve_top_use_tree_for_import_one, 2); + // use item variations based on the first 2 input parameters. cov_mark::check_count!(merge_with_use_item_neighbors, 4); check_assist_import_one_variations!( "std::fmt$0::{Display, Debug}", @@ -257,7 +240,7 @@ use std::fmt::{Debug, Display}; } #[test] - fn merge_self1() { + fn merge_self() { check_assist( merge_imports, r" @@ -275,28 +258,6 @@ use std::fmt::{self, Display}; ); } - #[test] - fn merge_self2() { - check_assist( - merge_imports, - r" -use std::{fmt, $0fmt::Display}; -", - r" -use std::{fmt::{self, Display}}; -", - ); - } - - #[test] - fn not_applicable_to_single_one_style_import() { - cov_mark::check!(resolve_top_use_tree_for_import_one); - check_assist_not_applicable_for_import_one( - merge_imports, - "use {std::{fmt, $0fmt::Display}};", - ); - } - #[test] fn skip_pub1() { check_assist_not_applicable( @@ -385,14 +346,14 @@ pub(in this::path) use std::fmt::{Debug, Display}; #[test] fn test_merge_nested() { - cov_mark::check!(merge_with_use_tree_neighbors); check_assist( merge_imports, r" -use std::{fmt$0::Debug, fmt::Display}; +use std::{fmt$0::Debug, fmt::Error}; +use std::{fmt::Write, fmt::Display}; ", r" -use std::{fmt::{Debug, Display}}; +use std::fmt::{Debug, Display, Error, Write}; ", ); } @@ -402,10 +363,11 @@ use std::{fmt::{Debug, Display}}; check_assist( merge_imports, r" -use std::{fmt::Debug, fmt$0::Display}; +use std::{fmt::Debug, fmt$0::Error}; +use std::{fmt::Write, fmt::Display}; ", r" -use std::{fmt::{Debug, Display}}; +use std::fmt::{Debug, Display, Error, Write}; ", ); } @@ -448,19 +410,6 @@ use std::fmt::{self, Debug, Display, Write}; ); } - #[test] - fn test_merge_self_with_nested_self_item() { - check_assist( - merge_imports, - r" -use std::{fmt$0::{self, Debug}, fmt::{Write, Display}}; -", - r" -use std::{fmt::{self, Debug, Display, Write}}; -", - ); - } - #[test] fn test_merge_nested_self_and_empty() { check_assist( @@ -579,29 +528,27 @@ use foo::{bar, baz}; check_assist( merge_imports, r" -use { - foo$0::bar, - foo::baz, +use foo$0::{ + bar, baz, }; +use foo::qux; ", r" -use { - foo::{bar, baz}, +use foo::{ + bar, baz, qux, }; ", ); check_assist( merge_imports, r" -use { - foo::baz, - foo$0::bar, +use foo::{ + baz, bar, }; +use foo$0::qux; ", r" -use { - foo::{bar, baz}, -}; +use foo::{bar, baz, qux}; ", ); } From fc00602723f9115dff36750eeaf58140bf7a6ac2 Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sun, 21 Jan 2024 23:44:51 +0300 Subject: [PATCH 088/246] merge imports assist avoids adding unnecessary braces when merging nested use tree selections --- .../ide-assists/src/handlers/merge_imports.rs | 58 +++++++++++++++++-- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/crates/ide-assists/src/handlers/merge_imports.rs b/crates/ide-assists/src/handlers/merge_imports.rs index ee6376f247c5a..797c5c0653321 100644 --- a/crates/ide-assists/src/handlers/merge_imports.rs +++ b/crates/ide-assists/src/handlers/merge_imports.rs @@ -1,8 +1,9 @@ use either::Either; use ide_db::imports::{ insert_use::{ImportGranularity, InsertUseConfig}, - merge_imports::{try_merge_imports, try_merge_trees, MergeBehavior}, + merge_imports::{try_merge_imports, try_merge_trees, try_normalize_use_tree, MergeBehavior}, }; +use itertools::Itertools; use syntax::{ algo::neighbor, ast::{self, edit_in_place::Removable}, @@ -83,7 +84,35 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio for edit in edits_mut { match edit { Remove(it) => it.as_ref().either(Removable::remove, Removable::remove), - Replace(old, new) => ted::replace(old, new), + 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()); + } + } + } } } }, @@ -148,7 +177,10 @@ impl Edit { #[cfg(test)] mod tests { - use crate::tests::{check_assist, check_assist_import_one, check_assist_not_applicable}; + use crate::tests::{ + check_assist, check_assist_import_one, check_assist_not_applicable, + check_assist_not_applicable_for_import_one, + }; use super::*; @@ -258,6 +290,15 @@ use std::fmt::{self, Display}; ); } + #[test] + fn not_applicable_to_single_import() { + check_assist_not_applicable(merge_imports, "use std::{fmt, $0fmt::Display};"); + check_assist_not_applicable_for_import_one( + merge_imports, + "use {std::{fmt, $0fmt::Display}};", + ); + } + #[test] fn skip_pub1() { check_assist_not_applicable( @@ -658,12 +699,19 @@ use std::{ };", ); - // FIXME: Remove redundant braces. See also unnecessary-braces diagnostic. cov_mark::check!(merge_with_selected_use_tree_neighbors); + check_assist( + merge_imports, + r"use std::{fmt::Result, $0fmt::Display, fmt::Debug$0};", + r"use std::{fmt::Result, fmt::{Debug, Display}};", + ); + + cov_mark::check!(merge_with_selected_use_tree_neighbors); + cov_mark::check!(replace_parent_with_normalized_use_tree); check_assist( merge_imports, r"use std::$0{fmt::Display, fmt::Debug}$0;", - r"use std::{fmt::{Debug, Display}};", + r"use std::fmt::{Debug, Display};", ); } } From 84e13145ff37095a1e73ba1f0fcebb64097087d5 Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Mon, 22 Jan 2024 11:18:22 +0300 Subject: [PATCH 089/246] add more tests for normalize import assist --- .../src/handlers/normalize_import.rs | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/crates/ide-assists/src/handlers/normalize_import.rs b/crates/ide-assists/src/handlers/normalize_import.rs index 42076c4ff192e..7d003efe721d1 100644 --- a/crates/ide-assists/src/handlers/normalize_import.rs +++ b/crates/ide-assists/src/handlers/normalize_import.rs @@ -147,6 +147,59 @@ mod tests { ); } + #[test] + fn test_merge_self() { + check_assist_variations!("std::{fmt, fmt::Display}", "std::fmt::{self, Display}"); + } + + #[test] + fn test_merge_nested() { + check_assist_variations!("std::{fmt::Debug, fmt::Display}", "std::fmt::{Debug, Display}"); + } + + #[test] + fn test_merge_nested2() { + check_assist_variations!("std::{fmt::Debug, fmt::Display}", "std::fmt::{Debug, Display}"); + } + + #[test] + fn test_merge_self_with_nested_self_item() { + check_assist_variations!( + "std::{fmt::{self, Debug}, fmt::{Write, Display}}", + "std::fmt::{self, Debug, Display, Write}" + ); + } + + #[test] + fn works_with_trailing_comma() { + check_assist( + normalize_import, + r" +use $0{ + foo::bar, + foo::baz, +}; + ", + r" +use foo::{bar, baz}; + ", + ); + check_assist_import_one( + normalize_import, + r" +use $0{ + foo::bar, + foo::baz, +}; +", + r" +use { + foo::{bar, baz}, +}; +", + ); + } + #[test] fn not_applicable_to_normalized_import() { check_assist_not_applicable_variations!("foo::bar"); From 6f303f49fed35a0101b5fce1977bf719045d97df Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sun, 28 Jan 2024 18:28:13 +0800 Subject: [PATCH 090/246] feat: enable excluding refs search results in test --- crates/ide-db/src/search.rs | 37 +++++++++++++++++++- crates/ide/src/highlight_related.rs | 1 + crates/ide/src/references.rs | 3 +- crates/rust-analyzer/src/config.rs | 7 ++++ crates/rust-analyzer/src/handlers/request.rs | 4 ++- crates/rust-analyzer/src/lsp/to_proto.rs | 1 + docs/user/generated_config.adoc | 5 +++ editors/code/package.json | 5 +++ 8 files changed, 60 insertions(+), 3 deletions(-) diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index 7769d8fba100c..5aa4186f8227d 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -15,7 +15,10 @@ use memchr::memmem::Finder; use nohash_hasher::IntMap; use once_cell::unsync::Lazy; use parser::SyntaxKind; -use syntax::{ast, match_ast, AstNode, AstToken, SyntaxElement, TextRange, TextSize}; +use syntax::{ + ast::{self, HasAttrs as _}, + match_ast, AstNode, AstToken, SyntaxElement, TextRange, TextSize, +}; use triomphe::Arc; use crate::{ @@ -134,6 +137,7 @@ pub enum ReferenceCategory { // FIXME: Some day should be able to search in doc comments. Would probably // need to switch from enum to bitflags then? // DocComment + Test, } /// Generally, `search_scope` returns files that might contain references for the element. @@ -872,6 +876,10 @@ fn def_to_ty(sema: &Semantics<'_, RootDatabase>, def: &Definition) -> Option Option { + if is_name_ref_in_test(r) { + return Some(ReferenceCategory::Test); + } + // Only Locals and Fields have accesses for now. if !matches!(def, Definition::Local(_) | Definition::Field(_)) { return is_name_ref_in_import(r).then_some(ReferenceCategory::Import); @@ -910,3 +918,30 @@ fn is_name_ref_in_import(name_ref: &ast::NameRef) -> bool { .and_then(|it| it.parent_path().top_path().syntax().parent()) .map_or(false, |it| it.kind() == SyntaxKind::USE_TREE) } + +fn is_name_ref_in_test(name_ref: &ast::NameRef) -> bool { + let mode = name_ref.syntax().ancestors().find_map(|node| { + match_ast! { + match node { + ast::Fn(f) => { + let attrs = f.attrs(); + let mut is_test = false; + for attr in attrs { + if attr.to_string() == "#[test]" { + is_test = true; + break; + } + } + if is_test { + Some(ReferenceCategory::Test) + } + else { + None + } + }, + _ => None + } + } + }); + mode.is_some() +} diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs index c3a403b10704b..53ed117060ab9 100644 --- a/crates/ide/src/highlight_related.rs +++ b/crates/ide/src/highlight_related.rs @@ -519,6 +519,7 @@ mod tests { ReferenceCategory::Read => "read", ReferenceCategory::Write => "write", ReferenceCategory::Import => "import", + ReferenceCategory::Test => "test", } .to_string() }), diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 78fe84f70d3a6..bcf862012a6f1 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -454,6 +454,7 @@ fn main() { "#]], ); } + #[test] fn test_variant_tuple_before_paren() { check( @@ -1435,7 +1436,7 @@ fn test$0() { expect![[r#" test Function FileId(0) 0..33 11..15 - FileId(0) 24..28 + FileId(0) 24..28 Test "#]], ); } diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 3c1b464c3c1f5..eeb28b8fe4263 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -494,6 +494,9 @@ config_data! { /// Exclude imports from find-all-references. references_excludeImports: bool = "false", + /// Exclude tests from find-all-references. + references_excludeTests: bool = "false", + /// Allow renaming of items not belonging to the loaded workspaces. rename_allowExternalItems: bool = "false", @@ -1545,6 +1548,10 @@ impl Config { self.data.references_excludeImports } + pub fn find_all_refs_exclude_tests(&self) -> bool { + self.data.references_excludeTests + } + pub fn snippet_cap(&self) -> bool { self.experimental("snippetTextEdit") } diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index f3c2df24d951b..03725daedd382 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -1055,6 +1055,7 @@ pub(crate) fn handle_references( let position = from_proto::file_position(&snap, params.text_document_position)?; let exclude_imports = snap.config.find_all_refs_exclude_imports(); + let exclude_tests = snap.config.find_all_refs_exclude_tests(); let refs = match snap.analysis.find_all_refs(position, None)? { None => return Ok(None), @@ -1078,7 +1079,8 @@ pub(crate) fn handle_references( .flat_map(|(file_id, refs)| { refs.into_iter() .filter(|&(_, category)| { - !exclude_imports || category != Some(ReferenceCategory::Import) + (!exclude_imports || category != Some(ReferenceCategory::Import)) + && (!exclude_tests || category != Some(ReferenceCategory::Test)) }) .map(move |(range, _)| FileRange { file_id, range }) }) diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index fe381fbeb3f03..f221863aff0ee 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -92,6 +92,7 @@ pub(crate) fn document_highlight_kind( ReferenceCategory::Read => Some(lsp_types::DocumentHighlightKind::READ), ReferenceCategory::Write => Some(lsp_types::DocumentHighlightKind::WRITE), ReferenceCategory::Import => None, + ReferenceCategory::Test => None, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index f887bb9df31c8..cfa7503d73900 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -777,6 +777,11 @@ Internal config, path to proc-macro server executable. -- Exclude imports from find-all-references. -- +[[rust-analyzer.references.excludeTests]]rust-analyzer.references.excludeTests (default: `false`):: ++ +-- +Exclude tests from find-all-references. +-- [[rust-analyzer.rename.allowExternalItems]]rust-analyzer.rename.allowExternalItems (default: `false`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 5ed5146ea1b11..841e364ed8457 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1505,6 +1505,11 @@ "default": false, "type": "boolean" }, + "rust-analyzer.references.excludeTests": { + "markdownDescription": "Exclude tests from find-all-references.", + "default": false, + "type": "boolean" + }, "rust-analyzer.rename.allowExternalItems": { "markdownDescription": "Allow renaming of items not belonging to the loaded workspaces.", "default": false, From 1bd21e98c0b67097b7c242e6ebc24085bfba982c Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sun, 28 Jan 2024 18:39:42 +0800 Subject: [PATCH 091/246] test: add test for excluding refs --- crates/ide/src/references.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index bcf862012a6f1..4b695612a699d 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -307,6 +307,30 @@ mod tests { use crate::{fixture, SearchScope}; + #[test] + fn exclude_tests() { + check( + r#" +fn test_func() {} + +fn func() { + test_func$0(); +} + +#[test] +fn test() { + test_func(); +} +"#, + expect![[r#" + test_func Function FileId(0) 0..17 3..12 + + FileId(0) 35..44 + FileId(0) 75..84 Test + "#]], + ); + } + #[test] fn test_struct_literal_after_space() { check( From f43cea0878475d747511e55b34c4c89bae78d072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sun, 28 Jan 2024 15:56:54 +0200 Subject: [PATCH 092/246] Merge commit '7219414e81810fd4d967136c4a0650523892c157' into sync-from-ra --- Cargo.lock | 91 +- Cargo.toml | 9 +- crates/base-db/src/lib.rs | 2 +- crates/cfg/src/cfg_expr.rs | 22 - crates/cfg/src/lib.rs | 8 +- crates/hir-def/src/attr.rs | 11 +- crates/hir-def/src/body.rs | 4 +- crates/hir-def/src/body/lower.rs | 1 + crates/hir-def/src/db.rs | 2 +- crates/hir-def/src/hir.rs | 2 +- crates/hir-def/src/lib.rs | 80 +- .../hir-def/src/macro_expansion_tests/mbe.rs | 2 +- .../hir-def/src/macro_expansion_tests/mod.rs | 4 +- crates/hir-def/src/nameres.rs | 4 +- crates/hir-def/src/nameres/attr_resolution.rs | 67 +- crates/hir-def/src/nameres/collector.rs | 10 +- crates/hir-expand/src/ast_id_map.rs | 9 +- crates/hir-expand/src/attrs.rs | 77 +- crates/hir-expand/src/builtin_attr_macro.rs | 8 +- crates/hir-expand/src/db.rs | 278 +---- crates/hir-expand/src/declarative.rs | 177 +++ crates/hir-expand/src/hygiene.rs | 40 + crates/hir-expand/src/lib.rs | 9 +- crates/hir-expand/src/mod_path.rs | 118 +- crates/hir-expand/src/span_map.rs | 37 +- crates/hir-ty/Cargo.toml | 1 + crates/hir-ty/src/diagnostics.rs | 2 +- crates/hir-ty/src/diagnostics/expr.rs | 38 +- crates/hir-ty/src/diagnostics/match_check.rs | 100 +- .../match_check/deconstruct_pat.rs | 1098 ----------------- .../diagnostics/match_check/pat_analysis.rs | 475 +++++++ .../src/diagnostics/match_check/usefulness.rs | 824 ------------- crates/hir-ty/src/lib.rs | 7 +- crates/hir-ty/src/mir.rs | 4 +- crates/hir-ty/src/tests.rs | 14 +- crates/hir/src/attrs.rs | 66 +- crates/hir/src/lib.rs | 197 ++- crates/ide-assists/src/handlers/sort_items.rs | 2 - crates/ide-assists/src/lib.rs | 38 +- crates/ide-assists/src/utils.rs | 2 +- crates/ide-completion/src/completions.rs | 4 +- .../src/completions/attribute.rs | 2 +- crates/ide-completion/src/lib.rs | 2 +- crates/ide-completion/src/render.rs | 8 +- crates/ide-completion/src/tests.rs | 2 +- crates/ide-db/src/lib.rs | 8 +- .../src/handlers/mismatched_arg_count.rs | 14 +- .../src/handlers/no_such_field.rs | 30 + crates/ide-diagnostics/src/lib.rs | 14 +- crates/ide-ssr/src/lib.rs | 2 +- crates/ide/src/inlay_hints.rs | 4 +- crates/ide/src/lib.rs | 18 +- crates/ide/src/navigation_target.rs | 2 +- crates/ide/src/syntax_highlighting.rs | 6 +- crates/mbe/src/lib.rs | 4 +- crates/mbe/src/syntax_bridge.rs | 10 +- crates/parser/src/grammar.rs | 4 +- crates/parser/src/grammar/items.rs | 2 +- crates/parser/src/lib.rs | 8 +- crates/parser/src/tests.rs | 2 +- .../proc-macro-srv/proc-macro-test/build.rs | 6 +- crates/proc-macro-srv/src/lib.rs | 2 +- crates/proc-macro-srv/src/server.rs | 2 +- crates/proc-macro-srv/src/server/token_id.rs | 2 +- crates/profile/src/lib.rs | 4 +- crates/project-model/src/lib.rs | 8 +- crates/rust-analyzer/src/cli.rs | 12 +- crates/rust-analyzer/src/handlers/request.rs | 6 +- crates/rust-analyzer/src/lsp.rs | 4 +- crates/rust-analyzer/tests/slow-tests/tidy.rs | 1 + crates/span/src/lib.rs | 3 - crates/stdx/src/lib.rs | 6 +- crates/syntax/src/ast.rs | 12 +- crates/syntax/src/lib.rs | 12 +- editors/code/language-configuration.json | 6 +- lib/lsp-server/src/lib.rs | 6 +- rustfmt.toml | 2 +- xtask/src/main.rs | 6 +- 78 files changed, 1390 insertions(+), 2796 deletions(-) create mode 100644 crates/hir-expand/src/declarative.rs delete mode 100644 crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs create mode 100644 crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs delete mode 100644 crates/hir-ty/src/diagnostics/match_check/usefulness.rs diff --git a/Cargo.lock b/Cargo.lock index a743d1c870a5a..7513abf17c8c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,7 +166,7 @@ checksum = "5676cea088c32290fe65c82895be9d06dd21e0fa49bb97ca840529e9417ab71a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", "synstructure", ] @@ -312,6 +312,17 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_arbitrary" version = "1.3.2" @@ -320,7 +331,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] @@ -582,6 +593,7 @@ dependencies = [ "project-model", "ra-ap-rustc_abi", "ra-ap-rustc_index", + "ra-ap-rustc_pattern_analysis", "rustc-hash", "scoped-tls", "smallvec", @@ -1407,20 +1419,20 @@ dependencies = [ [[package]] name = "ra-ap-rustc_abi" -version = "0.21.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7816f980fab89e878ff2e916e2077d484e3aa1c619a3cc982c8a417c3dfe45fa" +checksum = "8ce9100fc66c6c60aeeb076868ead9c2eaa65d6a5a90404f08c242327a92ff4b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "ra-ap-rustc_index", "tracing", ] [[package]] name = "ra-ap-rustc_index" -version = "0.21.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8352918d61aa4afab9f2ed7314cf638976b20949b3d61d2f468c975b0d251f24" +checksum = "5e5313d7f243b63ef9e58d94355b11aa8499f1328055f1f58adf0a5ea7d2faca" dependencies = [ "arrayvec", "ra-ap-rustc_index_macros", @@ -1429,21 +1441,21 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index_macros" -version = "0.21.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a9424018828155a3e3596515598f90e68427d8f35eff6df7f0856c73fc58a8" +checksum = "a83108ebf3e73dde205b9c25706209bcd7736480820f90ded28eabaf8b469f25" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", "synstructure", ] [[package]] name = "ra-ap-rustc_lexer" -version = "0.21.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc741c7a78103efab416b562e35bd73c8d4967478575010c86c6062f8d3cbf29" +checksum = "d2d221356e5717595e8a0afa5fba1620dcb4032ab784dc4d98fdc7284e3feb66" dependencies = [ "unicode-properties", "unicode-xid", @@ -1451,14 +1463,28 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.21.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d557201d71792487bd2bab637ab5be9aa6fff59b88e25e12de180b0f9d2df60f" +checksum = "ab62fc925612374103b4f178da347b535b35d9eb1ff5ba42105c990b2e25a164" dependencies = [ "ra-ap-rustc_index", "ra-ap-rustc_lexer", ] +[[package]] +name = "ra-ap-rustc_pattern_analysis" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c4085e0c771fd4b883930b599ef42966b855762bbe4052c17673b3253421a6d" +dependencies = [ + "derivative", + "ra-ap-rustc_index", + "rustc-hash", + "rustc_apfloat", + "smallvec", + "tracing", +] + [[package]] name = "rayon" version = "1.8.0" @@ -1593,7 +1619,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] @@ -1608,6 +1634,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_apfloat" +version = "0.2.0+llvm-462a31f5a5ab" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465187772033a5ee566f69fe008df03628fce549a0899aae76f0a0c2e34696be" +dependencies = [ + "bitflags 1.3.2", + "smallvec", +] + [[package]] name = "ryu" version = "1.0.13" @@ -1670,7 +1706,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] @@ -1693,7 +1729,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] @@ -1707,9 +1743,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e" [[package]] name = "smol_str" @@ -1770,6 +1806,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.39" @@ -1789,7 +1836,7 @@ checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", "unicode-xid", ] @@ -1876,7 +1923,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] @@ -1977,7 +2024,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2547f1ccb9915..56db5a28c08a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,10 +79,11 @@ tt = { path = "./crates/tt", version = "0.0.0" } vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } -ra-ap-rustc_lexer = { version = "0.21.0", default-features = false } -ra-ap-rustc_parse_format = { version = "0.21.0", default-features = false } -ra-ap-rustc_index = { version = "0.21.0", default-features = false } -ra-ap-rustc_abi = { version = "0.21.0", default-features = false } +ra-ap-rustc_lexer = { version = "0.33.0", default-features = false } +ra-ap-rustc_parse_format = { version = "0.33.0", default-features = false } +ra-ap-rustc_index = { version = "0.33.0", default-features = false } +ra-ap-rustc_abi = { version = "0.33.0", default-features = false } +ra-ap-rustc_pattern_analysis = { version = "0.33.0", default-features = false } # local crates that aren't published to crates.io. These should not have versions. sourcegen = { path = "./crates/sourcegen" } diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index 92d2b9c3f57c9..90da7efd4a8b2 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -2,8 +2,8 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod input; mod change; +mod input; use std::panic; diff --git a/crates/cfg/src/cfg_expr.rs b/crates/cfg/src/cfg_expr.rs index fb7505ba2dd5b..4be6ae7481d8e 100644 --- a/crates/cfg/src/cfg_expr.rs +++ b/crates/cfg/src/cfg_expr.rs @@ -18,28 +18,6 @@ pub enum CfgAtom { KeyValue { key: SmolStr, value: SmolStr }, } -impl CfgAtom { - /// Returns `true` when the atom comes from the target specification. - /// - /// If this returns `true`, then changing this atom requires changing the compilation target. If - /// it returns `false`, the atom might come from a build script or the build system. - pub fn is_target_defined(&self) -> bool { - match self { - CfgAtom::Flag(flag) => matches!(&**flag, "unix" | "windows"), - CfgAtom::KeyValue { key, value: _ } => matches!( - &**key, - "target_arch" - | "target_os" - | "target_env" - | "target_family" - | "target_endian" - | "target_pointer_width" - | "target_vendor" // NOTE: `target_feature` is left out since it can be configured via `-Ctarget-feature` - ), - } - } -} - impl fmt::Display for CfgAtom { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs index 6b178e7b04a76..454d6fc5384ba 100644 --- a/crates/cfg/src/lib.rs +++ b/crates/cfg/src/lib.rs @@ -131,11 +131,9 @@ impl CfgDiff { /// of both. pub fn new(enable: Vec, disable: Vec) -> Option { let mut occupied = FxHashSet::default(); - for item in enable.iter().chain(disable.iter()) { - if !occupied.insert(item) { - // was present - return None; - } + if enable.iter().chain(disable.iter()).any(|item| !occupied.insert(item)) { + // was present + return None; } Some(CfgDiff { enable, disable }) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 8fbfcc81d2800..a8e081705e324 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -32,6 +32,7 @@ use crate::{ VariantId, }; +/// Desugared attributes of an item post `cfg_attr` expansion. #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct Attrs(RawAttrs); @@ -228,7 +229,6 @@ pub enum DocAtom { KeyValue { key: SmolStr, value: SmolStr }, } -// Adapted from `CfgExpr` parsing code #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum DocExpr { Invalid, @@ -448,10 +448,7 @@ impl AttrsWithOwner { let map = db.fields_attrs_source_map(id.parent); let file_id = id.parent.file_id(db); let root = db.parse_or_expand(file_id); - let owner = match &map[id.local_id] { - Either::Left(it) => ast::AnyHasAttrs::new(it.to_node(&root)), - Either::Right(it) => ast::AnyHasAttrs::new(it.to_node(&root)), - }; + let owner = ast::AnyHasAttrs::new(map[id.local_id].to_node(&root)); InFile::new(file_id, owner) } AttrDefId::AdtId(adt) => match adt { @@ -634,7 +631,7 @@ fn attrs_from_item_tree_assoc<'db, N: ItemTreeModItemNode>( pub(crate) fn fields_attrs_source_map( db: &dyn DefDatabase, def: VariantId, -) -> Arc, AstPtr>>> { +) -> Arc>>> { let mut res = ArenaMap::default(); let child_source = def.child_source(db); @@ -643,7 +640,7 @@ pub(crate) fn fields_attrs_source_map( idx, variant .as_ref() - .either(|l| Either::Left(AstPtr::new(l)), |r| Either::Right(AstPtr::new(r))), + .either(|l| AstPtr::new(l).wrap_left(), |r| AstPtr::new(r).wrap_right()), ); } diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index 81132d738539f..e4308c6b7f1f2 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -1,10 +1,10 @@ //! Defines `Body`: a lowered representation of bodies of functions, statics and //! consts. mod lower; +mod pretty; +pub mod scope; #[cfg(test)] mod tests; -pub mod scope; -mod pretty; use std::ops::Index; diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index 5fc4867bfa67b..492ea6d5c591a 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -1335,6 +1335,7 @@ impl ExprCollector<'_> { let args = record_pat_field_list .fields() .filter_map(|f| { + self.check_cfg(&f)?; let ast_pat = f.pat()?; let pat = self.collect_pat(ast_pat, binding_list); let name = f.field_name()?.as_name(); diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index c9789ceb207c5..708abb5369377 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -194,7 +194,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Arc, AstPtr>>>; + ) -> Arc>>>; #[salsa::invoke(AttrsWithOwner::attrs_query)] fn attrs(&self, def: AttrDefId) -> Attrs; diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index 1a33868a78cd9..ac44d379415c0 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -12,8 +12,8 @@ //! //! See also a neighboring `body` module. -pub mod type_ref; pub mod format_args; +pub mod type_ref; use std::fmt; diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index adf070fe7da91..243de663977fd 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -25,13 +25,13 @@ extern crate ra_ap_rustc_abi as rustc_abi; pub mod db; pub mod attr; -pub mod path; pub mod builtin_type; -pub mod per_ns; pub mod item_scope; +pub mod path; +pub mod per_ns; -pub mod lower; pub mod expander; +pub mod lower; pub mod dyn_map; @@ -46,24 +46,24 @@ pub use self::hir::type_ref; pub mod body; pub mod resolver; -mod trace; pub mod nameres; +mod trace; -pub mod src; pub mod child_by_source; +pub mod src; -pub mod visibility; pub mod find_path; pub mod import_map; +pub mod visibility; pub use rustc_abi as layout; use triomphe::Arc; -#[cfg(test)] -mod test_db; #[cfg(test)] mod macro_expansion_tests; mod pretty; +#[cfg(test)] +mod test_db; use std::{ hash::{Hash, Hasher}, @@ -73,7 +73,6 @@ use std::{ use base_db::{impl_intern_key, salsa, CrateId, Edition}; use hir_expand::{ ast_id_map::{AstIdNode, FileAstId}, - attrs::{Attr, AttrId, AttrInput}, builtin_attr_macro::BuiltinAttrExpander, builtin_derive_macro::BuiltinDeriveExpander, builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander}, @@ -939,6 +938,15 @@ impl From for AttrDefId { } } } +impl From for AttrDefId { + fn from(vid: VariantId) -> Self { + match vid { + VariantId::EnumVariantId(id) => id.into(), + VariantId::StructId(id) => id.into(), + VariantId::UnionId(id) => id.into(), + } + } +} #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum VariantId { @@ -1265,60 +1273,6 @@ fn macro_call_as_call_id_with_eager( Ok(res) } -fn derive_macro_as_call_id( - db: &dyn DefDatabase, - item_attr: &AstIdWithPath, - derive_attr_index: AttrId, - derive_pos: u32, - call_site: Span, - krate: CrateId, - resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>, -) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> { - let (macro_id, def_id) = resolver(item_attr.path.clone()) - .filter(|(_, def_id)| def_id.is_derive()) - .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?; - let call_id = def_id.as_lazy_macro( - db.upcast(), - krate, - MacroCallKind::Derive { - ast_id: item_attr.ast_id, - derive_index: derive_pos, - derive_attr_index, - }, - call_site, - ); - Ok((macro_id, def_id, call_id)) -} - -fn attr_macro_as_call_id( - db: &dyn DefDatabase, - item_attr: &AstIdWithPath, - macro_attr: &Attr, - krate: CrateId, - def: MacroDefId, -) -> MacroCallId { - let arg = match macro_attr.input.as_deref() { - Some(AttrInput::TokenTree(tt)) => { - let mut tt = tt.as_ref().clone(); - tt.delimiter = tt::Delimiter::invisible_spanned(macro_attr.span); - Some(tt) - } - - _ => None, - }; - - def.as_lazy_macro( - db.upcast(), - krate, - MacroCallKind::Attr { - ast_id: item_attr.ast_id, - attr_args: arg.map(Arc::new), - invoc_attr_index: macro_attr.id, - }, - macro_attr.span, - ) -} - #[derive(Debug)] pub struct UnresolvedMacro { pub path: hir_expand::mod_path::ModPath, diff --git a/crates/hir-def/src/macro_expansion_tests/mbe.rs b/crates/hir-def/src/macro_expansion_tests/mbe.rs index 6d365bd93c0a4..d0ae1f59f7ca6 100644 --- a/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -1,11 +1,11 @@ //! Tests specific to declarative macros, aka macros by example. This covers //! both stable `macro_rules!` macros as well as unstable `macro` macros. -mod tt_conversion; mod matching; mod meta_syntax; mod metavar_expr; mod regression; +mod tt_conversion; use expect_test::expect; diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs index 550ce35f12760..ec2994053877e 100644 --- a/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -9,9 +9,9 @@ //! write unit-tests (in fact, we used to do that), but that makes tests brittle //! and harder to understand. -mod mbe; -mod builtin_fn_macro; mod builtin_derive_macro; +mod builtin_fn_macro; +mod mbe; mod proc_macros; use std::{iter, ops::Range, sync}; diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 7eb2f3adddbf9..2295df16fdcc4 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -48,11 +48,11 @@ //! the result pub mod attr_resolution; -pub mod proc_macro; -pub mod diagnostics; mod collector; +pub mod diagnostics; mod mod_resolution; mod path_resolution; +pub mod proc_macro; #[cfg(test)] mod tests; diff --git a/crates/hir-def/src/nameres/attr_resolution.rs b/crates/hir-def/src/nameres/attr_resolution.rs index 6288b8366bf05..1cadae8c87c49 100644 --- a/crates/hir-def/src/nameres/attr_resolution.rs +++ b/crates/hir-def/src/nameres/attr_resolution.rs @@ -1,16 +1,21 @@ //! Post-nameres attribute resolution. -use hir_expand::{attrs::Attr, MacroCallId}; +use base_db::CrateId; +use hir_expand::{ + attrs::{Attr, AttrId, AttrInput}, + MacroCallId, MacroCallKind, MacroDefId, +}; +use span::Span; use syntax::{ast, SmolStr}; +use triomphe::Arc; use crate::{ attr::builtin::{find_builtin_attr_idx, TOOL_MODULES}, - attr_macro_as_call_id, db::DefDatabase, item_scope::BuiltinShadowMode, nameres::path_resolution::ResolveMode, - path::{ModPath, PathKind}, - AstIdWithPath, LocalModuleId, UnresolvedMacro, + path::{self, ModPath, PathKind}, + AstIdWithPath, LocalModuleId, MacroId, UnresolvedMacro, }; use super::{DefMap, MacroSubNs}; @@ -93,3 +98,57 @@ impl DefMap { false } } + +pub(super) fn attr_macro_as_call_id( + db: &dyn DefDatabase, + item_attr: &AstIdWithPath, + macro_attr: &Attr, + krate: CrateId, + def: MacroDefId, +) -> MacroCallId { + let arg = match macro_attr.input.as_deref() { + Some(AttrInput::TokenTree(tt)) => { + let mut tt = tt.as_ref().clone(); + tt.delimiter = tt::Delimiter::invisible_spanned(macro_attr.span); + Some(tt) + } + + _ => None, + }; + + def.as_lazy_macro( + db.upcast(), + krate, + MacroCallKind::Attr { + ast_id: item_attr.ast_id, + attr_args: arg.map(Arc::new), + invoc_attr_index: macro_attr.id, + }, + macro_attr.span, + ) +} + +pub(super) fn derive_macro_as_call_id( + db: &dyn DefDatabase, + item_attr: &AstIdWithPath, + derive_attr_index: AttrId, + derive_pos: u32, + call_site: Span, + krate: CrateId, + resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>, +) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> { + let (macro_id, def_id) = resolver(item_attr.path.clone()) + .filter(|(_, def_id)| def_id.is_derive()) + .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?; + let call_id = def_id.as_lazy_macro( + db.upcast(), + krate, + MacroCallKind::Derive { + ast_id: item_attr.ast_id, + derive_index: derive_pos, + derive_attr_index, + }, + call_site, + ); + Ok((macro_id, def_id, call_id)) +} diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 1c0f4d4d35ff1..248d3213d5d75 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -30,9 +30,7 @@ use triomphe::Arc; use crate::{ attr::Attrs, - attr_macro_as_call_id, db::DefDatabase, - derive_macro_as_call_id, item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports}, item_tree::{ self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, @@ -40,6 +38,7 @@ use crate::{ }, macro_call_as_call_id, macro_call_as_call_id_with_eager, nameres::{ + attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id}, diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, @@ -1245,7 +1244,9 @@ impl DefCollector<'_> { MacroDefId { kind: MacroDefKind::BuiltInAttr(expander, _),.. } if expander.is_derive() ) { - // Resolved to `#[derive]` + // Resolved to `#[derive]`, we don't actually expand this attribute like + // normal (as that would just be an identity expansion with extra output) + // Instead we treat derive attributes special and apply them separately. let item_tree = tree.item_tree(self.db); let ast_adt_id: FileAstId = match *mod_item { @@ -1284,7 +1285,8 @@ impl DefCollector<'_> { } // We treat the #[derive] macro as an attribute call, but we do not resolve it for nameres collection. - // This is just a trick to be able to resolve the input to derives as proper paths. + // This is just a trick to be able to resolve the input to derives + // as proper paths in `Semantics`. // Check the comment in [`builtin_attr_macro`]. let call_id = attr_macro_as_call_id( self.db, diff --git a/crates/hir-expand/src/ast_id_map.rs b/crates/hir-expand/src/ast_id_map.rs index 7bdd6db9321cb..530f10a06847e 100644 --- a/crates/hir-expand/src/ast_id_map.rs +++ b/crates/hir-expand/src/ast_id_map.rs @@ -155,7 +155,14 @@ impl PartialEq for AstIdMap { impl Eq for AstIdMap {} impl AstIdMap { - pub(crate) fn from_source(node: &SyntaxNode) -> AstIdMap { + pub(crate) fn ast_id_map( + db: &dyn ExpandDatabase, + file_id: span::HirFileId, + ) -> triomphe::Arc { + triomphe::Arc::new(AstIdMap::from_source(&db.parse_or_expand(file_id))) + } + + fn from_source(node: &SyntaxNode) -> AstIdMap { assert!(node.parent().is_none()); let mut res = AstIdMap::default(); diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs index 67a318afd062c..30d38299d99d4 100644 --- a/crates/hir-expand/src/attrs.rs +++ b/crates/hir-expand/src/attrs.rs @@ -117,14 +117,10 @@ impl RawAttrs { None => return smallvec![attr.clone()], }; let index = attr.id; - let attrs = - parts.enumerate().take(1 << AttrId::CFG_ATTR_BITS).filter_map(|(idx, attr)| { - let tree = Subtree { - delimiter: tt::Delimiter::invisible_spanned(attr.first()?.first_span()), - token_trees: attr.to_vec(), - }; - Attr::from_tt(db, &tree, index.with_cfg_attr(idx)) - }); + let attrs = parts + .enumerate() + .take(1 << AttrId::CFG_ATTR_BITS) + .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx))); let cfg_options = &crate_graph[krate].cfg_options; let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() }; @@ -222,12 +218,40 @@ impl Attr { Some(Attr { id, path, input, span }) } - fn from_tt(db: &dyn ExpandDatabase, tt: &tt::Subtree, id: AttrId) -> Option { - // FIXME: Unecessary roundtrip tt -> ast -> tt - let (parse, map) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MetaItem); - let ast = ast::Meta::cast(parse.syntax_node())?; - - Self::from_src(db, ast, SpanMapRef::ExpansionSpanMap(&map), id) + fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree], id: AttrId) -> Option { + let span = tt.first()?.first_span(); + let path_end = tt + .iter() + .position(|tt| { + !matches!( + tt, + tt::TokenTree::Leaf( + tt::Leaf::Punct(tt::Punct { char: ':' | '$', .. }) | tt::Leaf::Ident(_), + ) + ) + }) + .unwrap_or_else(|| tt.len()); + + let (path, input) = tt.split_at(path_end); + let path = Interned::new(ModPath::from_tt(db, path)?); + + let input = match input.get(0) { + Some(tt::TokenTree::Subtree(tree)) => { + Some(Interned::new(AttrInput::TokenTree(Box::new(tree.clone())))) + } + Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. }))) => { + let input = match input.get(1) { + Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { text, .. }))) => { + //FIXME the trimming here isn't quite right, raw strings are not handled + Some(Interned::new(AttrInput::Literal(text.trim_matches('"').into()))) + } + _ => None, + }; + input + } + _ => None, + }; + Some(Attr { id, path, input, span }) } pub fn path(&self) -> &ModPath { @@ -277,29 +301,8 @@ impl Attr { .token_trees .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. })))) .filter_map(move |tts| { - if tts.is_empty() { - return None; - } - // FIXME: This is necessarily a hack. It'd be nice if we could avoid allocation - // here or maybe just parse a mod path from a token tree directly - let subtree = tt::Subtree { - delimiter: tt::Delimiter::invisible_spanned(tts.first()?.first_span()), - token_trees: tts.to_vec(), - }; - let (parse, span_map) = - mbe::token_tree_to_syntax_node(&subtree, mbe::TopEntryPoint::MetaItem); - let meta = ast::Meta::cast(parse.syntax_node())?; - // Only simple paths are allowed. - if meta.eq_token().is_some() || meta.expr().is_some() || meta.token_tree().is_some() - { - return None; - } - let path = meta.path()?; - let call_site = span_map.span_at(path.syntax().text_range().start()); - Some(( - ModPath::from_src(db, path, SpanMapRef::ExpansionSpanMap(&span_map))?, - call_site, - )) + let span = tts.first()?.first_span(); + Some((ModPath::from_tt(db, tts)?, span)) }); Some(paths) diff --git a/crates/hir-expand/src/builtin_attr_macro.rs b/crates/hir-expand/src/builtin_attr_macro.rs index 55157abe671ad..dd2aa94ad01df 100644 --- a/crates/hir-expand/src/builtin_attr_macro.rs +++ b/crates/hir-expand/src/builtin_attr_macro.rs @@ -48,11 +48,13 @@ impl BuiltinAttrExpander { register_builtin! { expand: (bench, Bench) => dummy_attr_expand, + (cfg, Cfg) => dummy_attr_expand, + (cfg_attr, CfgAttr) => dummy_attr_expand, (cfg_accessible, CfgAccessible) => dummy_attr_expand, (cfg_eval, CfgEval) => dummy_attr_expand, - (derive, Derive) => derive_attr_expand, + (derive, Derive) => derive_expand, // derive const is equivalent to derive for our proposes. - (derive_const, DeriveConst) => derive_attr_expand, + (derive_const, DeriveConst) => derive_expand, (global_allocator, GlobalAllocator) => dummy_attr_expand, (test, Test) => dummy_attr_expand, (test_case, TestCase) => dummy_attr_expand @@ -91,7 +93,7 @@ fn dummy_attr_expand( /// always resolve as a derive without nameres recollecting them. /// So this hacky approach is a lot more friendly for us, though it does require a bit of support in /// [`hir::Semantics`] to make this work. -fn derive_attr_expand( +fn derive_expand( db: &dyn ExpandDatabase, id: MacroCallId, tt: &tt::Subtree, diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 2f8c0951b1439..8c43017971fb0 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -1,16 +1,11 @@ //! Defines database & queries for macro expansion. -use std::sync::OnceLock; - -use base_db::{ - salsa::{self, debug::DebugQueryTable}, - CrateId, Edition, FileId, SourceDatabase, VersionReq, -}; +use base_db::{salsa, CrateId, FileId, SourceDatabase}; use either::Either; use limit::Limit; use mbe::{syntax_node_to_token_tree, ValueResult}; use rustc_hash::FxHashSet; -use span::{Span, SyntaxContextId}; +use span::SyntaxContextId; use syntax::{ ast::{self, HasAttrs}, AstNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T, @@ -19,13 +14,14 @@ use triomphe::Arc; use crate::{ ast_id_map::AstIdMap, - attrs::{collect_attrs, RawAttrs}, + attrs::collect_attrs, builtin_attr_macro::pseudo_derive_attr_expansion, builtin_fn_macro::EagerExpander, + declarative::DeclarativeMacroExpander, fixup::{self, reverse_fixups, SyntaxFixupUndoInfo}, hygiene::{ - apply_mark, span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt, - SyntaxContextData, Transparency, + span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt, + SyntaxContextData, }, proc_macro::ProcMacros, span_map::{RealSpanMap, SpanMap, SpanMapRef}, @@ -43,82 +39,6 @@ use crate::{ /// Actual max for `analysis-stats .` at some point: 30672. static TOKEN_LIMIT: Limit = Limit::new(1_048_576); -#[derive(Debug, Clone, Eq, PartialEq)] -/// Old-style `macro_rules` or the new macros 2.0 -pub struct DeclarativeMacroExpander { - pub mac: mbe::DeclarativeMacro, - pub transparency: Transparency, -} - -// FIXME: Remove this once we drop support for 1.76 -static REQUIREMENT: OnceLock = OnceLock::new(); - -impl DeclarativeMacroExpander { - pub fn expand( - &self, - db: &dyn ExpandDatabase, - tt: tt::Subtree, - call_id: MacroCallId, - ) -> ExpandResult { - let loc = db.lookup_intern_macro_call(call_id); - let toolchain = &db.crate_graph()[loc.def.krate].toolchain; - let new_meta_vars = toolchain.as_ref().map_or(false, |version| { - REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( - &base_db::Version { - pre: base_db::Prerelease::EMPTY, - build: base_db::BuildMetadata::EMPTY, - major: version.major, - minor: version.minor, - patch: version.patch, - }, - ) - }); - match self.mac.err() { - Some(e) => ExpandResult::new( - tt::Subtree::empty(tt::DelimSpan { open: loc.call_site, close: loc.call_site }), - ExpandError::other(format!("invalid macro definition: {e}")), - ), - None => self - .mac - .expand( - &tt, - |s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency), - new_meta_vars, - loc.call_site, - ) - .map_err(Into::into), - } - } - - pub fn expand_unhygienic( - &self, - db: &dyn ExpandDatabase, - tt: tt::Subtree, - krate: CrateId, - call_site: Span, - ) -> ExpandResult { - let toolchain = &db.crate_graph()[krate].toolchain; - let new_meta_vars = toolchain.as_ref().map_or(false, |version| { - REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( - &base_db::Version { - pre: base_db::Prerelease::EMPTY, - build: base_db::BuildMetadata::EMPTY, - major: version.major, - minor: version.minor, - patch: version.patch, - }, - ) - }); - match self.mac.err() { - Some(e) => ExpandResult::new( - tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }), - ExpandError::other(format!("invalid macro definition: {e}")), - ), - None => self.mac.expand(&tt, |_| (), new_meta_vars, call_site).map_err(Into::into), - } - } -} - #[derive(Debug, Clone, Eq, PartialEq)] pub enum TokenExpander { /// Old-style `macro_rules` or the new macros 2.0 @@ -141,6 +61,7 @@ pub trait ExpandDatabase: SourceDatabase { #[salsa::input] fn proc_macros(&self) -> Arc; + #[salsa::invoke(AstIdMap::ast_id_map)] fn ast_id_map(&self, file_id: HirFileId) -> Arc; /// Main public API -- parses a hir file, not caring whether it's a real @@ -156,8 +77,10 @@ pub trait ExpandDatabase: SourceDatabase { macro_file: MacroFileId, ) -> ExpandResult<(Parse, Arc)>; #[salsa::transparent] + #[salsa::invoke(SpanMap::new)] fn span_map(&self, file_id: HirFileId) -> SpanMap; + #[salsa::invoke(crate::span_map::real_span_map)] fn real_span_map(&self, file_id: FileId) -> Arc; /// Macro ids. That's probably the tricksiest bit in rust-analyzer, and the @@ -173,6 +96,7 @@ pub trait ExpandDatabase: SourceDatabase { #[salsa::transparent] fn setup_syntax_context_root(&self) -> (); #[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 @@ -184,8 +108,10 @@ pub trait ExpandDatabase: SourceDatabase { ) -> ValueResult, SyntaxFixupUndoInfo)>, Arc>>; /// Fetches the expander for this macro. #[salsa::transparent] + #[salsa::invoke(TokenExpander::macro_expander)] fn macro_expander(&self, id: MacroDefId) -> TokenExpander; /// Fetches (and compiles) the expander of this decl macro. + #[salsa::invoke(DeclarativeMacroExpander::expander)] fn decl_macro_expander( &self, def_crate: CrateId, @@ -203,36 +129,6 @@ pub trait ExpandDatabase: SourceDatabase { ) -> ExpandResult>; } -#[inline] -pub fn span_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> SpanMap { - match file_id.repr() { - HirFileIdRepr::FileId(file_id) => SpanMap::RealSpanMap(db.real_span_map(file_id)), - HirFileIdRepr::MacroFile(m) => { - SpanMap::ExpansionSpanMap(db.parse_macro_expansion(m).value.1) - } - } -} - -pub fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> 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 tree = db.parse(file_id).tree(); - // FIXME: Descend into modules and other item containing items that are not annotated with attributes - // and allocate pairs for those as well. This gives us finer grained span anchors resulting in - // better incrementality - pairs.extend( - tree.items() - .map(|item| (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())), - ); - - Arc::new(RealSpanMap::from_file( - file_id, - pairs.into_boxed_slice(), - tree.syntax().text_range().end(), - )) -} - /// This expands the given macro call, but with different arguments. This is /// used for completion, where we want to see what 'would happen' if we insert a /// token. The `token_to_map` mapped down into the expansion, with the mapped @@ -357,10 +253,6 @@ pub fn expand_speculative( Some((node.syntax_node(), token)) } -fn ast_id_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> Arc { - Arc::new(AstIdMap::from_source(&db.parse_or_expand(file_id))) -} - 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(), @@ -412,7 +304,10 @@ fn parse_macro_expansion_error( .map(|it| it.0.errors().to_vec().into_boxed_slice()) } -fn parse_with_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> (Parse, SpanMap) { +pub(crate) fn parse_with_map( + db: &dyn ExpandDatabase, + 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))) @@ -581,100 +476,18 @@ fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet, -) -> Arc { - let crate_data = &db.crate_graph()[def_crate]; - let is_2021 = crate_data.edition >= Edition::Edition2021; - let (root, map) = parse_with_map(db, id.file_id); - let root = root.syntax_node(); - - let transparency = |node| { - // ... would be nice to have the item tree here - let attrs = RawAttrs::new(db, node, map.as_ref()).filter(db, def_crate); - match &*attrs - .iter() - .find(|it| { - it.path.as_ident().and_then(|it| it.as_str()) == Some("rustc_macro_transparency") - })? - .token_tree_value()? - .token_trees - { - [tt::TokenTree::Leaf(tt::Leaf::Ident(i)), ..] => match &*i.text { - "transparent" => Some(Transparency::Transparent), - "semitransparent" => Some(Transparency::SemiTransparent), - "opaque" => Some(Transparency::Opaque), - _ => None, - }, - _ => None, - } - }; - let toolchain = crate_data.toolchain.as_ref(); - let new_meta_vars = toolchain.as_ref().map_or(false, |version| { - REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( - &base_db::Version { - pre: base_db::Prerelease::EMPTY, - build: base_db::BuildMetadata::EMPTY, - major: version.major, - minor: version.minor, - patch: version.patch, - }, - ) - }); - - let (mac, transparency) = match id.to_ptr(db).to_node(&root) { - ast::Macro::MacroRules(macro_rules) => ( - match macro_rules.token_tree() { - Some(arg) => { - let tt = mbe::syntax_node_to_token_tree( - arg.syntax(), - map.as_ref(), - map.span_for_range(macro_rules.macro_rules_token().unwrap().text_range()), - ); - - mbe::DeclarativeMacro::parse_macro_rules(&tt, is_2021, new_meta_vars) - } - None => mbe::DeclarativeMacro::from_err( - mbe::ParseError::Expected("expected a token tree".into()), - is_2021, - ), - }, - transparency(¯o_rules).unwrap_or(Transparency::SemiTransparent), - ), - ast::Macro::MacroDef(macro_def) => ( - match macro_def.body() { - Some(arg) => { - let tt = mbe::syntax_node_to_token_tree( - arg.syntax(), - map.as_ref(), - map.span_for_range(macro_def.macro_token().unwrap().text_range()), - ); - - mbe::DeclarativeMacro::parse_macro2(&tt, is_2021, new_meta_vars) - } - None => mbe::DeclarativeMacro::from_err( - mbe::ParseError::Expected("expected a token tree".into()), - is_2021, - ), - }, - transparency(¯o_def).unwrap_or(Transparency::Opaque), - ), - }; - Arc::new(DeclarativeMacroExpander { mac, transparency }) -} - -fn macro_expander(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander { - match id.kind { - MacroDefKind::Declarative(ast_id) => { - TokenExpander::DeclarativeMacro(db.decl_macro_expander(id.krate, ast_id)) +impl TokenExpander { + fn macro_expander(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander { + match id.kind { + MacroDefKind::Declarative(ast_id) => { + TokenExpander::DeclarativeMacro(db.decl_macro_expander(id.krate, ast_id)) + } + MacroDefKind::BuiltIn(expander, _) => TokenExpander::BuiltIn(expander), + MacroDefKind::BuiltInAttr(expander, _) => TokenExpander::BuiltInAttr(expander), + MacroDefKind::BuiltInDerive(expander, _) => TokenExpander::BuiltInDerive(expander), + MacroDefKind::BuiltInEager(expander, ..) => TokenExpander::BuiltInEager(expander), + MacroDefKind::ProcMacro(expander, ..) => TokenExpander::ProcMacro(expander), } - MacroDefKind::BuiltIn(expander, _) => TokenExpander::BuiltIn(expander), - MacroDefKind::BuiltInAttr(expander, _) => TokenExpander::BuiltInAttr(expander), - MacroDefKind::BuiltInDerive(expander, _) => TokenExpander::BuiltInDerive(expander), - MacroDefKind::BuiltInEager(expander, ..) => TokenExpander::BuiltInEager(expander), - MacroDefKind::ProcMacro(expander, ..) => TokenExpander::ProcMacro(expander), } } @@ -862,40 +675,3 @@ fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<()>> { fn setup_syntax_context_root(db: &dyn ExpandDatabase) { db.intern_syntax_context(SyntaxContextData::root()); } - -fn dump_syntax_contexts(db: &dyn ExpandDatabase) -> String { - 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(); - s.push_str(&format!( - "\n{:?}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}", - id, - expn_data.kind.file_id(), - expn_data.call_site, - SyntaxContextId::ROOT, // FIXME expn_data.def_site, - expn_data.kind.descr(), - )); - } - - s.push_str("\n\nSyntaxContexts:\n"); - let mut entries = InternSyntaxContextLookupQuery.in_db(db).entries::>(); - entries.sort_by_key(|e| e.key); - for e in entries { - struct SyntaxContextDebug<'a>( - &'a dyn ExpandDatabase, - SyntaxContextId, - &'a SyntaxContextData, - ); - - impl<'a> std::fmt::Debug for SyntaxContextDebug<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.2.fancy_debug(self.1, self.0, f) - } - } - stdx::format_to!(s, "{:?}\n", SyntaxContextDebug(db, e.key, &e.value.unwrap())); - } - s -} diff --git a/crates/hir-expand/src/declarative.rs b/crates/hir-expand/src/declarative.rs new file mode 100644 index 0000000000000..37084ee8b93c9 --- /dev/null +++ b/crates/hir-expand/src/declarative.rs @@ -0,0 +1,177 @@ +//! Compiled declarative macro expanders (`macro_rules!`` and `macro`) +use std::sync::OnceLock; + +use base_db::{CrateId, Edition, VersionReq}; +use span::{MacroCallId, Span}; +use syntax::{ast, AstNode}; +use triomphe::Arc; + +use crate::{ + attrs::RawAttrs, + db::ExpandDatabase, + hygiene::{apply_mark, Transparency}, + tt, AstId, ExpandError, ExpandResult, +}; + +/// Old-style `macro_rules` or the new macros 2.0 +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct DeclarativeMacroExpander { + pub mac: mbe::DeclarativeMacro, + pub transparency: Transparency, +} + +// FIXME: Remove this once we drop support for 1.76 +static REQUIREMENT: OnceLock = OnceLock::new(); + +impl DeclarativeMacroExpander { + pub fn expand( + &self, + db: &dyn ExpandDatabase, + tt: tt::Subtree, + call_id: MacroCallId, + ) -> ExpandResult { + let loc = db.lookup_intern_macro_call(call_id); + let toolchain = &db.crate_graph()[loc.def.krate].toolchain; + let new_meta_vars = toolchain.as_ref().map_or(false, |version| { + REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( + &base_db::Version { + pre: base_db::Prerelease::EMPTY, + build: base_db::BuildMetadata::EMPTY, + major: version.major, + minor: version.minor, + patch: version.patch, + }, + ) + }); + match self.mac.err() { + Some(e) => ExpandResult::new( + tt::Subtree::empty(tt::DelimSpan { open: loc.call_site, close: loc.call_site }), + ExpandError::other(format!("invalid macro definition: {e}")), + ), + None => self + .mac + .expand( + &tt, + |s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency), + new_meta_vars, + loc.call_site, + ) + .map_err(Into::into), + } + } + + pub fn expand_unhygienic( + &self, + db: &dyn ExpandDatabase, + tt: tt::Subtree, + krate: CrateId, + call_site: Span, + ) -> ExpandResult { + let toolchain = &db.crate_graph()[krate].toolchain; + let new_meta_vars = toolchain.as_ref().map_or(false, |version| { + REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( + &base_db::Version { + pre: base_db::Prerelease::EMPTY, + build: base_db::BuildMetadata::EMPTY, + major: version.major, + minor: version.minor, + patch: version.patch, + }, + ) + }); + match self.mac.err() { + Some(e) => ExpandResult::new( + tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }), + ExpandError::other(format!("invalid macro definition: {e}")), + ), + None => self.mac.expand(&tt, |_| (), new_meta_vars, call_site).map_err(Into::into), + } + } + + pub(crate) fn expander( + db: &dyn ExpandDatabase, + def_crate: CrateId, + id: AstId, + ) -> Arc { + let crate_data = &db.crate_graph()[def_crate]; + let is_2021 = crate_data.edition >= Edition::Edition2021; + let (root, map) = crate::db::parse_with_map(db, id.file_id); + let root = root.syntax_node(); + + let transparency = |node| { + // ... would be nice to have the item tree here + let attrs = RawAttrs::new(db, node, map.as_ref()).filter(db, def_crate); + match &*attrs + .iter() + .find(|it| { + it.path.as_ident().and_then(|it| it.as_str()) + == Some("rustc_macro_transparency") + })? + .token_tree_value()? + .token_trees + { + [tt::TokenTree::Leaf(tt::Leaf::Ident(i)), ..] => match &*i.text { + "transparent" => Some(Transparency::Transparent), + "semitransparent" => Some(Transparency::SemiTransparent), + "opaque" => Some(Transparency::Opaque), + _ => None, + }, + _ => None, + } + }; + let toolchain = crate_data.toolchain.as_ref(); + let new_meta_vars = toolchain.as_ref().map_or(false, |version| { + REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches( + &base_db::Version { + pre: base_db::Prerelease::EMPTY, + build: base_db::BuildMetadata::EMPTY, + major: version.major, + minor: version.minor, + patch: version.patch, + }, + ) + }); + + let (mac, transparency) = match id.to_ptr(db).to_node(&root) { + ast::Macro::MacroRules(macro_rules) => ( + match macro_rules.token_tree() { + Some(arg) => { + let tt = mbe::syntax_node_to_token_tree( + arg.syntax(), + map.as_ref(), + map.span_for_range( + macro_rules.macro_rules_token().unwrap().text_range(), + ), + ); + + mbe::DeclarativeMacro::parse_macro_rules(&tt, is_2021, new_meta_vars) + } + None => mbe::DeclarativeMacro::from_err( + mbe::ParseError::Expected("expected a token tree".into()), + is_2021, + ), + }, + transparency(¯o_rules).unwrap_or(Transparency::SemiTransparent), + ), + ast::Macro::MacroDef(macro_def) => ( + match macro_def.body() { + Some(arg) => { + let tt = mbe::syntax_node_to_token_tree( + arg.syntax(), + map.as_ref(), + map.span_for_range(macro_def.macro_token().unwrap().text_range()), + ); + + mbe::DeclarativeMacro::parse_macro2(&tt, is_2021, new_meta_vars) + } + None => mbe::DeclarativeMacro::from_err( + mbe::ParseError::Expected("expected a token tree".into()), + is_2021, + ), + }, + transparency(¯o_def).unwrap_or(Transparency::Opaque), + ), + }; + Arc::new(DeclarativeMacroExpander { mac, transparency }) + } +} diff --git a/crates/hir-expand/src/hygiene.rs b/crates/hir-expand/src/hygiene.rs index 57921543c4b4b..8ddaa3f3039ec 100644 --- a/crates/hir-expand/src/hygiene.rs +++ b/crates/hir-expand/src/hygiene.rs @@ -245,3 +245,43 @@ pub fn marks_rev( }) .map(|ctx| ctx.outer_mark(db)) } + +pub(crate) fn dump_syntax_contexts(db: &dyn ExpandDatabase) -> String { + use crate::db::{InternMacroCallLookupQuery, InternSyntaxContextLookupQuery}; + use base_db::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(); + s.push_str(&format!( + "\n{:?}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}", + id, + expn_data.kind.file_id(), + expn_data.call_site, + SyntaxContextId::ROOT, // FIXME expn_data.def_site, + expn_data.kind.descr(), + )); + } + + s.push_str("\n\nSyntaxContexts:\n"); + let mut entries = InternSyntaxContextLookupQuery.in_db(db).entries::>(); + entries.sort_by_key(|e| e.key); + for e in entries { + struct SyntaxContextDebug<'a>( + &'a dyn ExpandDatabase, + SyntaxContextId, + &'a SyntaxContextData, + ); + + impl<'a> std::fmt::Debug for SyntaxContextDebug<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.2.fancy_debug(self.1, self.0, f) + } + } + stdx::format_to!(s, "{:?}\n", SyntaxContextDebug(db, e.key, &e.value.unwrap())); + } + s +} diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index bd216ccca8239..05f12527a4400 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -11,16 +11,18 @@ pub mod attrs; pub mod builtin_attr_macro; pub mod builtin_derive_macro; pub mod builtin_fn_macro; +pub mod change; pub mod db; +pub mod declarative; pub mod eager; pub mod files; -pub mod change; pub mod hygiene; pub mod mod_path; pub mod name; pub mod proc_macro; pub mod quote; pub mod span_map; + mod fixup; use attrs::collect_attrs; @@ -167,7 +169,8 @@ pub struct MacroCallLoc { pub krate: CrateId, /// Some if this is a macro call for an eager macro. Note that this is `None` /// for the eager input macro file. - // FIXME: This seems bad to save in an interned structure + // FIXME: This is being interned, subtrees can vary quickly differ just slightly causing + // leakage problems here eager: Option>, pub kind: MacroCallKind, pub call_site: Span, @@ -220,7 +223,7 @@ pub enum MacroCallKind { }, Attr { ast_id: AstId, - // FIXME: This is being interned, subtrees can very quickly differ just slightly causing + // FIXME: This is being interned, subtrees can vary quickly differ just slightly causing // leakage problems here attr_args: Option>, /// Syntactical index of the invoking `#[attribute]`. diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 47a587e407c52..0eb1fc1eb5009 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -10,6 +10,7 @@ use crate::{ hygiene::{marks_rev, SyntaxContextExt, Transparency}, name::{known, AsName, Name}, span_map::SpanMapRef, + tt, }; use base_db::CrateId; use smallvec::SmallVec; @@ -39,7 +40,7 @@ pub enum PathKind { Crate, /// Absolute path (::foo) Abs, - // FIXME: Remove this + // FIXME: Can we remove this somehow? /// `$crate` from macro expansion DollarCrate(CrateId), } @@ -50,11 +51,16 @@ impl ModPath { path: ast::Path, span_map: SpanMapRef<'_>, ) -> Option { - convert_path(db, None, path, span_map) + convert_path(db, path, span_map) + } + + pub fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option { + convert_path_tt(db, tt) } pub fn from_segments(kind: PathKind, segments: impl IntoIterator) -> ModPath { - let segments = segments.into_iter().collect(); + let mut segments: SmallVec<_> = segments.into_iter().collect(); + segments.shrink_to_fit(); ModPath { kind, segments } } @@ -193,22 +199,15 @@ fn display_fmt_path( fn convert_path( db: &dyn ExpandDatabase, - prefix: Option, path: ast::Path, span_map: SpanMapRef<'_>, ) -> Option { - let prefix = match path.qualifier() { - Some(qual) => Some(convert_path(db, prefix, qual, span_map)?), - None => prefix, - }; + let mut segments = path.segments(); - let segment = path.segment()?; + let segment = &segments.next()?; let mut mod_path = match segment.kind()? { ast::PathSegmentKind::Name(name_ref) => { if name_ref.text() == "$crate" { - if prefix.is_some() { - return None; - } ModPath::from_kind( resolve_crate_root( db, @@ -218,41 +217,36 @@ fn convert_path( .unwrap_or(PathKind::Crate), ) } else { - let mut res = prefix.unwrap_or_else(|| { - ModPath::from_kind( - segment.coloncolon_token().map_or(PathKind::Plain, |_| PathKind::Abs), - ) - }); + let mut res = ModPath::from_kind( + segment.coloncolon_token().map_or(PathKind::Plain, |_| PathKind::Abs), + ); res.segments.push(name_ref.as_name()); res } } ast::PathSegmentKind::SelfTypeKw => { - if prefix.is_some() { - return None; - } ModPath::from_segments(PathKind::Plain, Some(known::SELF_TYPE)) } - ast::PathSegmentKind::CrateKw => { - if prefix.is_some() { - return None; - } - ModPath::from_segments(PathKind::Crate, iter::empty()) - } - ast::PathSegmentKind::SelfKw => { - if prefix.is_some() { - return None; - } - ModPath::from_segments(PathKind::Super(0), iter::empty()) - } + ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()), + ast::PathSegmentKind::SelfKw => ModPath::from_segments(PathKind::Super(0), iter::empty()), ast::PathSegmentKind::SuperKw => { - let nested_super_count = match prefix.map(|p| p.kind) { - Some(PathKind::Super(n)) => n, - Some(_) => return None, - None => 0, - }; + let mut deg = 1; + let mut next_segment = None; + while let Some(segment) = segments.next() { + match segment.kind()? { + ast::PathSegmentKind::SuperKw => deg += 1, + ast::PathSegmentKind::Name(name) => { + next_segment = Some(name.as_name()); + break; + } + ast::PathSegmentKind::Type { .. } + | ast::PathSegmentKind::SelfTypeKw + | ast::PathSegmentKind::SelfKw + | ast::PathSegmentKind::CrateKw => return None, + } + } - ModPath::from_segments(PathKind::Super(nested_super_count + 1), iter::empty()) + ModPath::from_segments(PathKind::Super(deg), next_segment) } ast::PathSegmentKind::Type { .. } => { // not allowed in imports @@ -260,6 +254,14 @@ fn convert_path( } }; + for segment in segments { + let name = match segment.kind()? { + ast::PathSegmentKind::Name(name) => name.as_name(), + _ => return None, + }; + mod_path.segments.push(name); + } + // handle local_inner_macros : // Basically, even in rustc it is quite hacky: // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 @@ -281,6 +283,46 @@ fn convert_path( Some(mod_path) } +fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option { + let mut leafs = tt.iter().filter_map(|tt| match tt { + tt::TokenTree::Leaf(leaf) => Some(leaf), + tt::TokenTree::Subtree(_) => None, + }); + let mut segments = smallvec::smallvec![]; + let kind = match leafs.next()? { + tt::Leaf::Punct(tt::Punct { char: ':', .. }) => match leafs.next()? { + tt::Leaf::Punct(tt::Punct { char: ':', .. }) => PathKind::Abs, + _ => return None, + }, + tt::Leaf::Ident(tt::Ident { text, span }) if text == "$crate" => { + resolve_crate_root(db, span.ctx).map(PathKind::DollarCrate).unwrap_or(PathKind::Crate) + } + tt::Leaf::Ident(tt::Ident { text, .. }) if text == "self" => PathKind::Super(0), + tt::Leaf::Ident(tt::Ident { text, .. }) if text == "super" => { + let mut deg = 1; + while let Some(tt::Leaf::Ident(tt::Ident { text, .. })) = leafs.next() { + if text != "super" { + segments.push(Name::new_text_dont_use(text.clone())); + break; + } + deg += 1; + } + PathKind::Super(deg) + } + tt::Leaf::Ident(tt::Ident { text, .. }) if text == "crate" => PathKind::Crate, + tt::Leaf::Ident(ident) => { + segments.push(Name::new_text_dont_use(ident.text.clone())); + PathKind::Plain + } + _ => return None, + }; + segments.extend(leafs.filter_map(|leaf| match leaf { + ::tt::Leaf::Ident(ident) => Some(Name::new_text_dont_use(ident.text.clone())), + _ => None, + })); + Some(ModPath { kind, segments }) +} + 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` diff --git a/crates/hir-expand/src/span_map.rs b/crates/hir-expand/src/span_map.rs index 4ec6e657f9ed9..8e624f5585d48 100644 --- a/crates/hir-expand/src/span_map.rs +++ b/crates/hir-expand/src/span_map.rs @@ -1,10 +1,12 @@ //! Span maps for real files and macro expansions. -use span::Span; -use syntax::TextRange; +use span::{FileId, HirFileId, HirFileIdRepr, Span}; +use syntax::{AstNode, TextRange}; use triomphe::Arc; pub use span::RealSpanMap; +use crate::db::ExpandDatabase; + pub type ExpansionSpanMap = span::SpanMap; /// Spanmap for a macro file or a real file @@ -34,7 +36,6 @@ impl mbe::SpanMapper for SpanMapRef<'_> { self.span_for_range(range) } } - impl SpanMap { pub fn span_for_range(&self, range: TextRange) -> Span { match self { @@ -53,6 +54,16 @@ impl SpanMap { Self::RealSpanMap(span_map) => SpanMapRef::RealSpanMap(span_map), } } + + #[inline] + pub(crate) fn new(db: &dyn ExpandDatabase, file_id: HirFileId) -> SpanMap { + match file_id.repr() { + HirFileIdRepr::FileId(file_id) => SpanMap::RealSpanMap(db.real_span_map(file_id)), + HirFileIdRepr::MacroFile(m) => { + SpanMap::ExpansionSpanMap(db.parse_macro_expansion(m).value.1) + } + } + } } impl SpanMapRef<'_> { @@ -63,3 +74,23 @@ impl SpanMapRef<'_> { } } } + +pub(crate) fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> 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 tree = db.parse(file_id).tree(); + // FIXME: Descend into modules and other item containing items that are not annotated with attributes + // and allocate pairs for those as well. This gives us finer grained span anchors resulting in + // better incrementality + pairs.extend( + tree.items() + .map(|item| (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())), + ); + + Arc::new(RealSpanMap::from_file( + file_id, + pairs.into_boxed_slice(), + tree.syntax().text_range().end(), + )) +} diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml index 822a7d3e91956..1f8f8744f9ebe 100644 --- a/crates/hir-ty/Cargo.toml +++ b/crates/hir-ty/Cargo.toml @@ -36,6 +36,7 @@ indexmap.workspace = true ra-ap-rustc_abi.workspace = true ra-ap-rustc_index.workspace = true +ra-ap-rustc_pattern_analysis.workspace = true # local deps diff --git a/crates/hir-ty/src/diagnostics.rs b/crates/hir-ty/src/diagnostics.rs index c1b3619009bd4..af4d2c9fc0461 100644 --- a/crates/hir-ty/src/diagnostics.rs +++ b/crates/hir-ty/src/diagnostics.rs @@ -1,8 +1,8 @@ //! Type inference-based diagnostics. +mod decl_check; mod expr; mod match_check; mod unsafe_check; -mod decl_check; pub use crate::diagnostics::{ decl_check::{incorrect_case, CaseType, IncorrectCase}, diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index f1bf162bc6bfd..530608292e6fd 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -11,6 +11,7 @@ use hir_def::{ItemContainerId, Lookup}; use hir_expand::name; use itertools::Itertools; use rustc_hash::FxHashSet; +use rustc_pattern_analysis::usefulness::{compute_match_usefulness, ValidityConstraint}; use triomphe::Arc; use typed_arena::Arena; @@ -18,8 +19,7 @@ use crate::{ db::HirDatabase, diagnostics::match_check::{ self, - deconstruct_pat::DeconstructedPat, - usefulness::{compute_match_usefulness, MatchCheckCtx}, + pat_analysis::{self, DeconstructedPat, MatchCheckCtx, WitnessPat}, }, display::HirDisplay, InferenceResult, Ty, TyExt, @@ -152,7 +152,14 @@ impl ExprValidator { } let pattern_arena = Arena::new(); - let cx = MatchCheckCtx::new(self.owner.module(db.upcast()), self.owner, db, &pattern_arena); + let ty_arena = Arena::new(); + let cx = MatchCheckCtx::new( + self.owner.module(db.upcast()), + self.owner, + db, + &pattern_arena, + &ty_arena, + ); let mut m_arms = Vec::with_capacity(arms.len()); let mut has_lowering_errors = false; @@ -178,9 +185,10 @@ impl ExprValidator { // If we had a NotUsefulMatchArm diagnostic, we could // check the usefulness of each pattern as we added it // to the matrix here. - let m_arm = match_check::MatchArm { + let m_arm = pat_analysis::MatchArm { pat: self.lower_pattern(&cx, arm.pat, db, &body, &mut has_lowering_errors), has_guard: arm.guard.is_some(), + arm_data: (), }; m_arms.push(m_arm); if !has_lowering_errors { @@ -197,7 +205,15 @@ impl ExprValidator { return; } - let report = compute_match_usefulness(&cx, &m_arms, scrut_ty); + let report = match compute_match_usefulness( + rustc_pattern_analysis::MatchCtxt { tycx: &cx }, + m_arms.as_slice(), + scrut_ty.clone(), + ValidityConstraint::ValidOnly, + ) { + Ok(report) => report, + Err(void) => match void {}, + }; // FIXME Report unreachable arms // https://github.com/rust-lang/rust/blob/f31622a50/compiler/rustc_mir_build/src/thir/pattern/check_match.rs#L200 @@ -213,7 +229,7 @@ impl ExprValidator { fn lower_pattern<'p>( &self, - cx: &MatchCheckCtx<'_, 'p>, + cx: &MatchCheckCtx<'p>, pat: PatId, db: &dyn HirDatabase, body: &Body, @@ -221,7 +237,7 @@ impl ExprValidator { ) -> &'p DeconstructedPat<'p> { let mut patcx = match_check::PatCtxt::new(db, &self.infer, body); let pattern = patcx.lower_pattern(pat); - let pattern = cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern)); + let pattern = cx.pattern_arena.alloc(cx.lower_pat(&pattern)); if !patcx.errors.is_empty() { *have_errors = true; } @@ -364,16 +380,16 @@ fn types_of_subpatterns_do_match(pat: PatId, body: &Body, infer: &InferenceResul } fn missing_match_arms<'p>( - cx: &MatchCheckCtx<'_, 'p>, + cx: &MatchCheckCtx<'p>, scrut_ty: &Ty, - witnesses: Vec>, + witnesses: Vec>, arms: &[MatchArm], ) -> String { - struct DisplayWitness<'a, 'p>(&'a DeconstructedPat<'p>, &'a MatchCheckCtx<'a, 'p>); + struct DisplayWitness<'a, 'p>(&'a WitnessPat<'p>, &'a MatchCheckCtx<'p>); impl fmt::Display for DisplayWitness<'_, '_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let DisplayWitness(witness, cx) = *self; - let pat = witness.to_pat(cx); + let pat = cx.hoist_witness_pat(witness); write!(f, "{}", pat.display(cx.db)) } } diff --git a/crates/hir-ty/src/diagnostics/match_check.rs b/crates/hir-ty/src/diagnostics/match_check.rs index e4d4536fc9321..8d6e502c6abe9 100644 --- a/crates/hir-ty/src/diagnostics/match_check.rs +++ b/crates/hir-ty/src/diagnostics/match_check.rs @@ -7,8 +7,7 @@ mod pat_util; -pub(crate) mod deconstruct_pat; -pub(crate) mod usefulness; +pub(crate) mod pat_analysis; use chalk_ir::Mutability; use hir_def::{ @@ -27,8 +26,6 @@ use crate::{ use self::pat_util::EnumerateAndAdjustIterator; -pub(crate) use self::usefulness::MatchArm; - #[derive(Clone, Debug)] pub(crate) enum PatternError { Unimplemented, @@ -413,98 +410,3 @@ where (self.0)(f) } } - -pub(crate) trait PatternFoldable: Sized { - fn fold_with(&self, folder: &mut F) -> Self { - self.super_fold_with(folder) - } - - fn super_fold_with(&self, folder: &mut F) -> Self; -} - -pub(crate) trait PatternFolder: Sized { - fn fold_pattern(&mut self, pattern: &Pat) -> Pat { - pattern.super_fold_with(self) - } - - fn fold_pattern_kind(&mut self, kind: &PatKind) -> PatKind { - kind.super_fold_with(self) - } -} - -impl PatternFoldable for Box { - fn super_fold_with(&self, folder: &mut F) -> Self { - let content: T = (**self).fold_with(folder); - Box::new(content) - } -} - -impl PatternFoldable for Vec { - fn super_fold_with(&self, folder: &mut F) -> Self { - self.iter().map(|t| t.fold_with(folder)).collect() - } -} - -impl PatternFoldable for Option { - fn super_fold_with(&self, folder: &mut F) -> Self { - self.as_ref().map(|t| t.fold_with(folder)) - } -} - -macro_rules! clone_impls { - ($($ty:ty),+) => { - $( - impl PatternFoldable for $ty { - fn super_fold_with(&self, _: &mut F) -> Self { - Clone::clone(self) - } - } - )+ - } -} - -clone_impls! { LocalFieldId, Ty, Substitution, EnumVariantId } - -impl PatternFoldable for FieldPat { - fn super_fold_with(&self, folder: &mut F) -> Self { - FieldPat { field: self.field.fold_with(folder), pattern: self.pattern.fold_with(folder) } - } -} - -impl PatternFoldable for Pat { - fn fold_with(&self, folder: &mut F) -> Self { - folder.fold_pattern(self) - } - - fn super_fold_with(&self, folder: &mut F) -> Self { - Pat { ty: self.ty.fold_with(folder), kind: self.kind.fold_with(folder) } - } -} - -impl PatternFoldable for PatKind { - fn fold_with(&self, folder: &mut F) -> Self { - folder.fold_pattern_kind(self) - } - - fn super_fold_with(&self, folder: &mut F) -> Self { - match self { - PatKind::Wild => PatKind::Wild, - PatKind::Binding { name, subpattern } => { - PatKind::Binding { name: name.clone(), subpattern: subpattern.fold_with(folder) } - } - PatKind::Variant { substs, enum_variant, subpatterns } => PatKind::Variant { - substs: substs.fold_with(folder), - enum_variant: enum_variant.fold_with(folder), - subpatterns: subpatterns.fold_with(folder), - }, - PatKind::Leaf { subpatterns } => { - PatKind::Leaf { subpatterns: subpatterns.fold_with(folder) } - } - PatKind::Deref { subpattern } => { - PatKind::Deref { subpattern: subpattern.fold_with(folder) } - } - &PatKind::LiteralBool { value } => PatKind::LiteralBool { value }, - PatKind::Or { pats } => PatKind::Or { pats: pats.fold_with(folder) }, - } - } -} diff --git a/crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs b/crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs deleted file mode 100644 index f066f8b798d6c..0000000000000 --- a/crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs +++ /dev/null @@ -1,1098 +0,0 @@ -//! [`super::usefulness`] explains most of what is happening in this file. As explained there, -//! values and patterns are made from constructors applied to fields. This file defines a -//! `Constructor` enum, a `Fields` struct, and various operations to manipulate them and convert -//! them from/to patterns. -//! -//! There's one idea that is not detailed in [`super::usefulness`] because the details are not -//! needed there: _constructor splitting_. -//! -//! # Constructor splitting -//! -//! The idea is as follows: given a constructor `c` and a matrix, we want to specialize in turn -//! with all the value constructors that are covered by `c`, and compute usefulness for each. -//! Instead of listing all those constructors (which is intractable), we group those value -//! constructors together as much as possible. Example: -//! -//! ``` -//! match (0, false) { -//! (0 ..=100, true) => {} // `p_1` -//! (50..=150, false) => {} // `p_2` -//! (0 ..=200, _) => {} // `q` -//! } -//! ``` -//! -//! The naive approach would try all numbers in the range `0..=200`. But we can be a lot more -//! clever: `0` and `1` for example will match the exact same rows, and return equivalent -//! witnesses. In fact all of `0..50` would. We can thus restrict our exploration to 4 -//! constructors: `0..50`, `50..=100`, `101..=150` and `151..=200`. That is enough and infinitely -//! more tractable. -//! -//! We capture this idea in a function `split(p_1 ... p_n, c)` which returns a list of constructors -//! `c'` covered by `c`. Given such a `c'`, we require that all value ctors `c''` covered by `c'` -//! return an equivalent set of witnesses after specializing and computing usefulness. -//! In the example above, witnesses for specializing by `c''` covered by `0..50` will only differ -//! in their first element. -//! -//! We usually also ask that the `c'` together cover all of the original `c`. However we allow -//! skipping some constructors as long as it doesn't change whether the resulting list of witnesses -//! is empty of not. We use this in the wildcard `_` case. -//! -//! Splitting is implemented in the [`Constructor::split`] function. We don't do splitting for -//! or-patterns; instead we just try the alternatives one-by-one. For details on splitting -//! wildcards, see [`SplitWildcard`]; for integer ranges, see [`SplitIntRange`]. - -use std::{ - cell::Cell, - cmp::{max, min}, - iter::once, - ops::RangeInclusive, -}; - -use hir_def::{EnumVariantId, HasModule, LocalFieldId, VariantId}; -use smallvec::{smallvec, SmallVec}; -use stdx::never; - -use crate::{ - infer::normalize, inhabitedness::is_enum_variant_uninhabited_from, AdtId, Interner, Scalar, Ty, - TyExt, TyKind, -}; - -use super::{ - is_box, - usefulness::{helper::Captures, MatchCheckCtx, PatCtxt}, - FieldPat, Pat, PatKind, -}; - -use self::Constructor::*; - -/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns. -fn expand_or_pat(pat: &Pat) -> Vec<&Pat> { - fn expand<'p>(pat: &'p Pat, vec: &mut Vec<&'p Pat>) { - if let PatKind::Or { pats } = pat.kind.as_ref() { - for pat in pats { - expand(pat, vec); - } - } else { - vec.push(pat) - } - } - - let mut pats = Vec::new(); - expand(pat, &mut pats); - pats -} - -/// [Constructor] uses this in unimplemented variants. -/// It allows porting match expressions from upstream algorithm without losing semantics. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub(super) enum Void {} - -/// An inclusive interval, used for precise integer exhaustiveness checking. -/// `IntRange`s always store a contiguous range. This means that values are -/// encoded such that `0` encodes the minimum value for the integer, -/// regardless of the signedness. -/// For example, the pattern `-128..=127i8` is encoded as `0..=255`. -/// This makes comparisons and arithmetic on interval endpoints much more -/// straightforward. See `signed_bias` for details. -/// -/// `IntRange` is never used to encode an empty range or a "range" that wraps -/// around the (offset) space: i.e., `range.lo <= range.hi`. -#[derive(Clone, Debug, PartialEq, Eq)] -pub(super) struct IntRange { - range: RangeInclusive, -} - -impl IntRange { - #[inline] - fn is_integral(ty: &Ty) -> bool { - matches!( - ty.kind(Interner), - TyKind::Scalar(Scalar::Char | Scalar::Int(_) | Scalar::Uint(_) | Scalar::Bool) - ) - } - - fn is_singleton(&self) -> bool { - self.range.start() == self.range.end() - } - - fn boundaries(&self) -> (u128, u128) { - (*self.range.start(), *self.range.end()) - } - - #[inline] - fn from_bool(value: bool) -> IntRange { - let val = value as u128; - IntRange { range: val..=val } - } - - #[inline] - fn from_range(lo: u128, hi: u128, scalar_ty: Scalar) -> IntRange { - match scalar_ty { - Scalar::Bool => IntRange { range: lo..=hi }, - _ => unimplemented!(), - } - } - - fn is_subrange(&self, other: &Self) -> bool { - other.range.start() <= self.range.start() && self.range.end() <= other.range.end() - } - - fn intersection(&self, other: &Self) -> Option { - let (lo, hi) = self.boundaries(); - let (other_lo, other_hi) = other.boundaries(); - if lo <= other_hi && other_lo <= hi { - Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi) }) - } else { - None - } - } - - fn to_pat(&self, _cx: &MatchCheckCtx<'_, '_>, ty: Ty) -> Pat { - match ty.kind(Interner) { - TyKind::Scalar(Scalar::Bool) => { - let kind = match self.boundaries() { - (0, 0) => PatKind::LiteralBool { value: false }, - (1, 1) => PatKind::LiteralBool { value: true }, - (0, 1) => PatKind::Wild, - (lo, hi) => { - never!("bad range for bool pattern: {}..={}", lo, hi); - PatKind::Wild - } - }; - Pat { ty, kind: kind.into() } - } - _ => unimplemented!(), - } - } - - /// See `Constructor::is_covered_by` - fn is_covered_by(&self, other: &Self) -> bool { - if self.intersection(other).is_some() { - // Constructor splitting should ensure that all intersections we encounter are actually - // inclusions. - assert!(self.is_subrange(other)); - true - } else { - false - } - } -} - -/// Represents a border between 2 integers. Because the intervals spanning borders must be able to -/// cover every integer, we need to be able to represent 2^128 + 1 such borders. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -enum IntBorder { - JustBefore(u128), - AfterMax, -} - -/// A range of integers that is partitioned into disjoint subranges. This does constructor -/// splitting for integer ranges as explained at the top of the file. -/// -/// This is fed multiple ranges, and returns an output that covers the input, but is split so that -/// the only intersections between an output range and a seen range are inclusions. No output range -/// straddles the boundary of one of the inputs. -/// -/// The following input: -/// ``` -/// |-------------------------| // `self` -/// |------| |----------| |----| -/// |-------| |-------| -/// ``` -/// would be iterated over as follows: -/// ``` -/// ||---|--||-|---|---|---|--| -/// ``` -#[derive(Debug, Clone)] -struct SplitIntRange { - /// The range we are splitting - range: IntRange, - /// The borders of ranges we have seen. They are all contained within `range`. This is kept - /// sorted. - borders: Vec, -} - -impl SplitIntRange { - fn new(range: IntRange) -> Self { - SplitIntRange { range, borders: Vec::new() } - } - - /// Internal use - fn to_borders(r: IntRange) -> [IntBorder; 2] { - use IntBorder::*; - let (lo, hi) = r.boundaries(); - let lo = JustBefore(lo); - let hi = match hi.checked_add(1) { - Some(m) => JustBefore(m), - None => AfterMax, - }; - [lo, hi] - } - - /// Add ranges relative to which we split. - fn split(&mut self, ranges: impl Iterator) { - let this_range = &self.range; - let included_ranges = ranges.filter_map(|r| this_range.intersection(&r)); - let included_borders = included_ranges.flat_map(|r| { - let borders = Self::to_borders(r); - once(borders[0]).chain(once(borders[1])) - }); - self.borders.extend(included_borders); - self.borders.sort_unstable(); - } - - /// Iterate over the contained ranges. - fn iter(&self) -> impl Iterator + '_ { - use IntBorder::*; - - let self_range = Self::to_borders(self.range.clone()); - // Start with the start of the range. - let mut prev_border = self_range[0]; - self.borders - .iter() - .copied() - // End with the end of the range. - .chain(once(self_range[1])) - // List pairs of adjacent borders. - .map(move |border| { - let ret = (prev_border, border); - prev_border = border; - ret - }) - // Skip duplicates. - .filter(|(prev_border, border)| prev_border != border) - // Finally, convert to ranges. - .map(|(prev_border, border)| { - let range = match (prev_border, border) { - (JustBefore(n), JustBefore(m)) if n < m => n..=(m - 1), - (JustBefore(n), AfterMax) => n..=u128::MAX, - _ => unreachable!(), // Ruled out by the sorting and filtering we did - }; - IntRange { range } - }) - } -} - -/// A constructor for array and slice patterns. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub(super) struct Slice { - _unimplemented: Void, -} - -impl Slice { - fn arity(self) -> usize { - match self._unimplemented {} - } - - /// See `Constructor::is_covered_by` - fn is_covered_by(self, _other: Self) -> bool { - match self._unimplemented {} - } -} - -/// A value can be decomposed into a constructor applied to some fields. This struct represents -/// the constructor. See also `Fields`. -/// -/// `pat_constructor` retrieves the constructor corresponding to a pattern. -/// `specialize_constructor` returns the list of fields corresponding to a pattern, given a -/// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and -/// `Fields`. -#[allow(dead_code)] -#[derive(Clone, Debug, PartialEq)] -pub(super) enum Constructor { - /// The constructor for patterns that have a single constructor, like tuples, struct patterns - /// and fixed-length arrays. - Single, - /// Enum variants. - Variant(EnumVariantId), - /// Ranges of integer literal values (`2`, `2..=5` or `2..5`). - IntRange(IntRange), - /// Ranges of floating-point literal values (`2.0..=5.2`). - FloatRange(Void), - /// String literals. Strings are not quite the same as `&[u8]` so we treat them separately. - Str(Void), - /// Array and slice patterns. - Slice(Slice), - /// Constants that must not be matched structurally. They are treated as black - /// boxes for the purposes of exhaustiveness: we must not inspect them, and they - /// don't count towards making a match exhaustive. - Opaque, - /// Fake extra constructor for enums that aren't allowed to be matched exhaustively. Also used - /// for those types for which we cannot list constructors explicitly, like `f64` and `str`. - NonExhaustive, - /// Stands for constructors that are not seen in the matrix, as explained in the documentation - /// for [`SplitWildcard`]. The carried `bool` is used for the `non_exhaustive_omitted_patterns` - /// lint. - Missing { nonexhaustive_enum_missing_real_variants: bool }, - /// Wildcard pattern. - Wildcard, - /// Or-pattern. - Or, -} - -impl Constructor { - pub(super) fn is_wildcard(&self) -> bool { - matches!(self, Wildcard) - } - - pub(super) fn is_non_exhaustive(&self) -> bool { - matches!(self, NonExhaustive) - } - - fn as_int_range(&self) -> Option<&IntRange> { - match self { - IntRange(range) => Some(range), - _ => None, - } - } - - fn as_slice(&self) -> Option { - match self { - Slice(slice) => Some(*slice), - _ => None, - } - } - - pub(super) fn is_unstable_variant(&self, _pcx: PatCtxt<'_, '_>) -> bool { - false //FIXME: implement this - } - - pub(super) fn is_doc_hidden_variant(&self, _pcx: PatCtxt<'_, '_>) -> bool { - false //FIXME: implement this - } - - fn variant_id_for_adt(&self, adt: hir_def::AdtId) -> VariantId { - match *self { - Variant(id) => id.into(), - Single => { - assert!(!matches!(adt, hir_def::AdtId::EnumId(_))); - match adt { - hir_def::AdtId::EnumId(_) => unreachable!(), - hir_def::AdtId::StructId(id) => id.into(), - hir_def::AdtId::UnionId(id) => id.into(), - } - } - _ => panic!("bad constructor {self:?} for adt {adt:?}"), - } - } - - /// The number of fields for this constructor. This must be kept in sync with - /// `Fields::wildcards`. - pub(super) fn arity(&self, pcx: PatCtxt<'_, '_>) -> usize { - match self { - Single | Variant(_) => match *pcx.ty.kind(Interner) { - TyKind::Tuple(arity, ..) => arity, - TyKind::Ref(..) => 1, - TyKind::Adt(adt, ..) => { - if is_box(pcx.cx.db, adt.0) { - // The only legal patterns of type `Box` (outside `std`) are `_` and box - // patterns. If we're here we can assume this is a box pattern. - 1 - } else { - let variant = self.variant_id_for_adt(adt.0); - Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant).count() - } - } - _ => { - never!("Unexpected type for `Single` constructor: {:?}", pcx.ty); - 0 - } - }, - Slice(slice) => slice.arity(), - Str(..) - | FloatRange(..) - | IntRange(..) - | NonExhaustive - | Opaque - | Missing { .. } - | Wildcard => 0, - Or => { - never!("The `Or` constructor doesn't have a fixed arity"); - 0 - } - } - } - - /// Some constructors (namely `Wildcard`, `IntRange` and `Slice`) actually stand for a set of actual - /// constructors (like variants, integers or fixed-sized slices). When specializing for these - /// constructors, we want to be specialising for the actual underlying constructors. - /// Naively, we would simply return the list of constructors they correspond to. We instead are - /// more clever: if there are constructors that we know will behave the same wrt the current - /// matrix, we keep them grouped. For example, all slices of a sufficiently large length - /// will either be all useful or all non-useful with a given matrix. - /// - /// See the branches for details on how the splitting is done. - /// - /// This function may discard some irrelevant constructors if this preserves behavior and - /// diagnostics. Eg. for the `_` case, we ignore the constructors already present in the - /// matrix, unless all of them are. - pub(super) fn split<'a>( - &self, - pcx: PatCtxt<'_, '_>, - ctors: impl Iterator + Clone, - ) -> SmallVec<[Self; 1]> { - match self { - Wildcard => { - let mut split_wildcard = SplitWildcard::new(pcx); - split_wildcard.split(pcx, ctors); - split_wildcard.into_ctors(pcx) - } - // Fast-track if the range is trivial. In particular, we don't do the overlapping - // ranges check. - IntRange(ctor_range) if !ctor_range.is_singleton() => { - let mut split_range = SplitIntRange::new(ctor_range.clone()); - let int_ranges = ctors.filter_map(|ctor| ctor.as_int_range()); - split_range.split(int_ranges.cloned()); - split_range.iter().map(IntRange).collect() - } - Slice(slice) => match slice._unimplemented {}, - // Any other constructor can be used unchanged. - _ => smallvec![self.clone()], - } - } - - /// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`. - /// For the simple cases, this is simply checking for equality. For the "grouped" constructors, - /// this checks for inclusion. - // We inline because this has a single call site in `Matrix::specialize_constructor`. - #[inline] - pub(super) fn is_covered_by(&self, _pcx: PatCtxt<'_, '_>, other: &Self) -> bool { - // This must be kept in sync with `is_covered_by_any`. - match (self, other) { - // Wildcards cover anything - (_, Wildcard) => true, - // The missing ctors are not covered by anything in the matrix except wildcards. - (Missing { .. } | Wildcard, _) => false, - - (Single, Single) => true, - (Variant(self_id), Variant(other_id)) => self_id == other_id, - - (IntRange(self_range), IntRange(other_range)) => self_range.is_covered_by(other_range), - (FloatRange(void), FloatRange(..)) => match *void {}, - (Str(void), Str(..)) => match *void {}, - (Slice(self_slice), Slice(other_slice)) => self_slice.is_covered_by(*other_slice), - - // We are trying to inspect an opaque constant. Thus we skip the row. - (Opaque, _) | (_, Opaque) => false, - // Only a wildcard pattern can match the special extra constructor. - (NonExhaustive, _) => false, - - _ => { - never!("trying to compare incompatible constructors {:?} and {:?}", self, other); - // Continue with 'whatever is covered' supposed to result in false no-error diagnostic. - true - } - } - } - - /// Faster version of `is_covered_by` when applied to many constructors. `used_ctors` is - /// assumed to be built from `matrix.head_ctors()` with wildcards filtered out, and `self` is - /// assumed to have been split from a wildcard. - fn is_covered_by_any(&self, _pcx: PatCtxt<'_, '_>, used_ctors: &[Constructor]) -> bool { - if used_ctors.is_empty() { - return false; - } - - // This must be kept in sync with `is_covered_by`. - match self { - // If `self` is `Single`, `used_ctors` cannot contain anything else than `Single`s. - Single => !used_ctors.is_empty(), - Variant(_) => used_ctors.iter().any(|c| c == self), - IntRange(range) => used_ctors - .iter() - .filter_map(|c| c.as_int_range()) - .any(|other| range.is_covered_by(other)), - Slice(slice) => used_ctors - .iter() - .filter_map(|c| c.as_slice()) - .any(|other| slice.is_covered_by(other)), - // This constructor is never covered by anything else - NonExhaustive => false, - Str(..) | FloatRange(..) | Opaque | Missing { .. } | Wildcard | Or => { - never!("found unexpected ctor in all_ctors: {:?}", self); - true - } - } - } -} - -/// A wildcard constructor that we split relative to the constructors in the matrix, as explained -/// at the top of the file. -/// -/// A constructor that is not present in the matrix rows will only be covered by the rows that have -/// wildcards. Thus we can group all of those constructors together; we call them "missing -/// constructors". Splitting a wildcard would therefore list all present constructors individually -/// (or grouped if they are integers or slices), and then all missing constructors together as a -/// group. -/// -/// However we can go further: since any constructor will match the wildcard rows, and having more -/// rows can only reduce the amount of usefulness witnesses, we can skip the present constructors -/// and only try the missing ones. -/// This will not preserve the whole list of witnesses, but will preserve whether the list is empty -/// or not. In fact this is quite natural from the point of view of diagnostics too. This is done -/// in `to_ctors`: in some cases we only return `Missing`. -#[derive(Debug)] -pub(super) struct SplitWildcard { - /// Constructors seen in the matrix. - matrix_ctors: Vec, - /// All the constructors for this type - all_ctors: SmallVec<[Constructor; 1]>, -} - -impl SplitWildcard { - pub(super) fn new(pcx: PatCtxt<'_, '_>) -> Self { - let cx = pcx.cx; - let make_range = |start, end, scalar| IntRange(IntRange::from_range(start, end, scalar)); - - // Unhandled types are treated as non-exhaustive. Being explicit here instead of falling - // to catchall arm to ease further implementation. - let unhandled = || smallvec![NonExhaustive]; - - // This determines the set of all possible constructors for the type `pcx.ty`. For numbers, - // arrays and slices we use ranges and variable-length slices when appropriate. - // - // If the `exhaustive_patterns` feature is enabled, we make sure to omit constructors that - // are statically impossible. E.g., for `Option`, we do not include `Some(_)` in the - // returned list of constructors. - // Invariant: this is empty if and only if the type is uninhabited (as determined by - // `cx.is_uninhabited()`). - let all_ctors = match pcx.ty.kind(Interner) { - TyKind::Scalar(Scalar::Bool) => smallvec![make_range(0, 1, Scalar::Bool)], - // TyKind::Array(..) if ... => unhandled(), - TyKind::Array(..) | TyKind::Slice(..) => unhandled(), - TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), subst) => { - let enum_data = cx.db.enum_data(*enum_id); - - // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an - // additional "unknown" constructor. - // There is no point in enumerating all possible variants, because the user can't - // actually match against them all themselves. So we always return only the fictitious - // constructor. - // E.g., in an example like: - // - // ``` - // let err: io::ErrorKind = ...; - // match err { - // io::ErrorKind::NotFound => {}, - // } - // ``` - // - // we don't want to show every possible IO error, but instead have only `_` as the - // witness. - let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty); - - let is_exhaustive_pat_feature = cx.feature_exhaustive_patterns(); - - // If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it - // as though it had an "unknown" constructor to avoid exposing its emptiness. The - // exception is if the pattern is at the top level, because we want empty matches to be - // considered exhaustive. - let is_secretly_empty = enum_data.variants.is_empty() - && !is_exhaustive_pat_feature - && !pcx.is_top_level; - - let mut ctors: SmallVec<[_; 1]> = enum_data - .variants - .iter() - .map(|&(variant, _)| variant) - .filter(|&variant| { - // If `exhaustive_patterns` is enabled, we exclude variants known to be - // uninhabited. - let is_uninhabited = is_exhaustive_pat_feature - && is_enum_variant_uninhabited_from(variant, subst, cx.module, cx.db); - !is_uninhabited - }) - .map(Variant) - .collect(); - - if is_secretly_empty || is_declared_nonexhaustive { - ctors.push(NonExhaustive); - } - ctors - } - TyKind::Scalar(Scalar::Char) => unhandled(), - TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(), - TyKind::Never if !cx.feature_exhaustive_patterns() && !pcx.is_top_level => { - smallvec![NonExhaustive] - } - TyKind::Never => SmallVec::new(), - _ if cx.is_uninhabited(pcx.ty) => SmallVec::new(), - TyKind::Adt(..) | TyKind::Tuple(..) | TyKind::Ref(..) => smallvec![Single], - // This type is one for which we cannot list constructors, like `str` or `f64`. - _ => smallvec![NonExhaustive], - }; - - SplitWildcard { matrix_ctors: Vec::new(), all_ctors } - } - - /// Pass a set of constructors relative to which to split this one. Don't call twice, it won't - /// do what you want. - pub(super) fn split<'a>( - &mut self, - pcx: PatCtxt<'_, '_>, - ctors: impl Iterator + Clone, - ) { - // Since `all_ctors` never contains wildcards, this won't recurse further. - self.all_ctors = - self.all_ctors.iter().flat_map(|ctor| ctor.split(pcx, ctors.clone())).collect(); - self.matrix_ctors = ctors.filter(|c| !c.is_wildcard()).cloned().collect(); - } - - /// Whether there are any value constructors for this type that are not present in the matrix. - fn any_missing(&self, pcx: PatCtxt<'_, '_>) -> bool { - self.iter_missing(pcx).next().is_some() - } - - /// Iterate over the constructors for this type that are not present in the matrix. - pub(super) fn iter_missing<'a, 'p>( - &'a self, - pcx: PatCtxt<'a, 'p>, - ) -> impl Iterator + Captures<'p> { - self.all_ctors.iter().filter(move |ctor| !ctor.is_covered_by_any(pcx, &self.matrix_ctors)) - } - - /// Return the set of constructors resulting from splitting the wildcard. As explained at the - /// top of the file, if any constructors are missing we can ignore the present ones. - fn into_ctors(self, pcx: PatCtxt<'_, '_>) -> SmallVec<[Constructor; 1]> { - if self.any_missing(pcx) { - // Some constructors are missing, thus we can specialize with the special `Missing` - // constructor, which stands for those constructors that are not seen in the matrix, - // and matches the same rows as any of them (namely the wildcard rows). See the top of - // the file for details. - // However, when all constructors are missing we can also specialize with the full - // `Wildcard` constructor. The difference will depend on what we want in diagnostics. - - // If some constructors are missing, we typically want to report those constructors, - // e.g.: - // ``` - // enum Direction { N, S, E, W } - // let Direction::N = ...; - // ``` - // we can report 3 witnesses: `S`, `E`, and `W`. - // - // However, if the user didn't actually specify a constructor - // in this arm, e.g., in - // ``` - // let x: (Direction, Direction, bool) = ...; - // let (_, _, false) = x; - // ``` - // we don't want to show all 16 possible witnesses `(, , - // true)` - we are satisfied with `(_, _, true)`. So if all constructors are missing we - // prefer to report just a wildcard `_`. - // - // The exception is: if we are at the top-level, for example in an empty match, we - // sometimes prefer reporting the list of constructors instead of just `_`. - let report_when_all_missing = pcx.is_top_level && !IntRange::is_integral(pcx.ty); - let ctor = if !self.matrix_ctors.is_empty() || report_when_all_missing { - if pcx.is_non_exhaustive { - Missing { - nonexhaustive_enum_missing_real_variants: self - .iter_missing(pcx) - .any(|c| !(c.is_non_exhaustive() || c.is_unstable_variant(pcx))), - } - } else { - Missing { nonexhaustive_enum_missing_real_variants: false } - } - } else { - Wildcard - }; - return smallvec![ctor]; - } - - // All the constructors are present in the matrix, so we just go through them all. - self.all_ctors - } -} - -/// A value can be decomposed into a constructor applied to some fields. This struct represents -/// those fields, generalized to allow patterns in each field. See also `Constructor`. -/// -/// This is constructed for a constructor using [`Fields::wildcards()`]. The idea is that -/// [`Fields::wildcards()`] constructs a list of fields where all entries are wildcards, and then -/// given a pattern we fill some of the fields with its subpatterns. -/// In the following example `Fields::wildcards` returns `[_, _, _, _]`. Then in -/// `extract_pattern_arguments` we fill some of the entries, and the result is -/// `[Some(0), _, _, _]`. -/// ```rust -/// let x: [Option; 4] = foo(); -/// match x { -/// [Some(0), ..] => {} -/// } -/// ``` -/// -/// Note that the number of fields of a constructor may not match the fields declared in the -/// original struct/variant. This happens if a private or `non_exhaustive` field is uninhabited, -/// because the code mustn't observe that it is uninhabited. In that case that field is not -/// included in `fields`. For that reason, when you have a `mir::Field` you must use -/// `index_with_declared_idx`. -#[derive(Clone, Copy)] -pub(super) struct Fields<'p> { - fields: &'p [DeconstructedPat<'p>], -} - -impl<'p> Fields<'p> { - fn empty() -> Self { - Fields { fields: &[] } - } - - fn singleton(cx: &MatchCheckCtx<'_, 'p>, field: DeconstructedPat<'p>) -> Self { - let field = cx.pattern_arena.alloc(field); - Fields { fields: std::slice::from_ref(field) } - } - - pub(super) fn from_iter( - cx: &MatchCheckCtx<'_, 'p>, - fields: impl IntoIterator>, - ) -> Self { - let fields: &[_] = cx.pattern_arena.alloc_extend(fields); - Fields { fields } - } - - fn wildcards_from_tys(cx: &MatchCheckCtx<'_, 'p>, tys: impl IntoIterator) -> Self { - Fields::from_iter(cx, tys.into_iter().map(DeconstructedPat::wildcard)) - } - - // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide - // uninhabited fields in order not to reveal the uninhabitedness of the whole variant. - // This lists the fields we keep along with their types. - fn list_variant_nonhidden_fields<'a>( - cx: &'a MatchCheckCtx<'a, 'p>, - ty: &'a Ty, - variant: VariantId, - ) -> impl Iterator + Captures<'a> + Captures<'p> { - let (adt, substs) = ty.as_adt().unwrap(); - - let adt_is_local = variant.module(cx.db.upcast()).krate() == cx.module.krate(); - // Whether we must not match the fields of this variant exhaustively. - let is_non_exhaustive = is_field_list_non_exhaustive(variant, cx) && !adt_is_local; - - let visibility = cx.db.field_visibilities(variant); - let field_ty = cx.db.field_types(variant); - let fields_len = variant.variant_data(cx.db.upcast()).fields().len() as u32; - - (0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).filter_map(move |fid| { - let ty = field_ty[fid].clone().substitute(Interner, substs); - let ty = normalize(cx.db, cx.db.trait_environment_for_body(cx.body), ty); - let is_visible = matches!(adt, hir_def::AdtId::EnumId(..)) - || visibility[fid].is_visible_from(cx.db.upcast(), cx.module); - let is_uninhabited = cx.is_uninhabited(&ty); - - if is_uninhabited && (!is_visible || is_non_exhaustive) { - None - } else { - Some((fid, ty)) - } - }) - } - - /// Creates a new list of wildcard fields for a given constructor. The result must have a - /// length of `constructor.arity()`. - pub(crate) fn wildcards( - cx: &MatchCheckCtx<'_, 'p>, - ty: &Ty, - constructor: &Constructor, - ) -> Self { - let ret = match constructor { - Single | Variant(_) => match ty.kind(Interner) { - TyKind::Tuple(_, substs) => { - let tys = substs.iter(Interner).map(|ty| ty.assert_ty_ref(Interner)); - Fields::wildcards_from_tys(cx, tys.cloned()) - } - TyKind::Ref(.., rty) => Fields::wildcards_from_tys(cx, once(rty.clone())), - &TyKind::Adt(AdtId(adt), ref substs) => { - if is_box(cx.db, adt) { - // The only legal patterns of type `Box` (outside `std`) are `_` and box - // patterns. If we're here we can assume this is a box pattern. - let subst_ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone(); - Fields::wildcards_from_tys(cx, once(subst_ty)) - } else { - let variant = constructor.variant_id_for_adt(adt); - let tys = Fields::list_variant_nonhidden_fields(cx, ty, variant) - .map(|(_, ty)| ty); - Fields::wildcards_from_tys(cx, tys) - } - } - ty_kind => { - never!("Unexpected type for `Single` constructor: {:?}", ty_kind); - Fields::wildcards_from_tys(cx, once(ty.clone())) - } - }, - Slice(slice) => match slice._unimplemented {}, - Str(..) - | FloatRange(..) - | IntRange(..) - | NonExhaustive - | Opaque - | Missing { .. } - | Wildcard => Fields::empty(), - Or => { - never!("called `Fields::wildcards` on an `Or` ctor"); - Fields::empty() - } - }; - ret - } - - /// Returns the list of patterns. - pub(super) fn iter_patterns<'a>( - &'a self, - ) -> impl Iterator> + Captures<'a> { - self.fields.iter() - } -} - -/// Values and patterns can be represented as a constructor applied to some fields. This represents -/// a pattern in this form. -/// This also keeps track of whether the pattern has been found reachable during analysis. For this -/// reason we should be careful not to clone patterns for which we care about that. Use -/// `clone_and_forget_reachability` if you're sure. -pub(crate) struct DeconstructedPat<'p> { - ctor: Constructor, - fields: Fields<'p>, - ty: Ty, - reachable: Cell, -} - -impl<'p> DeconstructedPat<'p> { - pub(super) fn wildcard(ty: Ty) -> Self { - Self::new(Wildcard, Fields::empty(), ty) - } - - pub(super) fn new(ctor: Constructor, fields: Fields<'p>, ty: Ty) -> Self { - DeconstructedPat { ctor, fields, ty, reachable: Cell::new(false) } - } - - /// Construct a pattern that matches everything that starts with this constructor. - /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern - /// `Some(_)`. - pub(super) fn wild_from_ctor(pcx: PatCtxt<'_, 'p>, ctor: Constructor) -> Self { - let fields = Fields::wildcards(pcx.cx, pcx.ty, &ctor); - DeconstructedPat::new(ctor, fields, pcx.ty.clone()) - } - - /// Clone this value. This method emphasizes that cloning loses reachability information and - /// should be done carefully. - pub(super) fn clone_and_forget_reachability(&self) -> Self { - DeconstructedPat::new(self.ctor.clone(), self.fields, self.ty.clone()) - } - - pub(crate) fn from_pat(cx: &MatchCheckCtx<'_, 'p>, pat: &Pat) -> Self { - let mkpat = |pat| DeconstructedPat::from_pat(cx, pat); - let ctor; - let fields; - match pat.kind.as_ref() { - PatKind::Binding { subpattern: Some(subpat), .. } => return mkpat(subpat), - PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { - ctor = Wildcard; - fields = Fields::empty(); - } - PatKind::Deref { subpattern } => { - ctor = Single; - fields = Fields::singleton(cx, mkpat(subpattern)); - } - PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => { - match pat.ty.kind(Interner) { - TyKind::Tuple(_, substs) => { - ctor = Single; - let mut wilds: SmallVec<[_; 2]> = substs - .iter(Interner) - .map(|arg| arg.assert_ty_ref(Interner).clone()) - .map(DeconstructedPat::wildcard) - .collect(); - for pat in subpatterns { - let idx: u32 = pat.field.into_raw().into(); - wilds[idx as usize] = mkpat(&pat.pattern); - } - fields = Fields::from_iter(cx, wilds) - } - TyKind::Adt(adt, substs) if is_box(cx.db, adt.0) => { - // The only legal patterns of type `Box` (outside `std`) are `_` and box - // patterns. If we're here we can assume this is a box pattern. - // FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_, - // _)` or a box pattern. As a hack to avoid an ICE with the former, we - // ignore other fields than the first one. This will trigger an error later - // anyway. - // See https://github.com/rust-lang/rust/issues/82772 , - // explanation: https://github.com/rust-lang/rust/pull/82789#issuecomment-796921977 - // The problem is that we can't know from the type whether we'll match - // normally or through box-patterns. We'll have to figure out a proper - // solution when we introduce generalized deref patterns. Also need to - // prevent mixing of those two options. - let pat = - subpatterns.iter().find(|pat| pat.field.into_raw() == 0u32.into()); - let field = if let Some(pat) = pat { - mkpat(&pat.pattern) - } else { - let ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone(); - DeconstructedPat::wildcard(ty) - }; - ctor = Single; - fields = Fields::singleton(cx, field) - } - &TyKind::Adt(adt, _) => { - ctor = match pat.kind.as_ref() { - PatKind::Leaf { .. } => Single, - PatKind::Variant { enum_variant, .. } => Variant(*enum_variant), - _ => { - never!(); - Wildcard - } - }; - let variant = ctor.variant_id_for_adt(adt.0); - let fields_len = variant.variant_data(cx.db.upcast()).fields().len(); - // For each field in the variant, we store the relevant index into `self.fields` if any. - let mut field_id_to_id: Vec> = vec![None; fields_len]; - let tys = Fields::list_variant_nonhidden_fields(cx, &pat.ty, variant) - .enumerate() - .map(|(i, (fid, ty))| { - let field_idx: u32 = fid.into_raw().into(); - field_id_to_id[field_idx as usize] = Some(i); - ty - }); - let mut wilds: SmallVec<[_; 2]> = - tys.map(DeconstructedPat::wildcard).collect(); - for pat in subpatterns { - let field_idx: u32 = pat.field.into_raw().into(); - if let Some(i) = field_id_to_id[field_idx as usize] { - wilds[i] = mkpat(&pat.pattern); - } - } - fields = Fields::from_iter(cx, wilds); - } - _ => { - never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty); - ctor = Wildcard; - fields = Fields::empty(); - } - } - } - &PatKind::LiteralBool { value } => { - ctor = IntRange(IntRange::from_bool(value)); - fields = Fields::empty(); - } - PatKind::Or { .. } => { - ctor = Or; - let pats: SmallVec<[_; 2]> = expand_or_pat(pat).into_iter().map(mkpat).collect(); - fields = Fields::from_iter(cx, pats) - } - } - DeconstructedPat::new(ctor, fields, pat.ty.clone()) - } - - pub(crate) fn to_pat(&self, cx: &MatchCheckCtx<'_, 'p>) -> Pat { - let mut subpatterns = self.iter_fields().map(|p| p.to_pat(cx)); - let pat = match &self.ctor { - Single | Variant(_) => match self.ty.kind(Interner) { - TyKind::Tuple(..) => PatKind::Leaf { - subpatterns: subpatterns - .zip(0u32..) - .map(|(p, i)| FieldPat { - field: LocalFieldId::from_raw(i.into()), - pattern: p, - }) - .collect(), - }, - TyKind::Adt(adt, _) if is_box(cx.db, adt.0) => { - // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside - // of `std`). So this branch is only reachable when the feature is enabled and - // the pattern is a box pattern. - PatKind::Deref { subpattern: subpatterns.next().unwrap() } - } - TyKind::Adt(adt, substs) => { - let variant = self.ctor.variant_id_for_adt(adt.0); - let subpatterns = Fields::list_variant_nonhidden_fields(cx, self.ty(), variant) - .zip(subpatterns) - .map(|((field, _ty), pattern)| FieldPat { field, pattern }) - .collect(); - - if let VariantId::EnumVariantId(enum_variant) = variant { - PatKind::Variant { substs: substs.clone(), enum_variant, subpatterns } - } else { - PatKind::Leaf { subpatterns } - } - } - // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should - // be careful to reconstruct the correct constant pattern here. However a string - // literal pattern will never be reported as a non-exhaustiveness witness, so we - // ignore this issue. - TyKind::Ref(..) => PatKind::Deref { subpattern: subpatterns.next().unwrap() }, - _ => { - never!("unexpected ctor for type {:?} {:?}", self.ctor, self.ty); - PatKind::Wild - } - }, - &Slice(slice) => match slice._unimplemented {}, - &Str(void) => match void {}, - &FloatRange(void) => match void {}, - IntRange(range) => return range.to_pat(cx, self.ty.clone()), - Wildcard | NonExhaustive => PatKind::Wild, - Missing { .. } => { - never!( - "trying to convert a `Missing` constructor into a `Pat`; this is a bug, \ - `Missing` should have been processed in `apply_constructors`" - ); - PatKind::Wild - } - Opaque | Or => { - never!("can't convert to pattern: {:?}", self.ctor); - PatKind::Wild - } - }; - Pat { ty: self.ty.clone(), kind: Box::new(pat) } - } - - pub(super) fn is_or_pat(&self) -> bool { - matches!(self.ctor, Or) - } - - pub(super) fn ctor(&self) -> &Constructor { - &self.ctor - } - - pub(super) fn ty(&self) -> &Ty { - &self.ty - } - - pub(super) fn iter_fields<'a>(&'a self) -> impl Iterator> + 'a { - self.fields.iter_patterns() - } - - /// Specialize this pattern with a constructor. - /// `other_ctor` can be different from `self.ctor`, but must be covered by it. - pub(super) fn specialize<'a>( - &'a self, - cx: &MatchCheckCtx<'_, 'p>, - other_ctor: &Constructor, - ) -> SmallVec<[&'p DeconstructedPat<'p>; 2]> { - match (&self.ctor, other_ctor) { - (Wildcard, _) => { - // We return a wildcard for each field of `other_ctor`. - Fields::wildcards(cx, &self.ty, other_ctor).iter_patterns().collect() - } - (Slice(self_slice), Slice(other_slice)) - if self_slice.arity() != other_slice.arity() => - { - match self_slice._unimplemented {} - } - _ => self.fields.iter_patterns().collect(), - } - } - - /// We keep track for each pattern if it was ever reachable during the analysis. This is used - /// with `unreachable_spans` to report unreachable subpatterns arising from or patterns. - pub(super) fn set_reachable(&self) { - self.reachable.set(true) - } - pub(super) fn is_reachable(&self) -> bool { - self.reachable.get() - } -} - -fn is_field_list_non_exhaustive(variant_id: VariantId, cx: &MatchCheckCtx<'_, '_>) -> bool { - let attr_def_id = match variant_id { - VariantId::EnumVariantId(id) => id.into(), - VariantId::StructId(id) => id.into(), - VariantId::UnionId(id) => id.into(), - }; - cx.db.attrs(attr_def_id).by_key("non_exhaustive").exists() -} diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs new file mode 100644 index 0000000000000..cd67ca599310c --- /dev/null +++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -0,0 +1,475 @@ +//! Interface with `rustc_pattern_analysis`. + +use std::fmt; + +use hir_def::{DefWithBodyId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId}; +use rustc_hash::FxHashMap; +use rustc_pattern_analysis::{ + constructor::{Constructor, ConstructorSet, VariantVisibility}, + index::IdxContainer, + Captures, TypeCx, +}; +use smallvec::SmallVec; +use stdx::never; +use typed_arena::Arena; + +use crate::{ + 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 Constructor::*; + +// Re-export r-a-specific versions of all these types. +pub(crate) type DeconstructedPat<'p> = + rustc_pattern_analysis::pat::DeconstructedPat<'p, MatchCheckCtx<'p>>; +pub(crate) type MatchArm<'p> = rustc_pattern_analysis::MatchArm<'p, MatchCheckCtx<'p>>; +pub(crate) type WitnessPat<'p> = rustc_pattern_analysis::pat::WitnessPat>; + +/// [Constructor] uses this in unimplemented variants. +/// It allows porting match expressions from upstream algorithm without losing semantics. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub(crate) enum Void {} + +#[derive(Clone)] +pub(crate) struct MatchCheckCtx<'p> { + module: ModuleId, + body: DefWithBodyId, + pub(crate) db: &'p dyn HirDatabase, + pub(crate) pattern_arena: &'p Arena>, + ty_arena: &'p Arena, + exhaustive_patterns: bool, +} + +impl<'p> MatchCheckCtx<'p> { + pub(crate) fn new( + module: ModuleId, + body: DefWithBodyId, + db: &'p dyn HirDatabase, + pattern_arena: &'p Arena>, + ty_arena: &'p Arena, + ) -> Self { + let def_map = db.crate_def_map(module.krate()); + let exhaustive_patterns = def_map.is_unstable_feature_enabled("exhaustive_patterns"); + Self { module, body, db, pattern_arena, exhaustive_patterns, ty_arena } + } + + fn is_uninhabited(&self, ty: &Ty) -> bool { + is_ty_uninhabited_from(ty, self.module, self.db) + } + + /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`. + fn is_foreign_non_exhaustive_enum(&self, ty: &Ty) -> bool { + match ty.as_adt() { + Some((adt @ hir_def::AdtId::EnumId(_), _)) => { + let has_non_exhaustive_attr = + self.db.attrs(adt.into()).by_key("non_exhaustive").exists(); + let is_local = adt.module(self.db.upcast()).krate() == self.module.krate(); + has_non_exhaustive_attr && !is_local + } + _ => false, + } + } + + fn variant_id_for_adt(&self, ctor: &Constructor, adt: hir_def::AdtId) -> VariantId { + match ctor { + &Variant(id) => id.into(), + Struct | UnionField => { + assert!(!matches!(adt, hir_def::AdtId::EnumId(_))); + match adt { + hir_def::AdtId::EnumId(_) => unreachable!(), + hir_def::AdtId::StructId(id) => id.into(), + hir_def::AdtId::UnionId(id) => id.into(), + } + } + _ => panic!("bad constructor {self:?} for adt {adt:?}"), + } + } + + // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide + // uninhabited fields in order not to reveal the uninhabitedness of the whole variant. + // This lists the fields we keep along with their types. + fn list_variant_nonhidden_fields<'a>( + &'a self, + ty: &'a Ty, + variant: VariantId, + ) -> impl Iterator + Captures<'a> + Captures<'p> { + let cx = self; + let (adt, substs) = ty.as_adt().unwrap(); + + let adt_is_local = variant.module(cx.db.upcast()).krate() == cx.module.krate(); + + // Whether we must not match the fields of this variant exhaustively. + let is_non_exhaustive = + cx.db.attrs(variant.into()).by_key("non_exhaustive").exists() && !adt_is_local; + + let visibility = cx.db.field_visibilities(variant); + let field_ty = cx.db.field_types(variant); + let fields_len = variant.variant_data(cx.db.upcast()).fields().len() as u32; + + (0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).filter_map(move |fid| { + let ty = field_ty[fid].clone().substitute(Interner, substs); + let ty = normalize(cx.db, cx.db.trait_environment_for_body(cx.body), ty); + let is_visible = matches!(adt, hir_def::AdtId::EnumId(..)) + || visibility[fid].is_visible_from(cx.db.upcast(), cx.module); + let is_uninhabited = cx.is_uninhabited(&ty); + + if is_uninhabited && (!is_visible || is_non_exhaustive) { + None + } else { + Some((fid, ty)) + } + }) + } + + pub(crate) fn lower_pat(&self, pat: &Pat) -> DeconstructedPat<'p> { + let singleton = |pat| std::slice::from_ref(self.pattern_arena.alloc(pat)); + let ctor; + let fields: &[_]; + + match pat.kind.as_ref() { + PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat), + PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { + ctor = Wildcard; + fields = &[]; + } + PatKind::Deref { subpattern } => { + ctor = match pat.ty.kind(Interner) { + // This is a box pattern. + TyKind::Adt(adt, _) if is_box(self.db, adt.0) => Struct, + TyKind::Ref(..) => Ref, + _ => { + never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty); + Wildcard + } + }; + fields = singleton(self.lower_pat(subpattern)); + } + PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => { + match pat.ty.kind(Interner) { + TyKind::Tuple(_, substs) => { + ctor = Struct; + let mut wilds: SmallVec<[_; 2]> = substs + .iter(Interner) + .map(|arg| arg.assert_ty_ref(Interner).clone()) + .map(DeconstructedPat::wildcard) + .collect(); + for pat in subpatterns { + let idx: u32 = pat.field.into_raw().into(); + wilds[idx as usize] = self.lower_pat(&pat.pattern); + } + fields = self.pattern_arena.alloc_extend(wilds) + } + TyKind::Adt(adt, substs) if is_box(self.db, adt.0) => { + // The only legal patterns of type `Box` (outside `std`) are `_` and box + // patterns. If we're here we can assume this is a box pattern. + // FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_, + // _)` or a box pattern. As a hack to avoid an ICE with the former, we + // ignore other fields than the first one. This will trigger an error later + // anyway. + // See https://github.com/rust-lang/rust/issues/82772 , + // explanation: https://github.com/rust-lang/rust/pull/82789#issuecomment-796921977 + // The problem is that we can't know from the type whether we'll match + // normally or through box-patterns. We'll have to figure out a proper + // solution when we introduce generalized deref patterns. Also need to + // prevent mixing of those two options. + let pat = + subpatterns.iter().find(|pat| pat.field.into_raw() == 0u32.into()); + let field = if let Some(pat) = pat { + self.lower_pat(&pat.pattern) + } else { + let ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone(); + DeconstructedPat::wildcard(ty) + }; + ctor = Struct; + fields = singleton(field); + } + &TyKind::Adt(adt, _) => { + ctor = match pat.kind.as_ref() { + PatKind::Leaf { .. } if matches!(adt.0, hir_def::AdtId::UnionId(_)) => { + UnionField + } + PatKind::Leaf { .. } => Struct, + PatKind::Variant { enum_variant, .. } => Variant(*enum_variant), + _ => { + never!(); + Wildcard + } + }; + let variant = self.variant_id_for_adt(&ctor, adt.0); + let fields_len = variant.variant_data(self.db.upcast()).fields().len(); + // For each field in the variant, we store the relevant index into `self.fields` if any. + let mut field_id_to_id: Vec> = vec![None; fields_len]; + let tys = self + .list_variant_nonhidden_fields(&pat.ty, variant) + .enumerate() + .map(|(i, (fid, ty))| { + let field_idx: u32 = fid.into_raw().into(); + field_id_to_id[field_idx as usize] = Some(i); + ty + }); + let mut wilds: SmallVec<[_; 2]> = + tys.map(DeconstructedPat::wildcard).collect(); + for pat in subpatterns { + let field_idx: u32 = pat.field.into_raw().into(); + if let Some(i) = field_id_to_id[field_idx as usize] { + wilds[i] = self.lower_pat(&pat.pattern); + } + } + fields = self.pattern_arena.alloc_extend(wilds); + } + _ => { + never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty); + ctor = Wildcard; + fields = &[]; + } + } + } + &PatKind::LiteralBool { value } => { + ctor = Bool(value); + fields = &[]; + } + PatKind::Or { pats } => { + ctor = Or; + // Collect here because `Arena::alloc_extend` panics on reentrancy. + let subpats: SmallVec<[_; 2]> = + pats.into_iter().map(|pat| self.lower_pat(pat)).collect(); + fields = self.pattern_arena.alloc_extend(subpats); + } + } + DeconstructedPat::new(ctor, fields, pat.ty.clone(), ()) + } + + pub(crate) fn hoist_witness_pat(&self, pat: &WitnessPat<'p>) -> Pat { + let mut subpatterns = pat.iter_fields().map(|p| self.hoist_witness_pat(p)); + let kind = match pat.ctor() { + &Bool(value) => PatKind::LiteralBool { value }, + IntRange(_) => unimplemented!(), + Struct | Variant(_) | UnionField => match pat.ty().kind(Interner) { + TyKind::Tuple(..) => PatKind::Leaf { + subpatterns: subpatterns + .zip(0u32..) + .map(|(p, i)| FieldPat { + field: LocalFieldId::from_raw(i.into()), + pattern: p, + }) + .collect(), + }, + TyKind::Adt(adt, _) if is_box(self.db, adt.0) => { + // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside + // of `std`). So this branch is only reachable when the feature is enabled and + // the pattern is a box pattern. + PatKind::Deref { subpattern: subpatterns.next().unwrap() } + } + TyKind::Adt(adt, substs) => { + let variant = self.variant_id_for_adt(pat.ctor(), adt.0); + let subpatterns = self + .list_variant_nonhidden_fields(pat.ty(), variant) + .zip(subpatterns) + .map(|((field, _ty), pattern)| FieldPat { field, pattern }) + .collect(); + + if let VariantId::EnumVariantId(enum_variant) = variant { + PatKind::Variant { substs: substs.clone(), enum_variant, subpatterns } + } else { + PatKind::Leaf { subpatterns } + } + } + _ => { + never!("unexpected ctor for type {:?} {:?}", pat.ctor(), pat.ty()); + PatKind::Wild + } + }, + // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should + // be careful to reconstruct the correct constant pattern here. However a string + // literal pattern will never be reported as a non-exhaustiveness witness, so we + // ignore this issue. + Ref => PatKind::Deref { subpattern: subpatterns.next().unwrap() }, + Slice(_) => unimplemented!(), + &Str(void) => match void {}, + Wildcard | NonExhaustive | Hidden => PatKind::Wild, + Missing | F32Range(..) | F64Range(..) | Opaque(..) | Or => { + never!("can't convert to pattern: {:?}", pat.ctor()); + PatKind::Wild + } + }; + Pat { ty: pat.ty().clone(), kind: Box::new(kind) } + } +} + +impl<'p> TypeCx for MatchCheckCtx<'p> { + type Error = Void; + type Ty = Ty; + type VariantIdx = EnumVariantId; + type StrLit = Void; + type ArmData = (); + type PatData = (); + + fn is_exhaustive_patterns_feature_on(&self) -> bool { + self.exhaustive_patterns + } + + fn ctor_arity( + &self, + ctor: &rustc_pattern_analysis::constructor::Constructor, + ty: &Self::Ty, + ) -> usize { + match ctor { + Struct | Variant(_) | UnionField => match *ty.kind(Interner) { + TyKind::Tuple(arity, ..) => arity, + TyKind::Adt(AdtId(adt), ..) => { + if is_box(self.db, adt) { + // The only legal patterns of type `Box` (outside `std`) are `_` and box + // patterns. If we're here we can assume this is a box pattern. + 1 + } else { + let variant = self.variant_id_for_adt(ctor, adt); + self.list_variant_nonhidden_fields(ty, variant).count() + } + } + _ => { + never!("Unexpected type for `Single` constructor: {:?}", ty); + 0 + } + }, + Ref => 1, + Slice(..) => unimplemented!(), + Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..) + | NonExhaustive | Hidden | Missing | Wildcard => 0, + Or => { + never!("The `Or` constructor doesn't have a fixed arity"); + 0 + } + } + } + + fn ctor_sub_tys( + &self, + ctor: &rustc_pattern_analysis::constructor::Constructor, + ty: &Self::Ty, + ) -> &[Self::Ty] { + use std::iter::once; + fn alloc<'a>(cx: &'a MatchCheckCtx<'_>, iter: impl Iterator) -> &'a [Ty] { + cx.ty_arena.alloc_extend(iter) + } + match ctor { + Struct | Variant(_) | UnionField => match ty.kind(Interner) { + TyKind::Tuple(_, substs) => { + let tys = substs.iter(Interner).map(|ty| ty.assert_ty_ref(Interner)); + alloc(self, tys.cloned()) + } + TyKind::Ref(.., rty) => alloc(self, once(rty.clone())), + &TyKind::Adt(AdtId(adt), ref substs) => { + if is_box(self.db, adt) { + // The only legal patterns of type `Box` (outside `std`) are `_` and box + // patterns. If we're here we can assume this is a box pattern. + let subst_ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone(); + alloc(self, once(subst_ty)) + } else { + let variant = self.variant_id_for_adt(ctor, adt); + let tys = self.list_variant_nonhidden_fields(ty, variant).map(|(_, ty)| ty); + alloc(self, tys) + } + } + ty_kind => { + never!("Unexpected type for `{:?}` constructor: {:?}", ctor, ty_kind); + alloc(self, once(ty.clone())) + } + }, + Ref => match ty.kind(Interner) { + TyKind::Ref(.., rty) => alloc(self, once(rty.clone())), + ty_kind => { + never!("Unexpected type for `{:?}` constructor: {:?}", ctor, ty_kind); + alloc(self, once(ty.clone())) + } + }, + Slice(_) => unreachable!("Found a `Slice` constructor in match checking"), + Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..) + | NonExhaustive | Hidden | Missing | Wildcard => &[], + Or => { + never!("called `Fields::wildcards` on an `Or` ctor"); + &[] + } + } + } + + fn ctors_for_ty( + &self, + ty: &Self::Ty, + ) -> Result, Self::Error> { + let cx = self; + + // Unhandled types are treated as non-exhaustive. Being explicit here instead of falling + // to catchall arm to ease further implementation. + let unhandled = || ConstructorSet::Unlistable; + + // This determines the set of all possible constructors for the type `ty`. For numbers, + // arrays and slices we use ranges and variable-length slices when appropriate. + // + // If the `exhaustive_patterns` feature is enabled, we make sure to omit constructors that + // are statically impossible. E.g., for `Option`, we do not include `Some(_)` in the + // returned list of constructors. + // Invariant: this is empty if and only if the type is uninhabited (as determined by + // `cx.is_uninhabited()`). + Ok(match ty.kind(Interner) { + TyKind::Scalar(Scalar::Bool) => ConstructorSet::Bool, + TyKind::Scalar(Scalar::Char) => unhandled(), + TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(), + TyKind::Array(..) | TyKind::Slice(..) => unhandled(), + TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), subst) => { + let enum_data = cx.db.enum_data(*enum_id); + let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(ty); + + if enum_data.variants.is_empty() && !is_declared_nonexhaustive { + ConstructorSet::NoConstructors + } else { + let mut variants = FxHashMap::default(); + for &(variant, _) in enum_data.variants.iter() { + let is_uninhabited = + is_enum_variant_uninhabited_from(variant, subst, cx.module, cx.db); + let visibility = if is_uninhabited { + VariantVisibility::Empty + } else { + VariantVisibility::Visible + }; + variants.insert(variant, visibility); + } + + ConstructorSet::Variants { + variants: IdxContainer(variants), + non_exhaustive: is_declared_nonexhaustive, + } + } + } + TyKind::Adt(AdtId(hir_def::AdtId::UnionId(_)), _) => ConstructorSet::Union, + TyKind::Adt(..) | TyKind::Tuple(..) => { + ConstructorSet::Struct { empty: cx.is_uninhabited(ty) } + } + TyKind::Ref(..) => ConstructorSet::Ref, + TyKind::Never => ConstructorSet::NoConstructors, + // This type is one for which we cannot list constructors, like `str` or `f64`. + _ => ConstructorSet::Unlistable, + }) + } + + fn debug_pat( + _f: &mut fmt::Formatter<'_>, + _pat: &rustc_pattern_analysis::pat::DeconstructedPat<'_, Self>, + ) -> fmt::Result { + unimplemented!() + } + + fn bug(&self, fmt: fmt::Arguments<'_>) -> ! { + panic!("{}", fmt) + } +} + +impl<'p> fmt::Debug for MatchCheckCtx<'p> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MatchCheckCtx").finish() + } +} diff --git a/crates/hir-ty/src/diagnostics/match_check/usefulness.rs b/crates/hir-ty/src/diagnostics/match_check/usefulness.rs deleted file mode 100644 index 1b1a5ff269413..0000000000000 --- a/crates/hir-ty/src/diagnostics/match_check/usefulness.rs +++ /dev/null @@ -1,824 +0,0 @@ -//! Based on rust-lang/rust (last sync f31622a50 2021-11-12) -//! -//! -//! ----- -//! -//! This file includes the logic for exhaustiveness and reachability checking for pattern-matching. -//! Specifically, given a list of patterns for a type, we can tell whether: -//! (a) each pattern is reachable (reachability) -//! (b) the patterns cover every possible value for the type (exhaustiveness) -//! -//! The algorithm implemented here is a modified version of the one described in [this -//! paper](http://moscova.inria.fr/~maranget/papers/warn/index.html). We have however generalized -//! it to accommodate the variety of patterns that Rust supports. We thus explain our version here, -//! without being as rigorous. -//! -//! -//! # Summary -//! -//! The core of the algorithm is the notion of "usefulness". A pattern `q` is said to be *useful* -//! relative to another pattern `p` of the same type if there is a value that is matched by `q` and -//! not matched by `p`. This generalizes to many `p`s: `q` is useful w.r.t. a list of patterns -//! `p_1 .. p_n` if there is a value that is matched by `q` and by none of the `p_i`. We write -//! `usefulness(p_1 .. p_n, q)` for a function that returns a list of such values. The aim of this -//! file is to compute it efficiently. -//! -//! This is enough to compute reachability: a pattern in a `match` expression is reachable iff it -//! is useful w.r.t. the patterns above it: -//! ```rust -//! match x { -//! Some(_) => ..., -//! None => ..., // reachable: `None` is matched by this but not the branch above -//! Some(0) => ..., // unreachable: all the values this matches are already matched by -//! // `Some(_)` above -//! } -//! ``` -//! -//! This is also enough to compute exhaustiveness: a match is exhaustive iff the wildcard `_` -//! pattern is _not_ useful w.r.t. the patterns in the match. The values returned by `usefulness` -//! are used to tell the user which values are missing. -//! ```rust -//! match x { -//! Some(0) => ..., -//! None => ..., -//! // not exhaustive: `_` is useful because it matches `Some(1)` -//! } -//! ``` -//! -//! The entrypoint of this file is the [`compute_match_usefulness`] function, which computes -//! reachability for each match branch and exhaustiveness for the whole match. -//! -//! -//! # Constructors and fields -//! -//! Note: we will often abbreviate "constructor" as "ctor". -//! -//! The idea that powers everything that is done in this file is the following: a (matcheable) -//! value is made from a constructor applied to a number of subvalues. Examples of constructors are -//! `Some`, `None`, `(,)` (the 2-tuple constructor), `Foo {..}` (the constructor for a struct -//! `Foo`), and `2` (the constructor for the number `2`). This is natural when we think of -//! pattern-matching, and this is the basis for what follows. -//! -//! Some of the ctors listed above might feel weird: `None` and `2` don't take any arguments. -//! That's ok: those are ctors that take a list of 0 arguments; they are the simplest case of -//! ctors. We treat `2` as a ctor because `u64` and other number types behave exactly like a huge -//! `enum`, with one variant for each number. This allows us to see any matcheable value as made up -//! from a tree of ctors, each having a set number of children. For example: `Foo { bar: None, -//! baz: Ok(0) }` is made from 4 different ctors, namely `Foo{..}`, `None`, `Ok` and `0`. -//! -//! This idea can be extended to patterns: they are also made from constructors applied to fields. -//! A pattern for a given type is allowed to use all the ctors for values of that type (which we -//! call "value constructors"), but there are also pattern-only ctors. The most important one is -//! the wildcard (`_`), and the others are integer ranges (`0..=10`), variable-length slices (`[x, -//! ..]`), and or-patterns (`Ok(0) | Err(_)`). Examples of valid patterns are `42`, `Some(_)`, `Foo -//! { bar: Some(0) | None, baz: _ }`. Note that a binder in a pattern (e.g. `Some(x)`) matches the -//! same values as a wildcard (e.g. `Some(_)`), so we treat both as wildcards. -//! -//! From this deconstruction we can compute whether a given value matches a given pattern; we -//! simply look at ctors one at a time. Given a pattern `p` and a value `v`, we want to compute -//! `matches!(v, p)`. It's mostly straightforward: we compare the head ctors and when they match -//! we compare their fields recursively. A few representative examples: -//! -//! - `matches!(v, _) := true` -//! - `matches!((v0, v1), (p0, p1)) := matches!(v0, p0) && matches!(v1, p1)` -//! - `matches!(Foo { bar: v0, baz: v1 }, Foo { bar: p0, baz: p1 }) := matches!(v0, p0) && matches!(v1, p1)` -//! - `matches!(Ok(v0), Ok(p0)) := matches!(v0, p0)` -//! - `matches!(Ok(v0), Err(p0)) := false` (incompatible variants) -//! - `matches!(v, 1..=100) := matches!(v, 1) || ... || matches!(v, 100)` -//! - `matches!([v0], [p0, .., p1]) := false` (incompatible lengths) -//! - `matches!([v0, v1, v2], [p0, .., p1]) := matches!(v0, p0) && matches!(v2, p1)` -//! - `matches!(v, p0 | p1) := matches!(v, p0) || matches!(v, p1)` -//! -//! Constructors, fields and relevant operations are defined in the [`super::deconstruct_pat`] module. -//! -//! Note: this constructors/fields distinction may not straightforwardly apply to every Rust type. -//! For example a value of type `Rc` can't be deconstructed that way, and `&str` has an -//! infinitude of constructors. There are also subtleties with visibility of fields and -//! uninhabitedness and various other things. The constructors idea can be extended to handle most -//! of these subtleties though; caveats are documented where relevant throughout the code. -//! -//! Whether constructors cover each other is computed by [`Constructor::is_covered_by`]. -//! -//! -//! # Specialization -//! -//! Recall that we wish to compute `usefulness(p_1 .. p_n, q)`: given a list of patterns `p_1 .. -//! p_n` and a pattern `q`, all of the same type, we want to find a list of values (called -//! "witnesses") that are matched by `q` and by none of the `p_i`. We obviously don't just -//! enumerate all possible values. From the discussion above we see that we can proceed -//! ctor-by-ctor: for each value ctor of the given type, we ask "is there a value that starts with -//! this constructor and matches `q` and none of the `p_i`?". As we saw above, there's a lot we can -//! say from knowing only the first constructor of our candidate value. -//! -//! Let's take the following example: -//! ``` -//! match x { -//! Enum::Variant1(_) => {} // `p1` -//! Enum::Variant2(None, 0) => {} // `p2` -//! Enum::Variant2(Some(_), 0) => {} // `q` -//! } -//! ``` -//! -//! We can easily see that if our candidate value `v` starts with `Variant1` it will not match `q`. -//! If `v = Variant2(v0, v1)` however, whether or not it matches `p2` and `q` will depend on `v0` -//! and `v1`. In fact, such a `v` will be a witness of usefulness of `q` exactly when the tuple -//! `(v0, v1)` is a witness of usefulness of `q'` in the following reduced match: -//! -//! ``` -//! match x { -//! (None, 0) => {} // `p2'` -//! (Some(_), 0) => {} // `q'` -//! } -//! ``` -//! -//! This motivates a new step in computing usefulness, that we call _specialization_. -//! Specialization consist of filtering a list of patterns for those that match a constructor, and -//! then looking into the constructor's fields. This enables usefulness to be computed recursively. -//! -//! Instead of acting on a single pattern in each row, we will consider a list of patterns for each -//! row, and we call such a list a _pattern-stack_. The idea is that we will specialize the -//! leftmost pattern, which amounts to popping the constructor and pushing its fields, which feels -//! like a stack. We note a pattern-stack simply with `[p_1 ... p_n]`. -//! Here's a sequence of specializations of a list of pattern-stacks, to illustrate what's -//! happening: -//! ``` -//! [Enum::Variant1(_)] -//! [Enum::Variant2(None, 0)] -//! [Enum::Variant2(Some(_), 0)] -//! //==>> specialize with `Variant2` -//! [None, 0] -//! [Some(_), 0] -//! //==>> specialize with `Some` -//! [_, 0] -//! //==>> specialize with `true` (say the type was `bool`) -//! [0] -//! //==>> specialize with `0` -//! [] -//! ``` -//! -//! The function `specialize(c, p)` takes a value constructor `c` and a pattern `p`, and returns 0 -//! or more pattern-stacks. If `c` does not match the head constructor of `p`, it returns nothing; -//! otherwise if returns the fields of the constructor. This only returns more than one -//! pattern-stack if `p` has a pattern-only constructor. -//! -//! - Specializing for the wrong constructor returns nothing -//! -//! `specialize(None, Some(p0)) := []` -//! -//! - Specializing for the correct constructor returns a single row with the fields -//! -//! `specialize(Variant1, Variant1(p0, p1, p2)) := [[p0, p1, p2]]` -//! -//! `specialize(Foo{..}, Foo { bar: p0, baz: p1 }) := [[p0, p1]]` -//! -//! - For or-patterns, we specialize each branch and concatenate the results -//! -//! `specialize(c, p0 | p1) := specialize(c, p0) ++ specialize(c, p1)` -//! -//! - We treat the other pattern constructors as if they were a large or-pattern of all the -//! possibilities: -//! -//! `specialize(c, _) := specialize(c, Variant1(_) | Variant2(_, _) | ...)` -//! -//! `specialize(c, 1..=100) := specialize(c, 1 | ... | 100)` -//! -//! `specialize(c, [p0, .., p1]) := specialize(c, [p0, p1] | [p0, _, p1] | [p0, _, _, p1] | ...)` -//! -//! - If `c` is a pattern-only constructor, `specialize` is defined on a case-by-case basis. See -//! the discussion about constructor splitting in [`super::deconstruct_pat`]. -//! -//! -//! We then extend this function to work with pattern-stacks as input, by acting on the first -//! column and keeping the other columns untouched. -//! -//! Specialization for the whole matrix is done in [`Matrix::specialize_constructor`]. Note that -//! or-patterns in the first column are expanded before being stored in the matrix. Specialization -//! for a single patstack is done from a combination of [`Constructor::is_covered_by`] and -//! [`PatStack::pop_head_constructor`]. The internals of how it's done mostly live in the -//! [`Fields`] struct. -//! -//! -//! # Computing usefulness -//! -//! We now have all we need to compute usefulness. The inputs to usefulness are a list of -//! pattern-stacks `p_1 ... p_n` (one per row), and a new pattern_stack `q`. The paper and this -//! file calls the list of patstacks a _matrix_. They must all have the same number of columns and -//! the patterns in a given column must all have the same type. `usefulness` returns a (possibly -//! empty) list of witnesses of usefulness. These witnesses will also be pattern-stacks. -//! -//! - base case: `n_columns == 0`. -//! Since a pattern-stack functions like a tuple of patterns, an empty one functions like the -//! unit type. Thus `q` is useful iff there are no rows above it, i.e. if `n == 0`. -//! -//! - inductive case: `n_columns > 0`. -//! We need a way to list the constructors we want to try. We will be more clever in the next -//! section but for now assume we list all value constructors for the type of the first column. -//! -//! - for each such ctor `c`: -//! -//! - for each `q'` returned by `specialize(c, q)`: -//! -//! - we compute `usefulness(specialize(c, p_1) ... specialize(c, p_n), q')` -//! -//! - for each witness found, we revert specialization by pushing the constructor `c` on top. -//! -//! - We return the concatenation of all the witnesses found, if any. -//! -//! Example: -//! ``` -//! [Some(true)] // p_1 -//! [None] // p_2 -//! [Some(_)] // q -//! //==>> try `None`: `specialize(None, q)` returns nothing -//! //==>> try `Some`: `specialize(Some, q)` returns a single row -//! [true] // p_1' -//! [_] // q' -//! //==>> try `true`: `specialize(true, q')` returns a single row -//! [] // p_1'' -//! [] // q'' -//! //==>> base case; `n != 0` so `q''` is not useful. -//! //==>> go back up a step -//! [true] // p_1' -//! [_] // q' -//! //==>> try `false`: `specialize(false, q')` returns a single row -//! [] // q'' -//! //==>> base case; `n == 0` so `q''` is useful. We return the single witness `[]` -//! witnesses: -//! [] -//! //==>> undo the specialization with `false` -//! witnesses: -//! [false] -//! //==>> undo the specialization with `Some` -//! witnesses: -//! [Some(false)] -//! //==>> we have tried all the constructors. The output is the single witness `[Some(false)]`. -//! ``` -//! -//! This computation is done in [`is_useful`]. In practice we don't care about the list of -//! witnesses when computing reachability; we only need to know whether any exist. We do keep the -//! witnesses when computing exhaustiveness to report them to the user. -//! -//! -//! # Making usefulness tractable: constructor splitting -//! -//! We're missing one last detail: which constructors do we list? Naively listing all value -//! constructors cannot work for types like `u64` or `&str`, so we need to be more clever. The -//! first obvious insight is that we only want to list constructors that are covered by the head -//! constructor of `q`. If it's a value constructor, we only try that one. If it's a pattern-only -//! constructor, we use the final clever idea for this algorithm: _constructor splitting_, where we -//! group together constructors that behave the same. -//! -//! The details are not necessary to understand this file, so we explain them in -//! [`super::deconstruct_pat`]. Splitting is done by the [`Constructor::split`] function. - -use std::iter::once; - -use hir_def::{AdtId, DefWithBodyId, HasModule, ModuleId}; -use smallvec::{smallvec, SmallVec}; -use typed_arena::Arena; - -use crate::{db::HirDatabase, inhabitedness::is_ty_uninhabited_from, Ty, TyExt}; - -use super::deconstruct_pat::{Constructor, DeconstructedPat, Fields, SplitWildcard}; - -use self::{helper::Captures, ArmType::*, Usefulness::*}; - -pub(crate) struct MatchCheckCtx<'a, 'p> { - pub(crate) module: ModuleId, - pub(crate) body: DefWithBodyId, - pub(crate) db: &'a dyn HirDatabase, - /// Lowered patterns from arms plus generated by the check. - pub(crate) pattern_arena: &'p Arena>, - exhaustive_patterns: bool, -} - -impl<'a, 'p> MatchCheckCtx<'a, 'p> { - pub(crate) fn new( - module: ModuleId, - body: DefWithBodyId, - db: &'a dyn HirDatabase, - pattern_arena: &'p Arena>, - ) -> Self { - let def_map = db.crate_def_map(module.krate()); - let exhaustive_patterns = def_map.is_unstable_feature_enabled("exhaustive_patterns"); - Self { module, body, db, pattern_arena, exhaustive_patterns } - } - - pub(super) fn is_uninhabited(&self, ty: &Ty) -> bool { - if self.feature_exhaustive_patterns() { - is_ty_uninhabited_from(ty, self.module, self.db) - } else { - false - } - } - - /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`. - pub(super) fn is_foreign_non_exhaustive_enum(&self, ty: &Ty) -> bool { - match ty.as_adt() { - Some((adt @ AdtId::EnumId(_), _)) => { - let has_non_exhaustive_attr = - self.db.attrs(adt.into()).by_key("non_exhaustive").exists(); - let is_local = adt.module(self.db.upcast()).krate() == self.module.krate(); - has_non_exhaustive_attr && !is_local - } - _ => false, - } - } - - // Rust's unstable feature described as "Allows exhaustive pattern matching on types that contain uninhabited types." - pub(super) fn feature_exhaustive_patterns(&self) -> bool { - self.exhaustive_patterns - } -} - -#[derive(Copy, Clone)] -pub(super) struct PatCtxt<'a, 'p> { - pub(super) cx: &'a MatchCheckCtx<'a, 'p>, - /// Type of the current column under investigation. - pub(super) ty: &'a Ty, - /// Whether the current pattern is the whole pattern as found in a match arm, or if it's a - /// subpattern. - pub(super) is_top_level: bool, - /// Whether the current pattern is from a `non_exhaustive` enum. - pub(super) is_non_exhaustive: bool, -} - -/// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]` -/// works well. -#[derive(Clone)] -pub(super) struct PatStack<'p> { - pats: SmallVec<[&'p DeconstructedPat<'p>; 2]>, -} - -impl<'p> PatStack<'p> { - fn from_pattern(pat: &'p DeconstructedPat<'p>) -> Self { - Self::from_vec(smallvec![pat]) - } - - fn from_vec(vec: SmallVec<[&'p DeconstructedPat<'p>; 2]>) -> Self { - PatStack { pats: vec } - } - - fn is_empty(&self) -> bool { - self.pats.is_empty() - } - - fn len(&self) -> usize { - self.pats.len() - } - - fn head(&self) -> &'p DeconstructedPat<'p> { - self.pats[0] - } - - // Recursively expand the first pattern into its subpatterns. Only useful if the pattern is an - // or-pattern. Panics if `self` is empty. - fn expand_or_pat(&self) -> impl Iterator> + Captures<'_> { - self.head().iter_fields().map(move |pat| { - let mut new_patstack = PatStack::from_pattern(pat); - new_patstack.pats.extend_from_slice(&self.pats[1..]); - new_patstack - }) - } - - /// This computes `S(self.head().ctor(), self)`. See top of the file for explanations. - /// - /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing - /// fields filled with wild patterns. - /// - /// This is roughly the inverse of `Constructor::apply`. - fn pop_head_constructor(&self, cx: &MatchCheckCtx<'_, 'p>, ctor: &Constructor) -> PatStack<'p> { - // We pop the head pattern and push the new fields extracted from the arguments of - // `self.head()`. - let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(cx, ctor); - new_fields.extend_from_slice(&self.pats[1..]); - PatStack::from_vec(new_fields) - } -} - -/// A 2D matrix. -#[derive(Clone)] -pub(super) struct Matrix<'p> { - patterns: Vec>, -} - -impl<'p> Matrix<'p> { - fn empty() -> Self { - Matrix { patterns: vec![] } - } - - /// Number of columns of this matrix. `None` is the matrix is empty. - pub(super) fn _column_count(&self) -> Option { - self.patterns.first().map(|r| r.len()) - } - - /// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively - /// expands it. - fn push(&mut self, row: PatStack<'p>) { - if !row.is_empty() && row.head().is_or_pat() { - self.patterns.extend(row.expand_or_pat()); - } else { - self.patterns.push(row); - } - } - - /// Iterate over the first component of each row - fn heads(&self) -> impl Iterator> + Clone + Captures<'_> { - self.patterns.iter().map(|r| r.head()) - } - - /// This computes `S(constructor, self)`. See top of the file for explanations. - fn specialize_constructor(&self, pcx: PatCtxt<'_, 'p>, ctor: &Constructor) -> Matrix<'p> { - let mut matrix = Matrix::empty(); - for row in &self.patterns { - if ctor.is_covered_by(pcx, row.head().ctor()) { - let new_row = row.pop_head_constructor(pcx.cx, ctor); - matrix.push(new_row); - } - } - matrix - } -} - -/// This carries the results of computing usefulness, as described at the top of the file. When -/// checking usefulness of a match branch, we use the `NoWitnesses` variant, which also keeps track -/// of potential unreachable sub-patterns (in the presence of or-patterns). When checking -/// exhaustiveness of a whole match, we use the `WithWitnesses` variant, which carries a list of -/// witnesses of non-exhaustiveness when there are any. -/// Which variant to use is dictated by `ArmType`. -enum Usefulness<'p> { - /// If we don't care about witnesses, simply remember if the pattern was useful. - NoWitnesses { useful: bool }, - /// Carries a list of witnesses of non-exhaustiveness. If empty, indicates that the whole - /// pattern is unreachable. - WithWitnesses(Vec>), -} - -impl<'p> Usefulness<'p> { - fn new_useful(preference: ArmType) -> Self { - match preference { - // A single (empty) witness of reachability. - FakeExtraWildcard => WithWitnesses(vec![Witness(vec![])]), - RealArm => NoWitnesses { useful: true }, - } - } - fn new_not_useful(preference: ArmType) -> Self { - match preference { - FakeExtraWildcard => WithWitnesses(vec![]), - RealArm => NoWitnesses { useful: false }, - } - } - - fn is_useful(&self) -> bool { - match self { - Usefulness::NoWitnesses { useful } => *useful, - Usefulness::WithWitnesses(witnesses) => !witnesses.is_empty(), - } - } - - /// Combine usefulnesses from two branches. This is an associative operation. - fn extend(&mut self, other: Self) { - match (&mut *self, other) { - (WithWitnesses(_), WithWitnesses(o)) if o.is_empty() => {} - (WithWitnesses(s), WithWitnesses(o)) if s.is_empty() => *self = WithWitnesses(o), - (WithWitnesses(s), WithWitnesses(o)) => s.extend(o), - (NoWitnesses { useful: s_useful }, NoWitnesses { useful: o_useful }) => { - *s_useful = *s_useful || o_useful - } - _ => unreachable!(), - } - } - - /// After calculating usefulness after a specialization, call this to reconstruct a usefulness - /// that makes sense for the matrix pre-specialization. This new usefulness can then be merged - /// with the results of specializing with the other constructors. - fn apply_constructor( - self, - pcx: PatCtxt<'_, 'p>, - matrix: &Matrix<'p>, - ctor: &Constructor, - ) -> Self { - match self { - NoWitnesses { .. } => self, - WithWitnesses(ref witnesses) if witnesses.is_empty() => self, - WithWitnesses(witnesses) => { - let new_witnesses = if let Constructor::Missing { .. } = ctor { - // We got the special `Missing` constructor, so each of the missing constructors - // gives a new pattern that is not caught by the match. We list those patterns. - let new_patterns = if pcx.is_non_exhaustive { - // Here we don't want the user to try to list all variants, we want them to add - // a wildcard, so we only suggest that. - vec![DeconstructedPat::wildcard(pcx.ty.clone())] - } else { - let mut split_wildcard = SplitWildcard::new(pcx); - split_wildcard.split(pcx, matrix.heads().map(DeconstructedPat::ctor)); - - // This lets us know if we skipped any variants because they are marked - // `doc(hidden)` or they are unstable feature gate (only stdlib types). - let mut hide_variant_show_wild = false; - // Construct for each missing constructor a "wild" version of this - // constructor, that matches everything that can be built with - // it. For example, if `ctor` is a `Constructor::Variant` for - // `Option::Some`, we get the pattern `Some(_)`. - let mut new: Vec> = split_wildcard - .iter_missing(pcx) - .filter_map(|missing_ctor| { - // Check if this variant is marked `doc(hidden)` - if missing_ctor.is_doc_hidden_variant(pcx) - || missing_ctor.is_unstable_variant(pcx) - { - hide_variant_show_wild = true; - return None; - } - Some(DeconstructedPat::wild_from_ctor(pcx, missing_ctor.clone())) - }) - .collect(); - - if hide_variant_show_wild { - new.push(DeconstructedPat::wildcard(pcx.ty.clone())) - } - - new - }; - - witnesses - .into_iter() - .flat_map(|witness| { - new_patterns.iter().map(move |pat| { - Witness( - witness - .0 - .iter() - .chain(once(pat)) - .map(DeconstructedPat::clone_and_forget_reachability) - .collect(), - ) - }) - }) - .collect() - } else { - witnesses - .into_iter() - .map(|witness| witness.apply_constructor(pcx, ctor)) - .collect() - }; - WithWitnesses(new_witnesses) - } - } - } -} - -#[derive(Copy, Clone, Debug)] -enum ArmType { - FakeExtraWildcard, - RealArm, -} - -/// A witness of non-exhaustiveness for error reporting, represented -/// as a list of patterns (in reverse order of construction) with -/// wildcards inside to represent elements that can take any inhabitant -/// of the type as a value. -/// -/// A witness against a list of patterns should have the same types -/// and length as the pattern matched against. Because Rust `match` -/// is always against a single pattern, at the end the witness will -/// have length 1, but in the middle of the algorithm, it can contain -/// multiple patterns. -/// -/// For example, if we are constructing a witness for the match against -/// -/// ``` -/// struct Pair(Option<(u32, u32)>, bool); -/// -/// match (p: Pair) { -/// Pair(None, _) => {} -/// Pair(_, false) => {} -/// } -/// ``` -/// -/// We'll perform the following steps: -/// 1. Start with an empty witness -/// `Witness(vec![])` -/// 2. Push a witness `true` against the `false` -/// `Witness(vec![true])` -/// 3. Push a witness `Some(_)` against the `None` -/// `Witness(vec![true, Some(_)])` -/// 4. Apply the `Pair` constructor to the witnesses -/// `Witness(vec![Pair(Some(_), true)])` -/// -/// The final `Pair(Some(_), true)` is then the resulting witness. -pub(crate) struct Witness<'p>(Vec>); - -impl<'p> Witness<'p> { - /// Asserts that the witness contains a single pattern, and returns it. - fn single_pattern(self) -> DeconstructedPat<'p> { - assert_eq!(self.0.len(), 1); - self.0.into_iter().next().unwrap() - } - - /// Constructs a partial witness for a pattern given a list of - /// patterns expanded by the specialization step. - /// - /// When a pattern P is discovered to be useful, this function is used bottom-up - /// to reconstruct a complete witness, e.g., a pattern P' that covers a subset - /// of values, V, where each value in that set is not covered by any previously - /// used patterns and is covered by the pattern P'. Examples: - /// - /// left_ty: tuple of 3 elements - /// pats: [10, 20, _] => (10, 20, _) - /// - /// left_ty: struct X { a: (bool, &'static str), b: usize} - /// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 } - fn apply_constructor(mut self, pcx: PatCtxt<'_, 'p>, ctor: &Constructor) -> Self { - let pat = { - let len = self.0.len(); - let arity = ctor.arity(pcx); - let pats = self.0.drain((len - arity)..).rev(); - let fields = Fields::from_iter(pcx.cx, pats); - DeconstructedPat::new(ctor.clone(), fields, pcx.ty.clone()) - }; - - self.0.push(pat); - - self - } -} - -/// Algorithm from . -/// The algorithm from the paper has been modified to correctly handle empty -/// types. The changes are: -/// (0) We don't exit early if the pattern matrix has zero rows. We just -/// continue to recurse over columns. -/// (1) all_constructors will only return constructors that are statically -/// possible. E.g., it will only return `Ok` for `Result`. -/// -/// This finds whether a (row) vector `v` of patterns is 'useful' in relation -/// to a set of such vectors `m` - this is defined as there being a set of -/// inputs that will match `v` but not any of the sets in `m`. -/// -/// All the patterns at each column of the `matrix ++ v` matrix must have the same type. -/// -/// This is used both for reachability checking (if a pattern isn't useful in -/// relation to preceding patterns, it is not reachable) and exhaustiveness -/// checking (if a wildcard pattern is useful in relation to a matrix, the -/// matrix isn't exhaustive). -/// -/// `is_under_guard` is used to inform if the pattern has a guard. If it -/// has one it must not be inserted into the matrix. This shouldn't be -/// relied on for soundness. -fn is_useful<'p>( - cx: &MatchCheckCtx<'_, 'p>, - matrix: &Matrix<'p>, - v: &PatStack<'p>, - witness_preference: ArmType, - is_under_guard: bool, - is_top_level: bool, -) -> Usefulness<'p> { - let Matrix { patterns: rows, .. } = matrix; - - // The base case. We are pattern-matching on () and the return value is - // based on whether our matrix has a row or not. - // NOTE: This could potentially be optimized by checking rows.is_empty() - // first and then, if v is non-empty, the return value is based on whether - // the type of the tuple we're checking is inhabited or not. - if v.is_empty() { - let ret = if rows.is_empty() { - Usefulness::new_useful(witness_preference) - } else { - Usefulness::new_not_useful(witness_preference) - }; - return ret; - } - - debug_assert!(rows.iter().all(|r| r.len() == v.len())); - - let ty = v.head().ty(); - let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty); - let pcx = PatCtxt { cx, ty, is_top_level, is_non_exhaustive }; - - // If the first pattern is an or-pattern, expand it. - let mut ret = Usefulness::new_not_useful(witness_preference); - if v.head().is_or_pat() { - // We try each or-pattern branch in turn. - let mut matrix = matrix.clone(); - for v in v.expand_or_pat() { - let usefulness = is_useful(cx, &matrix, &v, witness_preference, is_under_guard, false); - ret.extend(usefulness); - // If pattern has a guard don't add it to the matrix. - if !is_under_guard { - // We push the already-seen patterns into the matrix in order to detect redundant - // branches like `Some(_) | Some(0)`. - matrix.push(v); - } - } - } else { - let v_ctor = v.head().ctor(); - - // FIXME: implement `overlapping_range_endpoints` lint - - // We split the head constructor of `v`. - let split_ctors = v_ctor.split(pcx, matrix.heads().map(DeconstructedPat::ctor)); - // For each constructor, we compute whether there's a value that starts with it that would - // witness the usefulness of `v`. - let start_matrix = matrix; - for ctor in split_ctors { - // We cache the result of `Fields::wildcards` because it is used a lot. - let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor); - let v = v.pop_head_constructor(cx, &ctor); - let usefulness = - is_useful(cx, &spec_matrix, &v, witness_preference, is_under_guard, false); - let usefulness = usefulness.apply_constructor(pcx, start_matrix, &ctor); - - // FIXME: implement `non_exhaustive_omitted_patterns` lint - - ret.extend(usefulness); - } - }; - - if ret.is_useful() { - v.head().set_reachable(); - } - - ret -} - -/// The arm of a match expression. -#[derive(Clone, Copy)] -pub(crate) struct MatchArm<'p> { - pub(crate) pat: &'p DeconstructedPat<'p>, - pub(crate) has_guard: bool, -} - -/// Indicates whether or not a given arm is reachable. -#[derive(Clone, Debug)] -pub(crate) enum Reachability { - /// The arm is reachable. This additionally carries a set of or-pattern branches that have been - /// found to be unreachable despite the overall arm being reachable. Used only in the presence - /// of or-patterns, otherwise it stays empty. - // FIXME: store unreachable subpattern IDs - Reachable, - /// The arm is unreachable. - Unreachable, -} - -/// The output of checking a match for exhaustiveness and arm reachability. -pub(crate) struct UsefulnessReport<'p> { - /// For each arm of the input, whether that arm is reachable after the arms above it. - pub(crate) _arm_usefulness: Vec<(MatchArm<'p>, Reachability)>, - /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of - /// exhaustiveness. - pub(crate) non_exhaustiveness_witnesses: Vec>, -} - -/// The entrypoint for the usefulness algorithm. Computes whether a match is exhaustive and which -/// of its arms are reachable. -/// -/// Note: the input patterns must have been lowered through -/// `check_match::MatchVisitor::lower_pattern`. -pub(crate) fn compute_match_usefulness<'p>( - cx: &MatchCheckCtx<'_, 'p>, - arms: &[MatchArm<'p>], - scrut_ty: &Ty, -) -> UsefulnessReport<'p> { - let mut matrix = Matrix::empty(); - let arm_usefulness = arms - .iter() - .copied() - .map(|arm| { - let v = PatStack::from_pattern(arm.pat); - is_useful(cx, &matrix, &v, RealArm, arm.has_guard, true); - if !arm.has_guard { - matrix.push(v); - } - let reachability = if arm.pat.is_reachable() { - Reachability::Reachable - } else { - Reachability::Unreachable - }; - (arm, reachability) - }) - .collect(); - - let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty.clone())); - let v = PatStack::from_pattern(wild_pattern); - let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, false, true); - let non_exhaustiveness_witnesses = match usefulness { - WithWitnesses(pats) => pats.into_iter().map(Witness::single_pattern).collect(), - NoWitnesses { .. } => panic!("bug"), - }; - UsefulnessReport { _arm_usefulness: arm_usefulness, non_exhaustiveness_witnesses } -} - -pub(crate) mod helper { - // Copy-pasted from rust/compiler/rustc_data_structures/src/captures.rs - /// "Signaling" trait used in impl trait to tag lifetimes that you may - /// need to capture but don't really need for other reasons. - /// Basically a workaround; see [this comment] for details. - /// - /// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999 - // FIXME(eddyb) false positive, the lifetime parameter is "phantom" but needed. - #[allow(unused_lifetimes)] - pub(crate) trait Captures<'a> {} - - impl<'a, T: ?Sized> Captures<'a> for T {} -} diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 19052a18b1923..54e91e7b29a66 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -15,6 +15,9 @@ extern crate rustc_abi; #[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_abi as rustc_abi; +// No need to use the in-tree one. +extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis; + mod builder; mod chalk_db; mod chalk_ext; @@ -38,10 +41,10 @@ pub mod mir; pub mod primitive; pub mod traits; -#[cfg(test)] -mod tests; #[cfg(test)] mod test_db; +#[cfg(test)] +mod tests; use std::{ collections::hash_map::Entry, diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs index 952a97e3d0f6c..494f1850b88ab 100644 --- a/crates/hir-ty/src/mir.rs +++ b/crates/hir-ty/src/mir.rs @@ -21,11 +21,11 @@ use hir_def::{ }; use la_arena::{Arena, ArenaMap, Idx, RawIdx}; +mod borrowck; mod eval; mod lower; -mod borrowck; -mod pretty; mod monomorphization; +mod pretty; pub use borrowck::{borrowck_query, BorrowckResult, MutabilityReason}; pub use eval::{ diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs index 671fd9ec3a451..9804910c878d4 100644 --- a/crates/hir-ty/src/tests.rs +++ b/crates/hir-ty/src/tests.rs @@ -1,14 +1,14 @@ -mod never_type; mod coercion; +mod diagnostics; +mod display_source_code; +mod incremental; +mod macros; +mod method_resolution; +mod never_type; +mod patterns; mod regression; mod simple; -mod patterns; mod traits; -mod method_resolution; -mod macros; -mod display_source_code; -mod incremental; -mod diagnostics; use std::{collections::HashMap, env}; diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 7b9f895bc73eb..fc0a196df7cbe 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -2,7 +2,6 @@ use std::ops::ControlFlow; -use base_db::FileId; use hir_def::{ attr::AttrsWithOwner, item_scope::ItemInNs, @@ -11,12 +10,8 @@ use hir_def::{ resolver::{HasResolver, Resolver, TypeNs}, AssocItemId, AttrDefId, ModuleDefId, }; -use hir_expand::{ - name::Name, - span_map::{RealSpanMap, SpanMapRef}, -}; +use hir_expand::{mod_path::PathKind, name::Name}; use hir_ty::{db::HirDatabase, method_resolution}; -use syntax::{ast, AstNode}; use crate::{ Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, @@ -129,7 +124,7 @@ fn resolve_doc_path_on_( AttrDefId::GenericParamId(_) => return None, }; - let mut modpath = modpath_from_str(db, link)?; + let mut modpath = modpath_from_str(link)?; let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath); if resolved.is_none() { @@ -305,34 +300,37 @@ fn as_module_def_if_namespace_matches( (ns.unwrap_or(expected_ns) == expected_ns).then(|| DocLinkDef::ModuleDef(def)) } -fn modpath_from_str(db: &dyn HirDatabase, link: &str) -> Option { +fn modpath_from_str(link: &str) -> Option { // FIXME: this is not how we should get a mod path here. let try_get_modpath = |link: &str| { - let ast_path = ast::SourceFile::parse(&format!("type T = {link};")) - .syntax_node() - .descendants() - .find_map(ast::Path::cast)?; - if ast_path.syntax().text() != link { - return None; - } - ModPath::from_src( - db.upcast(), - ast_path, - SpanMapRef::RealSpanMap(&RealSpanMap::absolute(FileId::BOGUS)), - ) + let mut parts = link.split("::"); + let mut first_segment = None; + let kind = match parts.next()? { + "" => PathKind::Abs, + "crate" => PathKind::Crate, + "self" => PathKind::Super(0), + "super" => { + let mut deg = 1; + while let Some(segment) = parts.next() { + if segment == "super" { + deg += 1; + } else { + first_segment = Some(segment); + break; + } + } + PathKind::Super(deg) + } + segment => { + first_segment = Some(segment); + PathKind::Plain + } + }; + let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() { + Ok(idx) => Name::new_tuple_field(idx), + Err(_) => Name::new_text_dont_use(segment.into()), + }); + Some(ModPath::from_segments(kind, parts)) }; - - let full = try_get_modpath(link); - if full.is_some() { - return full; - } - - // Tuple field names cannot be a part of `ModPath` usually, but rustdoc can - // resolve doc paths like `TupleStruct::0`. - // FIXME: Find a better way to handle these. - let (base, maybe_tuple_field) = link.rsplit_once("::")?; - let tuple_field = Name::new_tuple_field(maybe_tuple_field.parse().ok()?); - let mut modpath = try_get_modpath(base)?; - modpath.push_segment(tuple_field); - Some(modpath) + try_get_modpath(link) } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c50be5f11419d..c332ab0050cfb 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -24,12 +24,12 @@ mod semantics; mod source_analyzer; -mod from_id; mod attrs; +mod from_id; mod has_source; -pub mod diagnostics; pub mod db; +pub mod diagnostics; pub mod symbols; mod display; @@ -70,13 +70,12 @@ use hir_ty::{ primitive::UintTy, traits::FnTrait, AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, - GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution, - TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId, - WhereClause, + GenericArgData, InferenceDiagnostic, Interner, ParamKind, QuantifiedWhereClause, Scalar, + Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, + ValueTyDefId, WhereClause, }; use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; -use once_cell::unsync::Lazy; use rustc_hash::FxHashSet; use stdx::{impl_from, never}; use syntax::{ @@ -1592,53 +1591,46 @@ impl DefWithBody { } for diag in source_map.diagnostics() { - match diag { - BodyDiagnostic::InactiveCode { node, cfg, opts } => acc.push( - InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into(), - ), - BodyDiagnostic::MacroError { node, message } => acc.push( - MacroError { - node: (*node).map(|it| it.into()), - precise_location: None, - message: message.to_string(), - } - .into(), - ), - BodyDiagnostic::UnresolvedProcMacro { node, krate } => acc.push( - UnresolvedProcMacro { - node: (*node).map(|it| it.into()), - precise_location: None, - macro_name: None, - kind: MacroKind::ProcMacro, - krate: *krate, - } - .into(), - ), - BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push( - UnresolvedMacroCall { - macro_call: (*node).map(|ast_ptr| ast_ptr.into()), - precise_location: None, - path: path.clone(), - is_bang: true, - } - .into(), - ), + acc.push(match diag { + BodyDiagnostic::InactiveCode { node, cfg, opts } => { + InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into() + } + BodyDiagnostic::MacroError { node, message } => MacroError { + node: (*node).map(|it| it.into()), + precise_location: None, + message: message.to_string(), + } + .into(), + BodyDiagnostic::UnresolvedProcMacro { node, krate } => UnresolvedProcMacro { + node: (*node).map(|it| it.into()), + precise_location: None, + macro_name: None, + kind: MacroKind::ProcMacro, + krate: *krate, + } + .into(), + BodyDiagnostic::UnresolvedMacroCall { node, path } => UnresolvedMacroCall { + macro_call: (*node).map(|ast_ptr| ast_ptr.into()), + precise_location: None, + path: path.clone(), + is_bang: true, + } + .into(), BodyDiagnostic::UnreachableLabel { node, name } => { - acc.push(UnreachableLabel { node: *node, name: name.clone() }.into()) + UnreachableLabel { node: *node, name: name.clone() }.into() } BodyDiagnostic::UndeclaredLabel { node, name } => { - acc.push(UndeclaredLabel { node: *node, name: name.clone() }.into()) + UndeclaredLabel { node: *node, name: name.clone() }.into() } - } + }); } let infer = db.infer(self.into()); - let source_map = Lazy::new(|| db.body_with_source_map(self.into()).1); let expr_syntax = |expr| source_map.expr_syntax(expr).expect("unexpected synthetic"); let pat_syntax = |pat| source_map.pat_syntax(pat).expect("unexpected synthetic"); for d in &infer.diagnostics { - match d { - &hir_ty::InferenceDiagnostic::NoSuchField { field: expr, private } => { + acc.push(match d { + &InferenceDiagnostic::NoSuchField { field: expr, private } => { let expr_or_pat = match expr { ExprOrPatId::ExprId(expr) => { source_map.field_syntax(expr).map(AstPtr::wrap_left) @@ -1647,57 +1639,48 @@ impl DefWithBody { source_map.pat_field_syntax(pat).map(AstPtr::wrap_right) } }; - acc.push(NoSuchField { field: expr_or_pat, private }.into()) + NoSuchField { field: expr_or_pat, private }.into() } - &hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { - acc.push( - MismatchedArgCount { call_expr: expr_syntax(call_expr), expected, found } - .into(), - ) + &InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { + MismatchedArgCount { call_expr: expr_syntax(call_expr), expected, found }.into() } - &hir_ty::InferenceDiagnostic::PrivateField { expr, field } => { + &InferenceDiagnostic::PrivateField { expr, field } => { let expr = expr_syntax(expr); let field = field.into(); - acc.push(PrivateField { expr, field }.into()) + PrivateField { expr, field }.into() } - &hir_ty::InferenceDiagnostic::PrivateAssocItem { id, item } => { + &InferenceDiagnostic::PrivateAssocItem { id, item } => { let expr_or_pat = match id { ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), }; let item = item.into(); - acc.push(PrivateAssocItem { expr_or_pat, item }.into()) + PrivateAssocItem { expr_or_pat, item }.into() } - hir_ty::InferenceDiagnostic::ExpectedFunction { call_expr, found } => { + InferenceDiagnostic::ExpectedFunction { call_expr, found } => { let call_expr = expr_syntax(*call_expr); - - acc.push( - ExpectedFunction { - call: call_expr, - found: Type::new(db, DefWithBodyId::from(self), found.clone()), - } - .into(), - ) + ExpectedFunction { + call: call_expr, + found: Type::new(db, DefWithBodyId::from(self), found.clone()), + } + .into() } - hir_ty::InferenceDiagnostic::UnresolvedField { + InferenceDiagnostic::UnresolvedField { expr, receiver, name, method_with_same_name_exists, } => { let expr = expr_syntax(*expr); - - acc.push( - UnresolvedField { - expr, - name: name.clone(), - receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), - method_with_same_name_exists: *method_with_same_name_exists, - } - .into(), - ) + UnresolvedField { + expr, + name: name.clone(), + receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), + method_with_same_name_exists: *method_with_same_name_exists, + } + .into() } - hir_ty::InferenceDiagnostic::UnresolvedMethodCall { + InferenceDiagnostic::UnresolvedMethodCall { expr, receiver, name, @@ -1705,50 +1688,38 @@ impl DefWithBody { assoc_func_with_same_name, } => { let expr = expr_syntax(*expr); - - acc.push( - UnresolvedMethodCall { - expr, - name: name.clone(), - receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), - field_with_same_name: field_with_same_name - .clone() - .map(|ty| Type::new(db, DefWithBodyId::from(self), ty)), - assoc_func_with_same_name: *assoc_func_with_same_name, - } - .into(), - ) + UnresolvedMethodCall { + expr, + name: name.clone(), + receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), + field_with_same_name: field_with_same_name + .clone() + .map(|ty| Type::new(db, DefWithBodyId::from(self), ty)), + assoc_func_with_same_name: *assoc_func_with_same_name, + } + .into() } - &hir_ty::InferenceDiagnostic::UnresolvedAssocItem { id } => { + &InferenceDiagnostic::UnresolvedAssocItem { id } => { let expr_or_pat = match id { ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), }; - acc.push(UnresolvedAssocItem { expr_or_pat }.into()) + UnresolvedAssocItem { expr_or_pat }.into() } - &hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { - expr, - is_break, - bad_value_break, - } => { + &InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break, bad_value_break } => { let expr = expr_syntax(expr); - acc.push(BreakOutsideOfLoop { expr, is_break, bad_value_break }.into()) + BreakOutsideOfLoop { expr, is_break, bad_value_break }.into() } - hir_ty::InferenceDiagnostic::TypedHole { expr, expected } => { + InferenceDiagnostic::TypedHole { expr, expected } => { let expr = expr_syntax(*expr); - acc.push( - TypedHole { - expr, - expected: Type::new(db, DefWithBodyId::from(self), expected.clone()), - } - .into(), - ) + + TypedHole { + expr, + expected: Type::new(db, DefWithBodyId::from(self), expected.clone()), + } + .into() } - &hir_ty::InferenceDiagnostic::MismatchedTupleStructPatArgCount { - pat, - expected, - found, - } => { + &InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => { let expr_or_pat = match pat { ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), ExprOrPatId::PatId(pat) => { @@ -1762,11 +1733,9 @@ impl DefWithBody { InFile { file_id, value: ptr } } }; - acc.push( - MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into(), - ) + MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into() } - } + }); } for (pat_or_expr, mismatch) in infer.type_mismatches() { let expr_or_pat = match pat_or_expr { @@ -1805,8 +1774,6 @@ impl DefWithBody { } } - let hir_body = db.body(self.into()); - if let Ok(borrowck_results) = db.borrowck(self.into()) { for borrowck_result in borrowck_results.iter() { let mir_body = &borrowck_result.mir_body; @@ -1828,7 +1795,7 @@ impl DefWithBody { ) } let mol = &borrowck_result.mutability_of_locals; - for (binding_id, binding_data) in hir_body.bindings.iter() { + for (binding_id, binding_data) in body.bindings.iter() { if binding_data.problems.is_some() { // We should report specific diagnostics for these problems, not `need-mut` and `unused-mut`. continue; diff --git a/crates/ide-assists/src/handlers/sort_items.rs b/crates/ide-assists/src/handlers/sort_items.rs index 3a0121f55fa02..64e30b1834522 100644 --- a/crates/ide-assists/src/handlers/sort_items.rs +++ b/crates/ide-assists/src/handlers/sort_items.rs @@ -116,11 +116,9 @@ trait AddRewrite { new: Vec, target: TextRange, ) -> Option<()>; - fn yeet() {} } impl AddRewrite for Assists { - fn yeet() {} fn add_rewrite( &mut self, label: &str, diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index 1eb4903ab2033..edcf52a9b38eb 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -111,6 +111,8 @@ mod handlers { mod add_label_to_loop; mod add_lifetime_to_type; mod add_missing_impl_members; + mod add_missing_match_arms; + mod add_return_type; mod add_turbo_fish; mod apply_demorgan; mod auto_import; @@ -124,15 +126,15 @@ mod handlers { mod convert_iter_for_each_to_for; mod convert_let_else_to_match; mod convert_match_to_let_else; + mod convert_named_struct_to_tuple_struct; mod convert_nested_function_to_closure; + mod convert_to_guarded_return; mod convert_tuple_return_type_to_struct; mod convert_tuple_struct_to_named_struct; - mod convert_named_struct_to_tuple_struct; - mod convert_to_guarded_return; mod convert_two_arm_bool_match_to_matches_macro; mod convert_while_to_loop; - mod desugar_doc_comment; mod destructure_tuple_binding; + mod desugar_doc_comment; mod expand_glob_import; mod extract_expressions_from_format_string; mod extract_function; @@ -140,7 +142,6 @@ mod handlers { mod extract_struct_from_enum_variant; mod extract_type_alias; mod extract_variable; - mod add_missing_match_arms; mod fix_visibility; mod flip_binexpr; mod flip_comma; @@ -148,6 +149,7 @@ mod handlers { mod generate_constant; mod generate_default_from_enum_variant; mod generate_default_from_new; + mod generate_delegate_methods; mod generate_delegate_trait; mod generate_deref; mod generate_derive; @@ -162,62 +164,60 @@ mod handlers { mod generate_is_empty_from_len; mod generate_mut_trait_impl; mod generate_new; - mod generate_delegate_methods; mod generate_trait_from_impl; - mod add_return_type; mod inline_call; mod inline_const_as_literal; mod inline_local_variable; mod inline_macro; mod inline_type_alias; + mod into_to_qualified_from; + mod introduce_named_generic; mod introduce_named_lifetime; mod invert_if; mod merge_imports; mod merge_match_arms; + mod merge_nested_if; mod move_bounds; mod move_const_to_impl; + mod move_from_mod_rs; mod move_guard; mod move_module_to_file; mod move_to_mod_rs; - mod move_from_mod_rs; mod number_representation; mod promote_local_to_const; mod pull_assignment_up; - mod qualify_path; mod qualify_method_call; + mod qualify_path; mod raw_string; mod remove_dbg; mod remove_mut; + mod remove_parentheses; mod remove_unused_imports; mod remove_unused_param; - mod remove_parentheses; mod reorder_fields; mod reorder_impl_items; - mod replace_try_expr_with_match; + mod replace_arith_op; mod replace_derive_with_manual_impl; mod replace_if_let_with_match; mod replace_is_method_with_if_let_method; - mod replace_method_eager_lazy; - mod replace_arith_op; - mod introduce_named_generic; mod replace_let_with_if_let; + mod replace_method_eager_lazy; mod replace_named_generic_with_impl; mod replace_qualified_name_with_use; mod replace_string_with_char; + mod replace_try_expr_with_match; mod replace_turbofish_with_explicit_type; - mod split_import; - mod unmerge_match_arm; - mod unwrap_tuple; mod sort_items; + mod split_import; mod toggle_ignore; + mod unmerge_match_arm; mod unmerge_use; mod unnecessary_async; + mod unqualify_method_call; mod unwrap_block; mod unwrap_result_return_type; - mod unqualify_method_call; + mod unwrap_tuple; mod wrap_return_type_in_result; - mod into_to_qualified_from; - mod merge_nested_if; pub(crate) fn all() -> &'static [Handler] { &[ diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs index 2420945f75607..eeb3d80d07bd1 100644 --- a/crates/ide-assists/src/utils.rs +++ b/crates/ide-assists/src/utils.rs @@ -23,8 +23,8 @@ use syntax::{ use crate::assist_context::{AssistContext, SourceChangeBuilder}; -pub(crate) mod suggest_name; mod gen_trait_fn_body; +pub(crate) mod suggest_name; pub(crate) fn unwrap_trivial_block(block_expr: ast::BlockExpr) -> ast::Expr { extract_trivial_expression(&block_expr) diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index 4d3d0b4d1a6f5..ba3c0cf3fd60e 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -2,8 +2,10 @@ pub(crate) mod attribute; pub(crate) mod dot; +pub(crate) mod env_vars; pub(crate) mod expr; pub(crate) mod extern_abi; +pub(crate) mod extern_crate; pub(crate) mod field; pub(crate) mod flyimport; pub(crate) mod fn_param; @@ -19,8 +21,6 @@ pub(crate) mod snippet; pub(crate) mod r#type; pub(crate) mod use_; pub(crate) mod vis; -pub(crate) mod env_vars; -pub(crate) mod extern_crate; use std::iter; diff --git a/crates/ide-completion/src/completions/attribute.rs b/crates/ide-completion/src/completions/attribute.rs index 8f7c3b5070bfd..a7a6cdebd361e 100644 --- a/crates/ide-completion/src/completions/attribute.rs +++ b/crates/ide-completion/src/completions/attribute.rs @@ -25,8 +25,8 @@ use crate::{ mod cfg; mod derive; mod lint; -mod repr; mod macro_use; +mod repr; pub(crate) use self::derive::complete_derive_path; diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs index 6a98e109f6dff..d26b6f431b5b4 100644 --- a/crates/ide-completion/src/lib.rs +++ b/crates/ide-completion/src/lib.rs @@ -8,9 +8,9 @@ mod context; mod item; mod render; +mod snippet; #[cfg(test)] mod tests; -mod snippet; use ide_db::{ base_db::FilePosition, diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index 6fd988bfc0fc6..ad26280ae748f 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -1,14 +1,14 @@ //! `render` module provides utilities for rendering completion suggestions //! into code pieces that will be presented to user. -pub(crate) mod macro_; -pub(crate) mod function; pub(crate) mod const_; +pub(crate) mod function; +pub(crate) mod literal; +pub(crate) mod macro_; pub(crate) mod pattern; pub(crate) mod type_alias; -pub(crate) mod variant; pub(crate) mod union_literal; -pub(crate) mod literal; +pub(crate) mod variant; use hir::{AsAssocItem, HasAttrs, HirDisplay, ModuleDef, ScopeDef, Type}; use ide_db::{ diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs index f13754e2ded05..c421be51a0d07 100644 --- a/crates/ide-completion/src/tests.rs +++ b/crates/ide-completion/src/tests.rs @@ -12,8 +12,8 @@ mod attribute; mod expression; mod flyimport; mod fn_param; -mod item_list; mod item; +mod item_list; mod pattern; mod predicate; mod proc_macros; diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index 1cc1e36329909..2881748dd477e 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -9,6 +9,7 @@ mod apply_change; pub mod active_parameter; pub mod assists; pub mod defs; +pub mod documentation; pub mod famous_defs; pub mod helpers; pub mod items_locator; @@ -22,7 +23,6 @@ pub mod symbol_index; pub mod traits; pub mod ty_filter; pub mod use_trivial_constructor; -pub mod documentation; pub mod imports { pub mod import_assets; @@ -35,10 +35,10 @@ pub mod generated { } pub mod syntax_helpers { - pub mod node_ext; - pub mod insert_whitespace_into_node; pub mod format_string; pub mod format_string_exprs; + pub mod insert_whitespace_into_node; + pub mod node_ext; pub use parser::LexedStr; } @@ -414,6 +414,6 @@ impl SnippetCap { #[cfg(test)] mod tests { - mod sourcegen_lints; mod line_index; + mod sourcegen_lints; } diff --git a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index 5e950ecb0d102..e75d89737281c 100644 --- a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -3,10 +3,10 @@ use hir::InFile; use ide_db::base_db::FileRange; use syntax::{ ast::{self, HasArgList}, - AstNode, SyntaxNodePtr, + AstNode, AstPtr, }; -use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{adjusted_display_range_new, Diagnostic, DiagnosticCode, DiagnosticsContext}; // Diagnostic: mismatched-tuple-struct-pat-arg-count // @@ -24,7 +24,7 @@ pub(crate) fn mismatched_tuple_struct_pat_arg_count( Diagnostic::new( DiagnosticCode::RustcHardError("E0023"), message, - invalid_args_range(ctx, d.expr_or_pat.map(Into::into), d.expected, d.found), + invalid_args_range(ctx, d.expr_or_pat, d.expected, d.found), ) } @@ -40,17 +40,17 @@ pub(crate) fn mismatched_arg_count( Diagnostic::new( DiagnosticCode::RustcHardError("E0107"), message, - invalid_args_range(ctx, d.call_expr.map(Into::into), d.expected, d.found), + invalid_args_range(ctx, d.call_expr.map(AstPtr::wrap_left), d.expected, d.found), ) } fn invalid_args_range( ctx: &DiagnosticsContext<'_>, - source: InFile, + source: InFile>>, expected: usize, found: usize, ) -> FileRange { - adjusted_display_range::>(ctx, source, &|expr| { + adjusted_display_range_new(ctx, source, &|expr| { let (text_range, r_paren_token, expected_arg) = match expr { Either::Left(ast::Expr::CallExpr(call)) => { let arg_list = call.arg_list()?; @@ -68,7 +68,7 @@ fn invalid_args_range( arg_list.args().nth(expected).map(|it| it.syntax().text_range()), ) } - Either::Right(pat) => { + Either::Right(ast::Pat::TupleStructPat(pat)) => { let r_paren = pat.r_paren_token()?; let l_paren = pat.l_paren_token()?; ( diff --git a/crates/ide-diagnostics/src/handlers/no_such_field.rs b/crates/ide-diagnostics/src/handlers/no_such_field.rs index 5a20246cdd196..8d77e566edc9c 100644 --- a/crates/ide-diagnostics/src/handlers/no_such_field.rs +++ b/crates/ide-diagnostics/src/handlers/no_such_field.rs @@ -128,6 +128,36 @@ fn missing_record_expr_field_fixes( mod tests { use crate::tests::{check_diagnostics, check_fix, check_no_fix}; + #[test] + fn dont_work_for_field_with_disabled_cfg() { + check_diagnostics( + r#" +struct Test { + #[cfg(feature = "hello")] + test: u32, + other: u32 +} + +fn main() { + let a = Test { + #[cfg(feature = "hello")] + test: 1, + other: 1 + }; + + let Test { + #[cfg(feature = "hello")] + test, + mut other, + .. + } = a; + + other += 1; +} +"#, + ); + } + #[test] fn no_such_field_diagnostics() { check_diagnostics( diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 7743b060c8626..f35fc5b533a66 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -44,30 +44,30 @@ mod handlers { pub(crate) mod private_assoc_item; pub(crate) mod private_field; pub(crate) mod replace_filter_map_next_with_find_map; - pub(crate) mod trait_impl_orphan; pub(crate) mod trait_impl_incorrect_safety; pub(crate) mod trait_impl_missing_assoc_item; + pub(crate) mod trait_impl_orphan; pub(crate) mod trait_impl_redundant_assoc_item; - pub(crate) mod typed_hole; pub(crate) mod type_mismatch; + pub(crate) mod typed_hole; + pub(crate) mod undeclared_label; pub(crate) mod unimplemented_builtin_macro; + pub(crate) mod unreachable_label; pub(crate) mod unresolved_assoc_item; pub(crate) mod unresolved_extern_crate; pub(crate) mod unresolved_field; - pub(crate) mod unresolved_method; pub(crate) mod unresolved_import; pub(crate) mod unresolved_macro_call; + pub(crate) mod unresolved_method; pub(crate) mod unresolved_module; pub(crate) mod unresolved_proc_macro; - pub(crate) mod undeclared_label; - pub(crate) mod unreachable_label; pub(crate) mod unused_variables; // The handlers below are unusual, the implement the diagnostics as well. pub(crate) mod field_shorthand; - pub(crate) mod useless_braces; - pub(crate) mod unlinked_file; pub(crate) mod json_is_not_rust; + pub(crate) mod unlinked_file; + pub(crate) mod useless_braces; } #[cfg(test)] diff --git a/crates/ide-ssr/src/lib.rs b/crates/ide-ssr/src/lib.rs index d756e7a63eb9b..b5bf510aeed48 100644 --- a/crates/ide-ssr/src/lib.rs +++ b/crates/ide-ssr/src/lib.rs @@ -69,11 +69,11 @@ // // foo($a, $b) ==>> ($a).foo($b) // ``` +mod fragments; mod from_comment; mod matching; mod nester; mod parsing; -mod fragments; mod replacing; mod resolving; mod search; diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 79fff15f050b8..46e5901852ae5 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -25,13 +25,13 @@ mod bind_pat; mod binding_mode; mod chaining; mod closing_brace; -mod closure_ret; mod closure_captures; +mod closure_ret; mod discriminant; mod fn_lifetime_fn; +mod implicit_drop; mod implicit_static; mod param_name; -mod implicit_drop; mod range_exclusive; #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 81682e07e0952..e9f42d478554f 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -21,24 +21,25 @@ macro_rules! eprintln { mod fixture; mod markup; -mod prime_caches; mod navigation_target; +mod prime_caches; mod annotations; mod call_hierarchy; -mod signature_help; mod doc_links; -mod highlight_related; mod expand_macro; mod extend_selection; +mod fetch_crates; mod file_structure; mod folding_ranges; mod goto_declaration; mod goto_definition; mod goto_implementation; mod goto_type_definition; +mod highlight_related; mod hover; mod inlay_hints; +mod interpret_function; mod join_lines; mod markdown_remove; mod matching_brace; @@ -48,6 +49,8 @@ mod parent_module; mod references; mod rename; mod runnables; +mod shuffle_crate_graph; +mod signature_help; mod ssr; mod static_index; mod status; @@ -56,12 +59,9 @@ mod syntax_tree; mod typing; mod view_crate_graph; mod view_hir; -mod view_mir; -mod interpret_function; mod view_item_tree; -mod shuffle_crate_graph; -mod fetch_crates; mod view_memory_layout; +mod view_mir; use std::ffi::OsStr; @@ -79,7 +79,7 @@ use syntax::SourceFile; use triomphe::Arc; use view_memory_layout::{view_memory_layout, RecursiveMemoryLayout}; -use crate::navigation_target::{ToNav, TryToNav}; +use crate::navigation_target::ToNav; pub use crate::{ annotations::{Annotation, AnnotationConfig, AnnotationKind, AnnotationLocation}, @@ -104,7 +104,7 @@ pub use crate::{ SymbolInformationKind, }, move_item::Direction, - navigation_target::{NavigationTarget, UpmappingResult}, + navigation_target::{NavigationTarget, TryToNav, UpmappingResult}, prime_caches::ParallelPrimeCachesProgress, references::ReferenceSearchResult, rename::RenameError, diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index c8d7b7e25bb71..bfd91feeb3900 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -76,7 +76,7 @@ pub(crate) trait ToNav { fn to_nav(&self, db: &RootDatabase) -> UpmappingResult; } -pub(crate) trait TryToNav { +pub trait TryToNav { fn try_to_nav(&self, db: &RootDatabase) -> Option>; } diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 3607c486d7d39..8c6f5e2e9cb50 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -3,11 +3,11 @@ pub(crate) mod tags; mod highlights; mod injector; -mod highlight; +mod escape; mod format; -mod macro_; +mod highlight; mod inject; -mod escape; +mod macro_; mod html; #[cfg(test)] diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index f968a89a441f2..62fdce36892f2 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs @@ -8,11 +8,11 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod parser; mod expander; +mod parser; mod syntax_bridge; -mod tt_iter; mod to_parser_input; +mod tt_iter; #[cfg(test)] mod benchmark; diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index 8b57d7eeaf588..4513732902db7 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs @@ -234,7 +234,7 @@ where let mut stack = NonEmptyVec::new(entry); while let Some((token, abs_range)) = conv.bump() { - let tt::Subtree { delimiter, token_trees: result } = stack.last_mut(); + let tt::Subtree { delimiter, token_trees } = stack.last_mut(); let tt = match token.as_leaf() { Some(leaf) => tt::TokenTree::Leaf(leaf.clone()), @@ -243,7 +243,7 @@ where COMMENT => { let span = conv.span_for(abs_range); if let Some(tokens) = conv.convert_doc_comment(&token, span) { - result.extend(tokens); + token_trees.extend(tokens); } continue; } @@ -317,7 +317,7 @@ where span: conv .span_for(TextRange::at(abs_range.start(), TextSize::of('\''))), }); - result.push(apostrophe.into()); + token_trees.push(apostrophe.into()); let ident = tt::Leaf::from(tt::Ident { text: SmolStr::new(&token.to_text(conv)[1..]), @@ -326,7 +326,7 @@ where abs_range.end(), )), }); - result.push(ident.into()); + token_trees.push(ident.into()); continue; } _ => continue, @@ -337,7 +337,7 @@ where }, }; - result.push(tt); + token_trees.push(tt); } // If we get here, we've consumed all input tokens. diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs index 19da297b58ccc..53fda3ae4fd26 100644 --- a/crates/parser/src/grammar.rs +++ b/crates/parser/src/grammar.rs @@ -30,12 +30,12 @@ mod attributes; mod expressions; +mod generic_args; +mod generic_params; mod items; mod params; mod paths; mod patterns; -mod generic_args; -mod generic_params; mod types; use crate::{ diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs index caf2a005a7d8b..243a219525a8a 100644 --- a/crates/parser/src/grammar/items.rs +++ b/crates/parser/src/grammar/items.rs @@ -1,5 +1,5 @@ -mod consts; mod adt; +mod consts; mod traits; mod use_item; diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index ed0aec3cab32a..3ca285e787e81 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -26,15 +26,15 @@ extern crate ra_ap_rustc_lexer as rustc_lexer; #[cfg(feature = "in-rust-tree")] extern crate rustc_lexer; -mod lexed_str; -mod token_set; -mod syntax_kind; mod event; -mod parser; mod grammar; mod input; +mod lexed_str; mod output; +mod parser; mod shortcuts; +mod syntax_kind; +mod token_set; #[cfg(test)] mod tests; diff --git a/crates/parser/src/tests.rs b/crates/parser/src/tests.rs index 2fec765bd7871..c65219b28dce6 100644 --- a/crates/parser/src/tests.rs +++ b/crates/parser/src/tests.rs @@ -1,6 +1,6 @@ +mod prefix_entries; mod sourcegen_inline_tests; mod top_entries; -mod prefix_entries; use std::{ fmt::Write, diff --git a/crates/proc-macro-srv/proc-macro-test/build.rs b/crates/proc-macro-srv/proc-macro-test/build.rs index e6903fb8d4aed..c9b605a808765 100644 --- a/crates/proc-macro-srv/proc-macro-test/build.rs +++ b/crates/proc-macro-srv/proc-macro-test/build.rs @@ -100,7 +100,8 @@ fn main() { .current_dir(&staging_dir) .args(["pkgid", name]) .output() - .unwrap().stdout, + .unwrap() + .stdout, ) .unwrap(); let pkgid = pkgid.trim(); @@ -109,7 +110,8 @@ fn main() { 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.package_id.repr.starts_with(&repr) || artifact.package_id.repr == pkgid { + if artifact.package_id.repr.starts_with(&repr) || artifact.package_id.repr == pkgid + { artifact_path = Some(PathBuf::from(&artifact.filenames[0])); } } diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs index 67b9f57a1636c..460a96c07f367 100644 --- a/crates/proc-macro-srv/src/lib.rs +++ b/crates/proc-macro-srv/src/lib.rs @@ -21,8 +21,8 @@ extern crate proc_macro; extern crate rustc_driver as _; mod dylib; -mod server; mod proc_macros; +mod server; use std::{ collections::{hash_map::Entry, HashMap}, diff --git a/crates/proc-macro-srv/src/server.rs b/crates/proc-macro-srv/src/server.rs index 1854322ddb5c3..ff8fd295d884a 100644 --- a/crates/proc-macro-srv/src/server.rs +++ b/crates/proc-macro-srv/src/server.rs @@ -13,9 +13,9 @@ use proc_macro::bridge; mod token_stream; pub use token_stream::TokenStream; -pub mod token_id; pub mod rust_analyzer_span; mod symbol; +pub mod token_id; pub use symbol::*; use tt::Spacing; diff --git a/crates/proc-macro-srv/src/server/token_id.rs b/crates/proc-macro-srv/src/server/token_id.rs index 12526ad4f3ae6..c83e09af0d6e1 100644 --- a/crates/proc-macro-srv/src/server/token_id.rs +++ b/crates/proc-macro-srv/src/server/token_id.rs @@ -206,7 +206,7 @@ impl server::TokenStream for TokenIdServer { stream: if subtree.token_trees.is_empty() { None } else { - Some(subtree.token_trees.into_iter().collect()) + Some(TokenStream { token_trees: subtree.token_trees }) }, span: bridge::DelimSpan::from_single(subtree.delimiter.open), }), diff --git a/crates/profile/src/lib.rs b/crates/profile/src/lib.rs index fdd724e2aab45..d86aa0c414406 100644 --- a/crates/profile/src/lib.rs +++ b/crates/profile/src/lib.rs @@ -2,11 +2,11 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod stop_watch; -mod memory_usage; #[cfg(feature = "cpu_profiler")] mod google_cpu_profiler; mod hprof; +mod memory_usage; +mod stop_watch; mod tree; use std::cell::RefCell; diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs index 5f9b708289d16..5114c9c016ded 100644 --- a/crates/project-model/src/lib.rs +++ b/crates/project-model/src/lib.rs @@ -17,15 +17,15 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod manifest_path; +mod build_scripts; mod cargo_workspace; mod cfg_flag; +mod manifest_path; mod project_json; -mod sysroot; -mod workspace; mod rustc_cfg; -mod build_scripts; +mod sysroot; pub mod target_data_layout; +mod workspace; #[cfg(test)] mod tests; diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs index de00c4192b46a..00670f2cb4c8d 100644 --- a/crates/rust-analyzer/src/cli.rs +++ b/crates/rust-analyzer/src/cli.rs @@ -1,16 +1,16 @@ //! Various batch processing tasks, intended primarily for debugging. -pub mod flags; -mod parse; -mod symbols; -mod highlight; mod analysis_stats; mod diagnostics; -mod ssr; +pub mod flags; +mod highlight; mod lsif; -mod scip; +mod parse; mod run_tests; mod rustc_tests; +mod scip; +mod ssr; +mod symbols; mod progress_report; diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index f3c2df24d951b..1a55dcebc1350 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -1319,6 +1319,9 @@ pub(crate) fn handle_code_lens_resolve( snap: GlobalStateSnapshot, code_lens: CodeLens, ) -> anyhow::Result { + if code_lens.data.is_none() { + return Ok(code_lens); + } let Some(annotation) = from_proto::annotation(&snap, code_lens.clone())? else { return Ok(code_lens); }; @@ -1327,13 +1330,14 @@ pub(crate) fn handle_code_lens_resolve( let mut acc = Vec::new(); to_proto::code_lens(&mut acc, &snap, annotation)?; - let res = match acc.pop() { + let mut res = match acc.pop() { Some(it) if acc.is_empty() => it, _ => { never!(); code_lens } }; + res.data = None; Ok(res) } diff --git a/crates/rust-analyzer/src/lsp.rs b/crates/rust-analyzer/src/lsp.rs index ac7e1a95e622f..9e0d42faed43f 100644 --- a/crates/rust-analyzer/src/lsp.rs +++ b/crates/rust-analyzer/src/lsp.rs @@ -2,11 +2,11 @@ use core::fmt; -pub(crate) mod utils; -pub(crate) mod semantic_tokens; pub mod ext; pub(crate) mod from_proto; +pub(crate) mod semantic_tokens; pub(crate) mod to_proto; +pub(crate) mod utils; #[derive(Debug)] pub(crate) struct LspError { diff --git a/crates/rust-analyzer/tests/slow-tests/tidy.rs b/crates/rust-analyzer/tests/slow-tests/tidy.rs index db192cf8fe53a..d3146ab7671cc 100644 --- a/crates/rust-analyzer/tests/slow-tests/tidy.rs +++ b/crates/rust-analyzer/tests/slow-tests/tidy.rs @@ -154,6 +154,7 @@ fn check_licenses() { Apache-2.0 Apache-2.0 OR BSL-1.0 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-3-Clause diff --git a/crates/span/src/lib.rs b/crates/span/src/lib.rs index f6569050b4a00..6796dc41886f5 100644 --- a/crates/span/src/lib.rs +++ b/crates/span/src/lib.rs @@ -1,7 +1,4 @@ //! File and span related types. -// FIXME: This should be moved into its own crate to get rid of the dependency inversion, base-db -// has business depending on tt, tt should depend on a span crate only (which unforunately will have -// to depend on salsa) use std::fmt::{self, Write}; use salsa::InternId; diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index cd5285295a2f4..07b7827228182 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs @@ -6,13 +6,13 @@ use std::io as sio; use std::process::Command; use std::{cmp::Ordering, ops, time::Instant}; +pub mod anymap; mod macros; -pub mod process; -pub mod panic_context; pub mod non_empty_vec; +pub mod panic_context; +pub mod process; pub mod rand; pub mod thread; -pub mod anymap; pub use always_assert::{always, never}; pub use itertools; diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index cc90d2dd1d55b..e9ab7a4320b0c 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs @@ -1,15 +1,15 @@ //! Abstract Syntax Tree, layered on top of untyped `SyntaxNode`s -mod generated; -mod traits; -mod token_ext; -mod node_ext; -mod expr_ext; -mod operators; pub mod edit; pub mod edit_in_place; +mod expr_ext; +mod generated; pub mod make; +mod node_ext; +mod operators; pub mod prec; +mod token_ext; +mod traits; use std::marker::PhantomData; diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index 21ed1310f56b7..62a0261d7a459 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -32,22 +32,22 @@ macro_rules! eprintln { ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; } -mod syntax_node; -mod syntax_error; mod parsing; -mod validation; mod ptr; -mod token_text; +mod syntax_error; +mod syntax_node; #[cfg(test)] mod tests; +mod token_text; +mod validation; pub mod algo; pub mod ast; #[doc(hidden)] pub mod fuzz; -pub mod utils; -pub mod ted; pub mod hacks; +pub mod ted; +pub mod utils; use std::marker::PhantomData; diff --git a/editors/code/language-configuration.json b/editors/code/language-configuration.json index 1c348b63f1a23..a2af8b51a908b 100644 --- a/editors/code/language-configuration.json +++ b/editors/code/language-configuration.json @@ -6,7 +6,9 @@ "brackets": [ ["{", "}"], ["[", "]"], - ["(", ")"] + ["(", ")"], + ["#[", "]"], + ["#![", "]"] ], "colorizedBracketPairs": [ ["{", "}"], @@ -17,6 +19,8 @@ { "open": "{", "close": "}" }, { "open": "[", "close": "]" }, { "open": "(", "close": ")" }, + { "open": "#[", "close": "]" }, + { "open": "#![", "close": "]" }, { "open": "\"", "close": "\"", "notIn": ["string"] }, { "open": "/*", "close": " */" }, { "open": "`", "close": "`", "notIn": ["string"] } diff --git a/lib/lsp-server/src/lib.rs b/lib/lsp-server/src/lib.rs index f717f8e0d4ba6..e476f8c2d1345 100644 --- a/lib/lsp-server/src/lib.rs +++ b/lib/lsp-server/src/lib.rs @@ -6,11 +6,11 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod msg; -mod stdio; mod error; -mod socket; +mod msg; mod req_queue; +mod socket; +mod stdio; use std::{ io, diff --git a/rustfmt.toml b/rustfmt.toml index 71007de81b9f6..20bf59547b86a 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,2 +1,2 @@ -reorder_modules = false +reorder_modules = true use_small_heuristics = "Max" diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 49f8ae79baf0e..2d40ceb737dff 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -12,11 +12,11 @@ mod flags; -mod install; -mod release; mod dist; -mod publish; +mod install; mod metrics; +mod publish; +mod release; use anyhow::bail; use std::{ From e7e81cf0008c1f47dfc0228fd57f054b0b5581ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sun, 28 Jan 2024 18:14:06 +0200 Subject: [PATCH 093/246] Silence triagebot on subtree syncs --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index c46f9c9003079..e680e064d0d78 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -549,6 +549,7 @@ this change to [rust-lang/rust-analyzer] instead. [rust-lang/rust-analyzer]: https://github.com/rust-lang/rust-analyzer """ cc = ["@rust-lang/rust-analyzer"] +exclude_titles = ["subtree update", "Subtree update"] [mentions."src/tools/rustfmt"] cc = ["@rust-lang/rustfmt"] From 309d6154b1e94921cd3d4e214889bf43cdc3f2be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sun, 28 Jan 2024 18:21:55 +0200 Subject: [PATCH 094/246] Add rustc_apfloat license exception for RA --- src/tools/tidy/src/deps.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index b06c072a2b0fd..d141de3c2c5ab 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -132,6 +132,7 @@ const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[ ("dissimilar", "Apache-2.0"), ("notify", "CC0-1.0"), ("pulldown-cmark-to-cmark", "Apache-2.0"), + ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"), ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0 ("scip", "Apache-2.0"), ("snap", "BSD-3-Clause"), From 7159d88d476d656808108d5b60acce1c8ba1ef2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sun, 28 Jan 2024 18:23:27 +0200 Subject: [PATCH 095/246] Revert "Silence triagebot on subtree syncs" This reverts commit e7e81cf0008c1f47dfc0228fd57f054b0b5581ec. --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index e680e064d0d78..c46f9c9003079 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -549,7 +549,6 @@ this change to [rust-lang/rust-analyzer] instead. [rust-lang/rust-analyzer]: https://github.com/rust-lang/rust-analyzer """ cc = ["@rust-lang/rust-analyzer"] -exclude_titles = ["subtree update", "Subtree update"] [mentions."src/tools/rustfmt"] cc = ["@rust-lang/rustfmt"] From 6aec11afbcf3acd195818948a3e7a8d5b337b78a Mon Sep 17 00:00:00 2001 From: Ryan Lowe Date: Sun, 28 Jan 2024 13:27:17 -0500 Subject: [PATCH 096/246] Document From<&CStr> for CString --- 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 4a4a3abd47f39..9419b0cfb24fa 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -1024,6 +1024,8 @@ impl ToOwned for CStr { #[stable(feature = "cstring_asref", since = "1.7.0")] impl From<&CStr> for CString { + /// Converts a &[CStr] into a [`CString`] + /// by copying the contents into a new allocation. fn from(s: &CStr) -> CString { s.to_owned() } From 699b59c01d1b3e67b5a29646705d9824e03ff1ad Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sun, 28 Jan 2024 22:44:32 -0800 Subject: [PATCH 097/246] update terminator.rs --- tests/mir-opt/dataflow-const-prop/terminator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mir-opt/dataflow-const-prop/terminator.rs b/tests/mir-opt/dataflow-const-prop/terminator.rs index 37bf3b3347024..4472861f132db 100644 --- a/tests/mir-opt/dataflow-const-prop/terminator.rs +++ b/tests/mir-opt/dataflow-const-prop/terminator.rs @@ -9,6 +9,6 @@ fn foo(n: i32) {} fn main() { let a = 1; // Checks that we propagate into terminators. - // CHECK: {{_.*}} = foo(const 2_i32) -> [return: {{bb.*}}, unwind continue]; + // CHECK: {{_.*}} = foo(const 2_i32) -> [return: {{bb.*}}, unwind foo(a + 1); } From 618110256752ce2c3b5873b51f458609cca901bc Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Mon, 29 Jan 2024 18:42:41 +0800 Subject: [PATCH 098/246] fix: use Semantics to judge whether a func is marked as #[test] --- crates/ide-db/src/search.rs | 53 ++++++++++++------------------------- 1 file changed, 17 insertions(+), 36 deletions(-) diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index 5aa4186f8227d..7be3ddd7e3e7f 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -15,10 +15,7 @@ use memchr::memmem::Finder; use nohash_hasher::IntMap; use once_cell::unsync::Lazy; use parser::SyntaxKind; -use syntax::{ - ast::{self, HasAttrs as _}, - match_ast, AstNode, AstToken, SyntaxElement, TextRange, TextSize, -}; +use syntax::{ast, match_ast, AstNode, AstToken, SyntaxElement, TextRange, TextSize}; use triomphe::Arc; use crate::{ @@ -747,7 +744,7 @@ impl<'a> FindUsages<'a> { let reference = FileReference { range, name: FileReferenceNode::NameRef(name_ref.clone()), - category: ReferenceCategory::new(&def, name_ref), + category: ReferenceCategory::new(self.sema, &def, name_ref), }; sink(file_id, reference) } @@ -763,7 +760,7 @@ impl<'a> FindUsages<'a> { let reference = FileReference { range, name: FileReferenceNode::NameRef(name_ref.clone()), - category: ReferenceCategory::new(&def, name_ref), + category: ReferenceCategory::new(self.sema, &def, name_ref), }; sink(file_id, reference) } @@ -773,7 +770,7 @@ impl<'a> FindUsages<'a> { let reference = FileReference { range, name: FileReferenceNode::NameRef(name_ref.clone()), - category: ReferenceCategory::new(&def, name_ref), + category: ReferenceCategory::new(self.sema, &def, name_ref), }; sink(file_id, reference) } else { @@ -787,10 +784,10 @@ impl<'a> FindUsages<'a> { let local = Definition::Local(local); let access = match self.def { Definition::Field(_) if field == self.def => { - ReferenceCategory::new(&field, name_ref) + ReferenceCategory::new(self.sema, &field, name_ref) } Definition::Local(_) if local == self.def => { - ReferenceCategory::new(&local, name_ref) + ReferenceCategory::new(self.sema, &local, name_ref) } _ => return false, }; @@ -875,8 +872,12 @@ fn def_to_ty(sema: &Semantics<'_, RootDatabase>, def: &Definition) -> Option Option { - if is_name_ref_in_test(r) { + fn new( + sema: &Semantics<'_, RootDatabase>, + def: &Definition, + r: &ast::NameRef, + ) -> Option { + if is_name_ref_in_test(sema, r) { return Some(ReferenceCategory::Test); } @@ -919,29 +920,9 @@ fn is_name_ref_in_import(name_ref: &ast::NameRef) -> bool { .map_or(false, |it| it.kind() == SyntaxKind::USE_TREE) } -fn is_name_ref_in_test(name_ref: &ast::NameRef) -> bool { - let mode = name_ref.syntax().ancestors().find_map(|node| { - match_ast! { - match node { - ast::Fn(f) => { - let attrs = f.attrs(); - let mut is_test = false; - for attr in attrs { - if attr.to_string() == "#[test]" { - is_test = true; - break; - } - } - if is_test { - Some(ReferenceCategory::Test) - } - else { - None - } - }, - _ => None - } - } - }); - mode.is_some() +fn is_name_ref_in_test(sema: &Semantics<'_, RootDatabase>, name_ref: &ast::NameRef) -> bool { + name_ref.syntax().ancestors().any(|node| match ast::Fn::cast(node) { + Some(it) => sema.to_def(&it).map_or(false, |func| func.is_test(sema.db)), + None => false, + }) } From 2b71acac4f07565907cc19737b92b63750911c3f Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Mon, 29 Jan 2024 18:47:58 +0800 Subject: [PATCH 099/246] test: add full path ref exclude test case --- crates/ide/src/references.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 4b695612a699d..9a58e0b40635f 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -329,6 +329,27 @@ fn test() { FileId(0) 75..84 Test "#]], ); + + check( + r#" +fn test_func() {} + +fn func() { + test_func$0(); +} + +#[::core::prelude::v1::test] +fn test() { + test_func(); +} +"#, + expect![[r#" + test_func Function FileId(0) 0..17 3..12 + + FileId(0) 35..44 + FileId(0) 96..105 Test + "#]], + ); } #[test] From ad1e6298ed785ad0d327231725db501be00f14c5 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 29 Jan 2024 20:03:14 +0100 Subject: [PATCH 100/246] Make duplicate lang items fatal Prevents terminal spam. --- compiler/rustc_passes/src/lang_items.rs | 4 +++- tests/ui/traits/issue-102989.rs | 1 - tests/ui/traits/issue-102989.stderr | 20 +++----------------- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 6aeaa8945fb59..9a21397789d6c 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -149,7 +149,9 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { } }; - self.tcx.dcx().emit_err(DuplicateLangItem { + // When there's a duplicate lang item, something went very wrong and there's no value in recovering or doing anything. + // Give the user the one message to let them debug the mess they created and then wish them farewell. + self.tcx.dcx().emit_fatal(DuplicateLangItem { local_span: item_span, lang_item_name, crate_name, diff --git a/tests/ui/traits/issue-102989.rs b/tests/ui/traits/issue-102989.rs index f1ecee0a552a7..216cd78e56f9a 100644 --- a/tests/ui/traits/issue-102989.rs +++ b/tests/ui/traits/issue-102989.rs @@ -7,7 +7,6 @@ trait Sized { } //~ ERROR found duplicate lang item `sized` fn ref_Struct(self: &Struct, f: &u32) -> &u32 { //~^ ERROR `self` parameter is only allowed in associated functions //~| ERROR cannot find type `Struct` in this scope - //~| ERROR mismatched types let x = x << 1; //~^ ERROR cannot find value `x` in this scope } diff --git a/tests/ui/traits/issue-102989.stderr b/tests/ui/traits/issue-102989.stderr index 40e49df2b2d96..e17df556d8d21 100644 --- a/tests/ui/traits/issue-102989.stderr +++ b/tests/ui/traits/issue-102989.stderr @@ -13,7 +13,7 @@ LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { | ^^^^^^ not found in this scope error[E0425]: cannot find value `x` in this scope - --> $DIR/issue-102989.rs:11:13 + --> $DIR/issue-102989.rs:10:13 | LL | let x = x << 1; | ^ help: a local variable with a similar name exists: `f` @@ -28,21 +28,7 @@ LL | trait Sized { } = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib = note: second definition in the local crate (`issue_102989`) -error[E0308]: mismatched types - --> $DIR/issue-102989.rs:7:42 - | -LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { - | ---------- ^^^^ expected `&u32`, found `()` - | | - | implicitly returns `()` as its body has no tail or `return` expression - | -help: consider returning the local binding `f` - | -LL ~ let x = x << 1; -LL + f - | - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0152, E0308, E0412, E0425. +Some errors have detailed explanations: E0152, E0412, E0425. For more information about an error, try `rustc --explain E0152`. From a360ecd64be275a4ecf2693dbfa058c9b48aa5d6 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 29 Jan 2024 20:06:26 +0100 Subject: [PATCH 101/246] Delete now-useless test The test was using an internal feature which doesn't really matter, but more importantly, we're now fatally exiting after the duplicate lang item, so this tests nothing. --- tests/ui/traits/issue-102989.rs | 14 ------------ tests/ui/traits/issue-102989.stderr | 34 ----------------------------- 2 files changed, 48 deletions(-) delete mode 100644 tests/ui/traits/issue-102989.rs delete mode 100644 tests/ui/traits/issue-102989.stderr diff --git a/tests/ui/traits/issue-102989.rs b/tests/ui/traits/issue-102989.rs deleted file mode 100644 index 216cd78e56f9a..0000000000000 --- a/tests/ui/traits/issue-102989.rs +++ /dev/null @@ -1,14 +0,0 @@ -// normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib" - -#![feature(lang_items)] -#[lang="sized"] -trait Sized { } //~ ERROR found duplicate lang item `sized` - -fn ref_Struct(self: &Struct, f: &u32) -> &u32 { - //~^ ERROR `self` parameter is only allowed in associated functions - //~| ERROR cannot find type `Struct` in this scope - let x = x << 1; - //~^ ERROR cannot find value `x` in this scope -} - -fn main() {} diff --git a/tests/ui/traits/issue-102989.stderr b/tests/ui/traits/issue-102989.stderr deleted file mode 100644 index e17df556d8d21..0000000000000 --- a/tests/ui/traits/issue-102989.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: `self` parameter is only allowed in associated functions - --> $DIR/issue-102989.rs:7:15 - | -LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { - | ^^^^ not semantically valid as function parameter - | - = note: associated functions are those in `impl` or `trait` definitions - -error[E0412]: cannot find type `Struct` in this scope - --> $DIR/issue-102989.rs:7:22 - | -LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { - | ^^^^^^ not found in this scope - -error[E0425]: cannot find value `x` in this scope - --> $DIR/issue-102989.rs:10:13 - | -LL | let x = x << 1; - | ^ help: a local variable with a similar name exists: `f` - -error[E0152]: found duplicate lang item `sized` - --> $DIR/issue-102989.rs:5:1 - | -LL | trait Sized { } - | ^^^^^^^^^^^^^^^ - | - = note: the lang item is first defined in crate `core` (which `std` depends on) - = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib - = note: second definition in the local crate (`issue_102989`) - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0152, E0412, E0425. -For more information about an error, try `rustc --explain E0152`. From 44d8ecbfb85d1649a4267e33c847f79a125b99f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 29 Jan 2024 19:07:36 +0000 Subject: [PATCH 102/246] Only suggest removal of `as_*` and `to_` conversion methods on E0308 Instead of ``` error[E0308]: mismatched types --> tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.rs:9:5 | 4 | fn get_name() -> String { | ------ expected `String` because of return type ... 9 | your_name.trim() //~ ERROR E0308 | ^^^^^^^^^^^^^^^^ expected `String`, found `&str` | help: try removing the method call | 9 - your_name.trim() 9 + your_name ``` output ``` error[E0308]: mismatched types --> $DIR/only-suggest-removal-of-conversion-method-calls.rs:9:5 | LL | fn get_name() -> String { | ------ expected `String` because of return type ... LL | your_name.trim() | ^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()` | | | expected `String`, found `&str` ``` Fix #114329. --- .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 ++ ...gest-removal-of-conversion-method-calls.fixed | 16 ++++++++++++++++ ...suggest-removal-of-conversion-method-calls.rs | 16 ++++++++++++++++ ...est-removal-of-conversion-method-calls.stderr | 14 ++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.fixed create mode 100644 tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.rs create mode 100644 tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 95c1139e43e44..5395ffda1d134 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -261,6 +261,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.kind && let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr) && self.can_coerce(recv_ty, expected) + && let name = method.name.as_str() + && (name.starts_with("to_") || name.starts_with("as_") || name == "into") { let span = if let Some(recv_span) = recv_expr.span.find_ancestor_inside(expr.span) { expr.span.with_lo(recv_span.hi()) diff --git a/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.fixed b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.fixed new file mode 100644 index 0000000000000..570d91d949bfc --- /dev/null +++ b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.fixed @@ -0,0 +1,16 @@ +// run-rustfix +use std::io::stdin; + +fn get_name() -> String { + let mut your_name = String::new(); + stdin() + .read_line(&mut your_name) + .expect("Failed to read the line for some reason"); + your_name.trim().to_string() //~ ERROR E0308 +} + +fn main() { + println!("Hello, What is your name? "); + let your_name = get_name(); + println!("Hello, {}", your_name) +} diff --git a/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.rs b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.rs new file mode 100644 index 0000000000000..93e8c0af0323e --- /dev/null +++ b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.rs @@ -0,0 +1,16 @@ +// run-rustfix +use std::io::stdin; + +fn get_name() -> String { + let mut your_name = String::new(); + stdin() + .read_line(&mut your_name) + .expect("Failed to read the line for some reason"); + your_name.trim() //~ ERROR E0308 +} + +fn main() { + println!("Hello, What is your name? "); + let your_name = get_name(); + println!("Hello, {}", your_name) +} diff --git a/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr new file mode 100644 index 0000000000000..c721ceb11463f --- /dev/null +++ b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/only-suggest-removal-of-conversion-method-calls.rs:9:5 + | +LL | fn get_name() -> String { + | ------ expected `String` because of return type +... +LL | your_name.trim() + | ^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()` + | | + | expected `String`, found `&str` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 1f89e900738b30c15894e57d7bdb1c2dbc089976 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 29 Jan 2024 20:10:01 +0100 Subject: [PATCH 103/246] Add test for duplicate lang items --- tests/ui/lang-items/duplicate.rs | 10 ++++++++++ tests/ui/lang-items/duplicate.stderr | 13 +++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 tests/ui/lang-items/duplicate.rs create mode 100644 tests/ui/lang-items/duplicate.stderr diff --git a/tests/ui/lang-items/duplicate.rs b/tests/ui/lang-items/duplicate.rs new file mode 100644 index 0000000000000..f88d23544145a --- /dev/null +++ b/tests/ui/lang-items/duplicate.rs @@ -0,0 +1,10 @@ +// normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib" +#![feature(lang_items)] + +#[lang = "sized"] +trait Sized {} +//~^ ERROR: duplicate lang item + +#[lang = "tuple_trait"] +pub trait Tuple {} +// no error diff --git a/tests/ui/lang-items/duplicate.stderr b/tests/ui/lang-items/duplicate.stderr new file mode 100644 index 0000000000000..aaa8f5e605afa --- /dev/null +++ b/tests/ui/lang-items/duplicate.stderr @@ -0,0 +1,13 @@ +error[E0152]: found duplicate lang item `sized` + --> $DIR/duplicate.rs:5:1 + | +LL | trait Sized {} + | ^^^^^^^^^^^^^^ + | + = note: the lang item is first defined in crate `core` (which `std` depends on) + = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib + = note: second definition in the local crate (`duplicate`) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0152`. From 7bdf705dd72edb9febe527c580a476d5d5f2f992 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Mon, 29 Jan 2024 21:01:15 -0500 Subject: [PATCH 104/246] Avoid ICE when is_val_statically_known is not of a supported type --- compiler/rustc_codegen_llvm/src/context.rs | 1 + compiler/rustc_codegen_llvm/src/intrinsic.rs | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 6cb62280a595e..7dfcf1ab50e41 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -909,6 +909,7 @@ impl<'ll> CodegenCx<'ll, '_> { ifn!("llvm.is.constant.isize", fn(t_isize) -> i1); ifn!("llvm.is.constant.f32", fn(t_f32) -> i1); ifn!("llvm.is.constant.f64", fn(t_f64) -> i1); + ifn!("llvm.is.constant.ptr", fn(ptr) -> i1); ifn!("llvm.expect.i1", fn(i1, i1) -> i1); ifn!("llvm.eh.typeid.for", fn(ptr) -> t_i32); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index f1a6f7bd8e690..b4512af38e37b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -119,10 +119,18 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { sym::likely => { self.call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(true)]) } - sym::is_val_statically_known => self.call_intrinsic( - &format!("llvm.is.constant.{:?}", args[0].layout.immediate_llvm_type(self.cx)), - &[args[0].immediate()], - ), + sym::is_val_statically_known => { + let intrinsic_type = args[0].layout.immediate_llvm_type(self.cx); + match self.type_kind(intrinsic_type) { + TypeKind::Pointer | TypeKind::Integer | TypeKind::Float | TypeKind::Double => { + self.call_intrinsic( + &format!("llvm.is.constant.{:?}", intrinsic_type), + &[args[0].immediate()], + ) + } + _ => self.const_bool(false), + } + } sym::unlikely => self .call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]), kw::Try => { From f8d4b2a150eca2797feaf863618886ac8e9cc8db Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sun, 29 Oct 2023 23:08:49 +0000 Subject: [PATCH 105/246] Update stdarch submodule --- library/std/src/lib.rs | 5 +++++ library/stdarch | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 2e458562744bf..b5c32e18f87cc 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -365,6 +365,11 @@ #![feature(panic_unwind)] // tidy-alphabetical-end // +// Library features (std_detect): +// tidy-alphabetical-start +#![feature(stdarch_internal)] +// tidy-alphabetical-end +// // Only for re-exporting: // tidy-alphabetical-start #![feature(assert_matches)] diff --git a/library/stdarch b/library/stdarch index f4528dd6e85d9..5ef6eb42bdcfe 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit f4528dd6e85d97bb802240d7cd048b6e1bf72540 +Subproject commit 5ef6eb42bdcfef6891517a6e4c77a89c18722f18 From 9a39e41637ec102cad6e2a6282129b834c267f4a Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 31 Oct 2023 23:06:00 +0000 Subject: [PATCH 106/246] Update feature names for new stdarch --- library/core/src/lib.rs | 4 ---- library/std/src/lib.rs | 14 ++++++++------ library/std/tests/run-time-detect.rs | 16 ++++++++++------ .../miri/tests/pass/intrinsics-x86-aes-vaes.rs | 2 +- .../miri/tests/pass/intrinsics-x86-avx512.rs | 2 +- tests/ui/asm/aarch64/type-check-3.rs | 2 +- tests/ui/asm/aarch64/type-check-4.rs | 2 +- 7 files changed, 22 insertions(+), 20 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 2af242d4b5071..62da0cae785cd 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -429,10 +429,6 @@ pub mod primitive; deprecated_in_future )] #[allow(rustdoc::bare_urls)] -// FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is -// merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet. -#[allow(clashing_extern_declarations)] -#[unstable(feature = "stdsimd", issue = "48556")] mod core_arch; #[stable(feature = "simd_arch", since = "1.27.0")] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index b5c32e18f87cc..91dd7eaf4e777 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -385,7 +385,6 @@ #![feature(get_many_mut)] #![feature(lazy_cell)] #![feature(log_syntax)] -#![feature(stdsimd)] #![feature(test)] #![feature(trace_macros)] // tidy-alphabetical-end @@ -624,13 +623,16 @@ pub mod arch { #[stable(feature = "simd_aarch64", since = "1.60.0")] pub use std_detect::is_aarch64_feature_detected; + #[unstable(feature = "stdarch_arm_feature_detection", issue = "111190")] + pub use std_detect::is_arm_feature_detected; + #[unstable(feature = "is_riscv_feature_detected", issue = "111192")] + pub use std_detect::is_riscv_feature_detected; #[stable(feature = "simd_x86", since = "1.27.0")] pub use std_detect::is_x86_feature_detected; - #[unstable(feature = "stdsimd", issue = "48556")] - pub use std_detect::{ - is_arm_feature_detected, is_mips64_feature_detected, is_mips_feature_detected, - is_powerpc64_feature_detected, is_powerpc_feature_detected, is_riscv_feature_detected, - }; + #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] + pub use std_detect::{is_mips64_feature_detected, is_mips_feature_detected}; + #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] + pub use std_detect::{is_powerpc64_feature_detected, is_powerpc_feature_detected}; } // This was stabilized in the crate root so we have to keep it there. diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 9ce29a33df6e6..c9b9c54e3d49c 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -1,12 +1,16 @@ //! These tests just check that the macros are available in std. #![cfg_attr( - any( - all(target_arch = "arm", any(target_os = "linux", target_os = "android")), - all(target_arch = "powerpc", target_os = "linux"), - all(target_arch = "powerpc64", target_os = "linux"), - ), - feature(stdsimd) + all(target_arch = "arm", any(target_os = "linux", target_os = "android")), + feature(stdarch_arm_feature_detection) +)] +#![cfg_attr( + all(target_arch = "powerpc", target_os = "linux"), + feature(stdarch_powerpc_feature_detection) +)] +#![cfg_attr( + all(target_arch = "powerpc64", target_os = "linux"), + feature(stdarch_powerpc_feature_detection) )] #[test] diff --git a/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs b/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs index 55d1bacdf4578..7363c75361779 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs @@ -9,7 +9,7 @@ //@ignore-target-wasm32 //@compile-flags: -C target-feature=+aes,+vaes,+avx512f -#![feature(avx512_target_feature, stdsimd)] +#![feature(avx512_target_feature, stdarch_x86_avx512)] use core::mem::transmute; #[cfg(target_arch = "x86")] diff --git a/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs b/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs index 394412a235432..66bfcb20f1c99 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs @@ -10,7 +10,7 @@ //@compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bitalg,+avx512vpopcntdq #![feature(avx512_target_feature)] -#![feature(stdsimd)] +#![feature(stdarch_x86_avx512)] #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/tests/ui/asm/aarch64/type-check-3.rs b/tests/ui/asm/aarch64/type-check-3.rs index 623f6593d79ba..77524ba7aa5e4 100644 --- a/tests/ui/asm/aarch64/type-check-3.rs +++ b/tests/ui/asm/aarch64/type-check-3.rs @@ -1,7 +1,7 @@ // only-aarch64 // compile-flags: -C target-feature=+neon -#![feature(repr_simd, stdsimd, asm_const)] +#![feature(repr_simd, asm_const)] use std::arch::aarch64::float64x2_t; use std::arch::{asm, global_asm}; diff --git a/tests/ui/asm/aarch64/type-check-4.rs b/tests/ui/asm/aarch64/type-check-4.rs index bd23755c02316..5dec60a2138d9 100644 --- a/tests/ui/asm/aarch64/type-check-4.rs +++ b/tests/ui/asm/aarch64/type-check-4.rs @@ -1,7 +1,7 @@ // only-aarch64 // compile-flags: -C target-feature=+neon -#![feature(repr_simd, stdsimd, asm_const)] +#![feature(repr_simd, asm_const)] use std::arch::aarch64::float64x2_t; use std::arch::{asm, global_asm}; From a00ec2d93bdaad574e339b0306e7bd7d01e3bc44 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 2 Jan 2024 19:42:47 +0100 Subject: [PATCH 107/246] Update ahash dependency to 0.8.7 --- Cargo.lock | 12 ++--- compiler/rustc_codegen_cranelift/Cargo.lock | 60 ++++++++++++++++++++- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cab14a7a202b2..e201aed28fe41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,9 +37,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", @@ -6406,18 +6406,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.28" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d6f15f7ade05d2a4935e34a457b936c23dc70a05cc1d97133dc99e7a3fe0f0e" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.28" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbbad221e3f78500350ecbd7dfa4e63ef945c05f4c61cb7f4d3f84cd0bba649b" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 86bc7d0f067cb..b70a1234af398 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -4,13 +4,14 @@ version = 3 [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -293,6 +294,24 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "proc-macro2" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + [[package]] name = "regalloc2" version = "0.9.3" @@ -360,12 +379,29 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "syn" +version = "2.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "target-lexicon" version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "version_check" version = "0.9.4" @@ -536,3 +572,23 @@ name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] From bfe6421d0b4ccf0353990e16801043e2a8847cc7 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 4 Jan 2024 08:34:02 +0000 Subject: [PATCH 108/246] Update allowed depdendencies for cranelift --- src/tools/tidy/src/deps.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index b06c072a2b0fd..48406d81af532 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -458,13 +458,17 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "mach", "memchr", "object", + "proc-macro2", + "quote", "regalloc2", "region", "rustc-hash", "slice-group-by", "smallvec", "stable_deref_trait", + "syn", "target-lexicon", + "unicode-ident", "version_check", "wasmtime-jit-icache-coherence", "winapi", @@ -479,6 +483,8 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", + "zerocopy", + "zerocopy-derive", // tidy-alphabetical-end ]; From 31007f51edfd9faf9793046145cfc5986f788b19 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 8 Jan 2024 13:36:05 +0000 Subject: [PATCH 109/246] Add stdarch_wasm_atomic_wait feature in std --- library/std/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 91dd7eaf4e777..78ce7c74a6936 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -262,6 +262,7 @@ )] #![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))] #![cfg_attr(target_os = "xous", feature(slice_ptr_len))] +#![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] // // Language features: // tidy-alphabetical-start From ab8b66166775362dbeb25c8f8898f8760baaf123 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 30 Jan 2024 03:40:53 +0000 Subject: [PATCH 110/246] Disable conversions between portable_simd and stdarch on big-endian ARM stdarch no longer provide SIMD on big-endian ARM due to https://github.com/rust-lang/stdarch/issues/1484 --- library/portable-simd/crates/core_simd/src/vendor/arm.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/portable-simd/crates/core_simd/src/vendor/arm.rs b/library/portable-simd/crates/core_simd/src/vendor/arm.rs index ff3b69ccf9592..ee5c642137367 100644 --- a/library/portable-simd/crates/core_simd/src/vendor/arm.rs +++ b/library/portable-simd/crates/core_simd/src/vendor/arm.rs @@ -7,9 +7,12 @@ use core::arch::arm::*; #[cfg(target_arch = "aarch64")] use core::arch::aarch64::*; -#[cfg(any( - target_arch = "aarch64", - all(target_arch = "arm", target_feature = "v7"), +#[cfg(all( + any( + target_arch = "aarch64", + all(target_arch = "arm", target_feature = "v7"), + ), + target_endian = "little" ))] mod neon { use super::*; From 20c01672a8909408b53c704acc4bd71b1b0b279a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 30 Jan 2024 08:41:43 +0200 Subject: [PATCH 111/246] Bump scip --- Cargo.lock | 4 ++-- crates/rust-analyzer/Cargo.toml | 2 +- crates/rust-analyzer/src/cli/scip.rs | 8 +++++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7513abf17c8c4..f55e1c4536b3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1661,9 +1661,9 @@ dependencies = [ [[package]] name = "scip" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e84d21062a3ba08d58870c8c36b0c005b2b2261c6ad1bf7042585427c781883" +checksum = "e5dc1bd66649133af84ab62436ddd2856c2605182b02dec2cd197f684dfe15ef" dependencies = [ "protobuf", ] diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index db5cabaf76941..56d9d65ddc0a3 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -23,7 +23,7 @@ anyhow.workspace = true crossbeam-channel = "0.5.5" dissimilar.workspace = true itertools.workspace = true -scip = "0.3.1" +scip = "0.3.3" lsp-types = { version = "=0.95.0", features = ["proposed"] } parking_lot = "0.12.1" xflags = "0.3.0" diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs index c9cf40db3a4cb..81622a4617ab9 100644 --- a/crates/rust-analyzer/src/cli/scip.rs +++ b/crates/rust-analyzer/src/cli/scip.rs @@ -143,11 +143,14 @@ impl flags::Scip { .map(|hover| hover.markup.as_str()) .filter(|it| !it.is_empty()) .map(|it| vec![it.to_owned()]); + let position_encoding = + scip_types::PositionEncoding::UTF8CodeUnitOffsetFromLineStart.into(); let signature_documentation = token.signature.clone().map(|text| scip_types::Document { relative_path: relative_path.clone(), language: "rust".to_string(), text, + position_encoding, ..Default::default() }); let symbol_info = scip_types::SymbolInformation { @@ -181,13 +184,16 @@ impl flags::Scip { continue; } + let position_encoding = + scip_types::PositionEncoding::UTF8CodeUnitOffsetFromLineStart.into(); documents.push(scip_types::Document { relative_path, language: "rust".to_string(), occurrences, symbols, - special_fields: Default::default(), text: String::new(), + position_encoding, + special_fields: Default::default(), }); } From 5860763f1808ef7ba2628bf46c08e77c96804925 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 30 Jan 2024 09:51:28 +0100 Subject: [PATCH 112/246] Cleanup error variants in MIR code slightly --- crates/hir-expand/src/proc_macro.rs | 2 +- crates/hir-ty/src/db.rs | 2 +- crates/hir-ty/src/display.rs | 5 +- crates/hir-ty/src/layout.rs | 2 +- crates/hir-ty/src/layout/adt.rs | 2 +- crates/hir-ty/src/layout/target.rs | 44 ++- crates/hir-ty/src/mir/borrowck.rs | 2 +- crates/hir-ty/src/mir/eval.rs | 147 ++++----- crates/hir-ty/src/mir/eval/shim.rs | 284 +++++++++++------- crates/hir-ty/src/mir/eval/shim/simd.rs | 42 ++- crates/hir-ty/src/mir/lower.rs | 2 +- crates/hir-ty/src/utils.rs | 10 +- crates/hir/src/diagnostics.rs | 237 ++++++++++++++- crates/hir/src/lib.rs | 225 +------------- crates/ide/src/hover/tests.rs | 8 +- .../rust-analyzer/src/cli/analysis_stats.rs | 4 +- crates/test-utils/src/minicore.rs | 14 +- 17 files changed, 598 insertions(+), 434 deletions(-) diff --git a/crates/hir-expand/src/proc_macro.rs b/crates/hir-expand/src/proc_macro.rs index 25c78fade824f..70b47fc54b11c 100644 --- a/crates/hir-expand/src/proc_macro.rs +++ b/crates/hir-expand/src/proc_macro.rs @@ -1,4 +1,4 @@ -//! Proc Macro Expander stub +//! Proc Macro Expander stuff use core::fmt; use std::{panic::RefUnwindSafe, sync}; diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs index aa7ca48b18ba6..89fe8c2b824a1 100644 --- a/crates/hir-ty/src/db.rs +++ b/crates/hir-ty/src/db.rs @@ -118,7 +118,7 @@ pub trait HirDatabase: DefDatabase + Upcast { 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) -> Option>; + fn target_data_layout(&self, krate: CrateId) -> Result, Arc>; #[salsa::invoke(crate::method_resolution::lookup_impl_method_query)] fn lookup_impl_method( diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 96c7949e3d626..2327c8df1b44c 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -605,8 +605,11 @@ fn render_const_scalar( write!(f, "{}", f.db.union_data(u).name.display(f.db.upcast())) } hir_def::AdtId::EnumId(e) => { + let Ok(target_data_layout) = f.db.target_data_layout(trait_env.krate) else { + return f.write_str(""); + }; let Some((var_id, var_layout)) = - detect_variant_from_bytes(&layout, f.db, trait_env, b, e) + detect_variant_from_bytes(&layout, f.db, &target_data_layout, b, e) else { return f.write_str(""); }; diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index 2b84cb6b13d2c..310c4cc9ffeca 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -198,7 +198,7 @@ pub fn layout_of_ty_query( trait_env: Arc, ) -> Result, LayoutError> { let krate = trait_env.krate; - let Some(target) = db.target_data_layout(krate) else { + let Ok(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable); }; let cx = LayoutCx { target: &target }; diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs index 47930358a11d6..4cc7dffc24ebb 100644 --- a/crates/hir-ty/src/layout/adt.rs +++ b/crates/hir-ty/src/layout/adt.rs @@ -32,7 +32,7 @@ pub fn layout_of_adt_query( trait_env: Arc, ) -> Result, LayoutError> { let krate = trait_env.krate; - let Some(target) = db.target_data_layout(krate) else { + let Ok(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable); }; let cx = LayoutCx { target: &target }; diff --git a/crates/hir-ty/src/layout/target.rs b/crates/hir-ty/src/layout/target.rs index b2185a03ea2dd..b67bb6c8661dd 100644 --- a/crates/hir-ty/src/layout/target.rs +++ b/crates/hir-ty/src/layout/target.rs @@ -2,6 +2,7 @@ use base_db::CrateId; use hir_def::layout::TargetDataLayout; +use ra_ap_rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors}; use triomphe::Arc; use crate::db::HirDatabase; @@ -9,15 +10,40 @@ use crate::db::HirDatabase; pub fn target_data_layout_query( db: &dyn HirDatabase, krate: CrateId, -) -> Option> { +) -> Result, Arc> { let crate_graph = db.crate_graph(); - let target_layout = crate_graph[krate].target_layout.as_ref().ok()?; - let res = TargetDataLayout::parse_from_llvm_datalayout_string(target_layout); - if let Err(_e) = &res { - // FIXME: Print the error here once it implements debug/display - // also logging here is somewhat wrong, but unfortunately this is the earliest place we can - // parse that doesn't impose a dependency to the rust-abi crate for project-model - tracing::error!("Failed to parse target data layout for {krate:?}"); + let res = crate_graph[krate].target_layout.as_deref(); + match res { + Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it) { + Ok(it) => Ok(Arc::new(it)), + Err(e) => { + Err(match e { + TargetDataLayoutErrors::InvalidAddressSpace { addr_space, cause, err } => { + format!( + r#"invalid address space `{addr_space}` for `{cause}` in "data-layout": {err}"# + ) + } + TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => format!(r#"invalid {kind} `{bit}` for `{cause}` in "data-layout": {err}"#), + TargetDataLayoutErrors::MissingAlignment { cause } => format!(r#"missing alignment for `{cause}` in "data-layout""#), + TargetDataLayoutErrors::InvalidAlignment { cause, err } => format!( + r#"invalid alignment for `{cause}` in "data-layout": `{align}` is {err_kind}"#, + align = err.align(), + err_kind = match err { + AlignFromBytesError::NotPowerOfTwo(_) => "not a power of two", + AlignFromBytesError::TooLarge(_) => "too large", + } + ), + TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { + format!(r#"inconsistent target specification: "data-layout" claims architecture is {dl}-endian, while "target-endian" is `{target}`"#) + } + TargetDataLayoutErrors::InconsistentTargetPointerWidth { + pointer_size, + target, + } => format!(r#"inconsistent target specification: "data-layout" claims pointers are {pointer_size}-bit, while "target-pointer-width" is `{target}`"#), + TargetDataLayoutErrors::InvalidBitsSize { err } => err, + }.into()) + } + }, + Err(e) => Err(Arc::from(&**e)), } - res.ok().map(Arc::new) } diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs index f7d043fc4e6a8..2dd5fa78d0754 100644 --- a/crates/hir-ty/src/mir/borrowck.rs +++ b/crates/hir-ty/src/mir/borrowck.rs @@ -444,7 +444,7 @@ fn mutability_of_locals( } if destination.projection.lookup(&body.projection_store).is_empty() { if ever_init_map.get(destination.local).copied().unwrap_or_default() { - push_mut_span(destination.local, MirSpan::Unknown, &mut result); + push_mut_span(destination.local, terminator.span, &mut result); } else { ever_init_map.insert(destination.local, true); } diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 8143dc05c38d4..885360d05fe78 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -17,6 +17,7 @@ use hir_def::{ use hir_expand::{mod_path::ModPath, HirFileIdExt, InFile}; use intern::Interned; use la_arena::ArenaMap; +use ra_ap_rustc_abi::TargetDataLayout; use rustc_hash::{FxHashMap, FxHashSet}; use stdx::never; use syntax::{SyntaxNodePtr, TextRange}; @@ -51,7 +52,7 @@ macro_rules! from_bytes { ($ty:tt, $value:expr) => { ($ty::from_le_bytes(match ($value).try_into() { Ok(it) => it, - Err(_) => return Err(MirEvalError::TypeError(stringify!(mismatched size in constructing $ty))), + Err(_) => return Err(MirEvalError::InternalError(stringify!(mismatched size in constructing $ty).into())), })) }; } @@ -145,6 +146,7 @@ enum MirOrDynIndex { pub struct Evaluator<'a> { db: &'a dyn HirDatabase, trait_env: Arc, + target_data_layout: Arc, stack: Vec, heap: Vec, code_stack: Vec, @@ -316,12 +318,12 @@ impl Address { pub enum MirEvalError { ConstEvalError(String, Box), LayoutError(LayoutError, Ty), - /// Means that code had type errors (or mismatched args) and we shouldn't generate mir in first place. - TypeError(&'static str), + TargetDataLayoutNotAvailable(Arc), /// Means that code had undefined behavior. We don't try to actively detect UB, but if it was detected /// then use this type of error. UndefinedBehavior(String), Panic(String), + // FIXME: This should be folded into ConstEvalError? MirLowerError(FunctionId, MirLowerError), MirLowerErrorForClosure(ClosureId, MirLowerError), TypeIsUnsized(Ty, &'static str), @@ -330,11 +332,12 @@ pub enum MirEvalError { InFunction(Box, Vec<(Either, MirSpan, DefWithBodyId)>), ExecutionLimitExceeded, StackOverflow, - TargetDataLayoutNotAvailable, + /// FIXME: Fold this into InternalError InvalidVTableId(usize), + /// ? CoerceUnsizedError(Ty), - LangItemNotFound(LangItem), - BrokenLayout(Box), + /// These should not occur, usually indicates a bug in mir lowering. + InternalError(Box), } impl MirEvalError { @@ -406,8 +409,8 @@ impl MirEvalError { span_formatter, )?; } - MirEvalError::TypeError(_) - | MirEvalError::UndefinedBehavior(_) + MirEvalError::UndefinedBehavior(_) + | MirEvalError::TargetDataLayoutNotAvailable(_) | MirEvalError::Panic(_) | MirEvalError::MirLowerErrorForClosure(_, _) | MirEvalError::TypeIsUnsized(_, _) @@ -415,10 +418,8 @@ impl MirEvalError { | MirEvalError::InvalidConst(_) | MirEvalError::ExecutionLimitExceeded | MirEvalError::StackOverflow - | MirEvalError::TargetDataLayoutNotAvailable | MirEvalError::CoerceUnsizedError(_) - | MirEvalError::LangItemNotFound(_) - | MirEvalError::BrokenLayout(_) + | MirEvalError::InternalError(_) | MirEvalError::InvalidVTableId(_) => writeln!(f, "{:?}", err)?, } Ok(()) @@ -431,16 +432,16 @@ impl std::fmt::Debug for MirEvalError { Self::ConstEvalError(arg0, arg1) => { f.debug_tuple("ConstEvalError").field(arg0).field(arg1).finish() } - Self::LangItemNotFound(arg0) => f.debug_tuple("LangItemNotFound").field(arg0).finish(), Self::LayoutError(arg0, arg1) => { f.debug_tuple("LayoutError").field(arg0).field(arg1).finish() } - Self::TypeError(arg0) => f.debug_tuple("TypeError").field(arg0).finish(), Self::UndefinedBehavior(arg0) => { f.debug_tuple("UndefinedBehavior").field(arg0).finish() } Self::Panic(msg) => write!(f, "Panic with message:\n{msg:?}"), - Self::TargetDataLayoutNotAvailable => write!(f, "TargetDataLayoutNotAvailable"), + Self::TargetDataLayoutNotAvailable(arg0) => { + f.debug_tuple("TargetDataLayoutNotAvailable").field(arg0).finish() + } Self::TypeIsUnsized(ty, it) => write!(f, "{ty:?} is unsized. {it} should be sized."), Self::ExecutionLimitExceeded => write!(f, "execution limit exceeded"), Self::StackOverflow => write!(f, "stack overflow"), @@ -453,7 +454,7 @@ impl std::fmt::Debug for MirEvalError { Self::CoerceUnsizedError(arg0) => { f.debug_tuple("CoerceUnsizedError").field(arg0).finish() } - Self::BrokenLayout(arg0) => f.debug_tuple("BrokenLayout").field(arg0).finish(), + Self::InternalError(arg0) => f.debug_tuple("InternalError").field(arg0).finish(), Self::InvalidVTableId(arg0) => f.debug_tuple("InvalidVTableId").field(arg0).finish(), Self::NotSupported(arg0) => f.debug_tuple("NotSupported").field(arg0).finish(), Self::InvalidConst(arg0) => { @@ -530,7 +531,11 @@ pub fn interpret_mir( trait_env: Option>, ) -> (Result, MirOutput) { let ty = body.locals[return_slot()].ty.clone(); - let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env); + let mut evaluator = + match Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env) { + Ok(it) => it, + Err(e) => return (Err(e), MirOutput { stdout: vec![], stderr: vec![] }), + }; let it: Result = (|| { if evaluator.ptr_size() != std::mem::size_of::() { not_supported!("targets with different pointer size from host"); @@ -566,9 +571,15 @@ impl Evaluator<'_> { owner: DefWithBodyId, assert_placeholder_ty_is_unused: bool, trait_env: Option>, - ) -> Evaluator<'_> { + ) -> Result> { let crate_id = owner.module(db.upcast()).krate(); - Evaluator { + let target_data_layout = match db.target_data_layout(crate_id) { + Ok(target_data_layout) => target_data_layout, + Err(e) => return Err(MirEvalError::TargetDataLayoutNotAvailable(e)), + }; + let cached_ptr_size = target_data_layout.pointer_size.bytes_usize(); + Ok(Evaluator { + target_data_layout, stack: vec![0], heap: vec![0], code_stack: vec![], @@ -590,10 +601,7 @@ impl Evaluator<'_> { not_special_fn_cache: RefCell::new(Default::default()), mir_or_dyn_index_cache: RefCell::new(Default::default()), unused_locals_store: RefCell::new(Default::default()), - cached_ptr_size: match db.target_data_layout(crate_id) { - Some(it) => it.pointer_size.bytes_usize(), - None => 8, - }, + cached_ptr_size, cached_fn_trait_func: db .lang_item(crate_id, LangItem::Fn) .and_then(|x| x.as_trait()) @@ -606,7 +614,7 @@ impl Evaluator<'_> { .lang_item(crate_id, LangItem::FnOnce) .and_then(|x| x.as_trait()) .and_then(|x| db.trait_data(x).method_by_name(&name![call_once])), - } + }) } fn place_addr(&self, p: &Place, locals: &Locals) -> Result
{ @@ -754,8 +762,8 @@ impl Evaluator<'_> { RustcEnumVariantIdx(it.lookup(self.db.upcast()).index as usize) } _ => { - return Err(MirEvalError::TypeError( - "Multivariant layout only happens for enums", + return Err(MirEvalError::InternalError( + "mismatched layout".into(), )) } }] @@ -993,12 +1001,12 @@ impl Evaluator<'_> { IntervalOrOwned::Borrowed(value) => interval.write_from_interval(self, value)?, } if remain_args == 0 { - return Err(MirEvalError::TypeError("more arguments provided")); + return Err(MirEvalError::InternalError("too many arguments".into())); } remain_args -= 1; } if remain_args > 0 { - return Err(MirEvalError::TypeError("not enough arguments provided")); + return Err(MirEvalError::InternalError("too few arguments".into())); } Ok(()) } @@ -1071,8 +1079,8 @@ impl Evaluator<'_> { match metadata { Some(m) => m, None => { - return Err(MirEvalError::TypeError( - "type without metadata is used for Rvalue::Len", + return Err(MirEvalError::InternalError( + "type without metadata is used for Rvalue::Len".into(), )); } } @@ -1312,7 +1320,7 @@ impl Evaluator<'_> { } AggregateKind::Tuple(ty) => { let layout = self.layout(ty)?; - Owned(self.make_by_layout( + Owned(self.construct_with_layout( layout.size.bytes_usize(), &layout, None, @@ -1334,7 +1342,7 @@ impl Evaluator<'_> { AggregateKind::Adt(it, subst) => { let (size, variant_layout, tag) = self.layout_of_variant(*it, subst.clone(), locals)?; - Owned(self.make_by_layout( + Owned(self.construct_with_layout( size, &variant_layout, tag, @@ -1343,7 +1351,7 @@ impl Evaluator<'_> { } AggregateKind::Closure(ty) => { let layout = self.layout(ty)?; - Owned(self.make_by_layout( + Owned(self.construct_with_layout( layout.size.bytes_usize(), &layout, None, @@ -1415,10 +1423,7 @@ impl Evaluator<'_> { Ok(r) } Variants::Multiple { tag, tag_encoding, variants, .. } => { - let Some(target_data_layout) = self.db.target_data_layout(self.crate_id) else { - not_supported!("missing target data layout"); - }; - let size = tag.size(&*target_data_layout).bytes_usize(); + let size = tag.size(&*self.target_data_layout).bytes_usize(); let offset = layout.fields.offset(0).bytes_usize(); // The only field on enum variants is the tag field match tag_encoding { TagEncoding::Direct => { @@ -1458,9 +1463,8 @@ impl Evaluator<'_> { if let TyKind::Adt(id, subst) = kind { if let AdtId::StructId(struct_id) = id.0 { let field_types = self.db.field_types(struct_id.into()); - let mut field_types = field_types.iter(); if let Some(ty) = - field_types.next().map(|it| it.1.clone().substitute(Interner, subst)) + field_types.iter().last().map(|it| it.1.clone().substitute(Interner, subst)) { return self.coerce_unsized_look_through_fields(&ty, goal); } @@ -1578,10 +1582,6 @@ impl Evaluator<'_> { Ok(match &layout.variants { Variants::Single { .. } => (layout.size.bytes_usize(), layout, None), Variants::Multiple { variants, tag, tag_encoding, .. } => { - let cx = self - .db - .target_data_layout(self.crate_id) - .ok_or(MirEvalError::TargetDataLayoutNotAvailable)?; let enum_variant_id = match it { VariantId::EnumVariantId(it) => it, _ => not_supported!("multi variant layout for non-enums"), @@ -1612,7 +1612,7 @@ impl Evaluator<'_> { if have_tag { Some(( layout.fields.offset(0).bytes_usize(), - tag.size(&*cx).bytes_usize(), + tag.size(&*self.target_data_layout).bytes_usize(), discriminant, )) } else { @@ -1623,7 +1623,7 @@ impl Evaluator<'_> { }) } - fn make_by_layout( + fn construct_with_layout( &mut self, size: usize, // Not necessarily equal to variant_layout.size variant_layout: &Layout, @@ -1634,7 +1634,14 @@ impl Evaluator<'_> { if let Some((offset, size, value)) = tag { match result.get_mut(offset..offset + size) { Some(it) => it.copy_from_slice(&value.to_le_bytes()[0..size]), - None => return Err(MirEvalError::BrokenLayout(Box::new(variant_layout.clone()))), + None => { + return Err(MirEvalError::InternalError( + format!( + "encoded tag ({offset}, {size}, {value}) is out of bounds 0..{size}" + ) + .into(), + )) + } } } for (i, op) in values.enumerate() { @@ -1642,7 +1649,11 @@ impl Evaluator<'_> { let op = op.get(self)?; match result.get_mut(offset..offset + op.len()) { Some(it) => it.copy_from_slice(op), - None => return Err(MirEvalError::BrokenLayout(Box::new(variant_layout.clone()))), + None => { + return Err(MirEvalError::InternalError( + format!("field offset ({offset}) is out of bounds 0..{size}").into(), + )) + } } } Ok(result) @@ -1695,28 +1706,29 @@ impl Evaluator<'_> { } ConstScalar::Unknown => not_supported!("evaluating unknown const"), }; - let mut v: Cow<'_, [u8]> = Cow::Borrowed(v); let patch_map = memory_map.transform_addresses(|b, align| { let addr = self.heap_allocate(b.len(), align)?; self.write_memory(addr, b)?; Ok(addr.to_usize()) })?; let (size, align) = self.size_align_of(ty, locals)?.unwrap_or((v.len(), 1)); - if size != v.len() { + let v: Cow<'_, [u8]> = if size != v.len() { // Handle self enum if size == 16 && v.len() < 16 { - v = Cow::Owned(pad16(&v, false).to_vec()); + Cow::Owned(pad16(&v, false).to_vec()) } else if size < 16 && v.len() == 16 { - v = Cow::Owned(v[0..size].to_vec()); + Cow::Borrowed(&v[0..size]) } else { return Err(MirEvalError::InvalidConst(konst.clone())); } - } + } else { + Cow::Borrowed(v) + }; let addr = self.heap_allocate(size, align)?; self.write_memory(addr, &v)?; self.patch_addresses( &patch_map, - |bytes| match &memory_map { + |bytes| match memory_map { MemoryMap::Empty | MemoryMap::Simple(_) => { Err(MirEvalError::InvalidVTableId(from_bytes!(usize, bytes))) } @@ -2000,7 +2012,7 @@ impl Evaluator<'_> { if let Some((v, l)) = detect_variant_from_bytes( &layout, this.db, - this.trait_env.clone(), + &this.target_data_layout, bytes, e, ) { @@ -2079,7 +2091,7 @@ impl Evaluator<'_> { if let Some((ev, layout)) = detect_variant_from_bytes( &layout, self.db, - self.trait_env.clone(), + &self.target_data_layout, self.read_memory(addr, layout.size.bytes_usize())?, e, ) { @@ -2153,14 +2165,14 @@ impl Evaluator<'_> { ) -> Result> { let id = from_bytes!(usize, bytes.get(self)?); let next_ty = self.vtable_map.ty(id)?.clone(); - match &next_ty.kind(Interner) { + match next_ty.kind(Interner) { TyKind::FnDef(def, generic_args) => { self.exec_fn_def(*def, generic_args, destination, args, locals, target_bb, span) } TyKind::Closure(id, subst) => { self.exec_closure(*id, bytes.slice(0..0), subst, destination, args, locals, span) } - _ => Err(MirEvalError::TypeError("function pointer to non function")), + _ => Err(MirEvalError::InternalError("function pointer to non function".into())), } } @@ -2241,7 +2253,7 @@ impl Evaluator<'_> { CallableDefId::StructId(id) => { let (size, variant_layout, tag) = self.layout_of_variant(id.into(), generic_args, locals)?; - let result = self.make_by_layout( + let result = self.construct_with_layout( size, &variant_layout, tag, @@ -2253,7 +2265,7 @@ impl Evaluator<'_> { CallableDefId::EnumVariantId(id) => { let (size, variant_layout, tag) = self.layout_of_variant(id.into(), generic_args, locals)?; - let result = self.make_by_layout( + let result = self.construct_with_layout( size, &variant_layout, tag, @@ -2407,7 +2419,9 @@ impl Evaluator<'_> { target_bb: Option, span: MirSpan, ) -> Result> { - let func = args.first().ok_or(MirEvalError::TypeError("fn trait with no arg"))?; + let func = args + .first() + .ok_or_else(|| MirEvalError::InternalError("fn trait with no arg".into()))?; let mut func_ty = func.ty.clone(); let mut func_data = func.interval; while let TyKind::Ref(_, _, z) = func_ty.kind(Interner) { @@ -2450,7 +2464,7 @@ impl Evaluator<'_> { ) .intern(Interner); let layout = self.layout(&ty)?; - let result = self.make_by_layout( + let result = self.construct_with_layout( layout.size.bytes_usize(), &layout, None, @@ -2634,7 +2648,7 @@ pub fn render_const_using_debug_impl( owner: ConstId, c: &Const, ) -> Result { - let mut evaluator = Evaluator::new(db, owner.into(), false, None); + let mut evaluator = Evaluator::new(db, owner.into(), false, None)?; let locals = &Locals { ptr: ArenaMap::new(), body: db @@ -2699,12 +2713,7 @@ pub fn render_const_using_debug_impl( pub fn pad16(it: &[u8], is_signed: bool) -> [u8; 16] { let is_negative = is_signed && it.last().unwrap_or(&0) > &127; - let fill_with = if is_negative { 255 } else { 0 }; - it.iter() - .copied() - .chain(iter::repeat(fill_with)) - .take(16) - .collect::>() - .try_into() - .expect("iterator take is not working") + let mut res = [if is_negative { 255 } else { 0 }; 16]; + res[..it.len()].copy_from_slice(it); + res } diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index 4336e1e53b7f5..b4fb99acae778 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -18,7 +18,7 @@ macro_rules! from_bytes { ($ty:tt, $value:expr) => { ($ty::from_le_bytes(match ($value).try_into() { Ok(it) => it, - Err(_) => return Err(MirEvalError::TypeError("mismatched size")), + Err(_) => return Err(MirEvalError::InternalError("mismatched size".into())), })) }; } @@ -249,7 +249,9 @@ impl Evaluator<'_> { match alloc_fn { "rustc_allocator_zeroed" | "rustc_allocator" => { let [size, align] = args else { - return Err(MirEvalError::TypeError("rustc_allocator args are not provided")); + return Err(MirEvalError::InternalError( + "rustc_allocator args are not provided".into(), + )); }; let size = from_bytes!(usize, size.get(self)?); let align = from_bytes!(usize, align.get(self)?); @@ -259,7 +261,9 @@ impl Evaluator<'_> { "rustc_deallocator" => { /* no-op for now */ } "rustc_reallocator" => { let [ptr, old_size, align, new_size] = args else { - return Err(MirEvalError::TypeError("rustc_allocator args are not provided")); + return Err(MirEvalError::InternalError( + "rustc_allocator args are not provided".into(), + )); }; let old_size = from_bytes!(usize, old_size.get(self)?); let new_size = from_bytes!(usize, new_size.get(self)?); @@ -339,22 +343,22 @@ impl Evaluator<'_> { Err(MirEvalError::Panic(message)) } SliceLen => { - let arg = args - .next() - .ok_or(MirEvalError::TypeError("argument of <[T]>::len() is not provided"))?; + let arg = args.next().ok_or(MirEvalError::InternalError( + "argument of <[T]>::len() is not provided".into(), + ))?; let ptr_size = arg.len() / 2; Ok(arg[ptr_size..].into()) } DropInPlace => { let ty = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)).ok_or( - MirEvalError::TypeError( - "generic argument of drop_in_place is not provided", + MirEvalError::InternalError( + "generic argument of drop_in_place is not provided".into(), ), )?; - let arg = args - .next() - .ok_or(MirEvalError::TypeError("argument of drop_in_place is not provided"))?; + let arg = args.next().ok_or(MirEvalError::InternalError( + "argument of drop_in_place is not provided".into(), + ))?; self.run_drop_glue_deep( ty.clone(), locals, @@ -380,7 +384,9 @@ impl Evaluator<'_> { 318 => { // SYS_getrandom let [buf, len, _flags] = args else { - return Err(MirEvalError::TypeError("SYS_getrandom args are not provided")); + return Err(MirEvalError::InternalError( + "SYS_getrandom args are not provided".into(), + )); }; let addr = Address::from_bytes(buf.get(self)?)?; let size = from_bytes!(usize, len.get(self)?); @@ -408,7 +414,7 @@ impl Evaluator<'_> { match as_str { "memcmp" => { let [ptr1, ptr2, size] = args else { - return Err(MirEvalError::TypeError("memcmp args are not provided")); + return Err(MirEvalError::InternalError("memcmp args are not provided".into())); }; let addr1 = Address::from_bytes(ptr1.get(self)?)?; let addr2 = Address::from_bytes(ptr2.get(self)?)?; @@ -424,7 +430,9 @@ impl Evaluator<'_> { } "write" => { let [fd, ptr, len] = args else { - return Err(MirEvalError::TypeError("libc::write args are not provided")); + return Err(MirEvalError::InternalError( + "libc::write args are not provided".into(), + )); }; let fd = u128::from_le_bytes(pad16(fd.get(self)?, false)); let interval = Interval { @@ -446,14 +454,16 @@ impl Evaluator<'_> { "pthread_key_create" => { let key = self.thread_local_storage.create_key(); let Some(arg0) = args.first() else { - return Err(MirEvalError::TypeError("pthread_key_create arg0 is not provided")); + return Err(MirEvalError::InternalError( + "pthread_key_create arg0 is not provided".into(), + )); }; let arg0_addr = Address::from_bytes(arg0.get(self)?)?; let key_ty = if let Some((ty, ..)) = arg0.ty.as_reference_or_ptr() { ty } else { - return Err(MirEvalError::TypeError( - "pthread_key_create arg0 is not a pointer", + return Err(MirEvalError::InternalError( + "pthread_key_create arg0 is not a pointer".into(), )); }; let arg0_interval = Interval::new( @@ -467,8 +477,8 @@ impl Evaluator<'_> { } "pthread_getspecific" => { let Some(arg0) = args.first() else { - return Err(MirEvalError::TypeError( - "pthread_getspecific arg0 is not provided", + return Err(MirEvalError::InternalError( + "pthread_getspecific arg0 is not provided".into(), )); }; let key = from_bytes!(usize, &pad16(arg0.get(self)?, false)[0..8]); @@ -478,14 +488,14 @@ impl Evaluator<'_> { } "pthread_setspecific" => { let Some(arg0) = args.first() else { - return Err(MirEvalError::TypeError( - "pthread_setspecific arg0 is not provided", + return Err(MirEvalError::InternalError( + "pthread_setspecific arg0 is not provided".into(), )); }; let key = from_bytes!(usize, &pad16(arg0.get(self)?, false)[0..8]); let Some(arg1) = args.get(1) else { - return Err(MirEvalError::TypeError( - "pthread_setspecific arg1 is not provided", + return Err(MirEvalError::InternalError( + "pthread_setspecific arg1 is not provided".into(), )); }; let value = from_bytes!(u128, pad16(arg1.get(self)?, false)); @@ -502,14 +512,16 @@ impl Evaluator<'_> { } "syscall" => { let Some((id, rest)) = args.split_first() else { - return Err(MirEvalError::TypeError("syscall arg1 is not provided")); + return Err(MirEvalError::InternalError("syscall arg1 is not provided".into())); }; let id = from_bytes!(i64, id.get(self)?); self.exec_syscall(id, rest, destination, locals, span) } "sched_getaffinity" => { let [_pid, _set_size, set] = args else { - return Err(MirEvalError::TypeError("libc::write args are not provided")); + return Err(MirEvalError::InternalError( + "libc::write args are not provided".into(), + )); }; let set = Address::from_bytes(set.get(self)?)?; // Only enable core 0 (we are single threaded anyway), which is bitset 0x0000001 @@ -520,7 +532,9 @@ impl Evaluator<'_> { } "getenv" => { let [name] = args else { - return Err(MirEvalError::TypeError("libc::write args are not provided")); + return Err(MirEvalError::InternalError( + "libc::write args are not provided".into(), + )); }; let mut name_buf = vec![]; let name = { @@ -586,8 +600,8 @@ impl Evaluator<'_> { "sqrt" | "sin" | "cos" | "exp" | "exp2" | "log" | "log10" | "log2" | "fabs" | "floor" | "ceil" | "trunc" | "rint" | "nearbyint" | "round" | "roundeven" => { let [arg] = args else { - return Err(MirEvalError::TypeError( - "f64 intrinsic signature doesn't match fn (f64) -> f64", + return Err(MirEvalError::InternalError( + "f64 intrinsic signature doesn't match fn (f64) -> f64".into(), )); }; let arg = from_bytes!(f64, arg.get(self)?); @@ -614,8 +628,8 @@ impl Evaluator<'_> { } "pow" | "minnum" | "maxnum" | "copysign" => { let [arg1, arg2] = args else { - return Err(MirEvalError::TypeError( - "f64 intrinsic signature doesn't match fn (f64, f64) -> f64", + return Err(MirEvalError::InternalError( + "f64 intrinsic signature doesn't match fn (f64, f64) -> f64".into(), )); }; let arg1 = from_bytes!(f64, arg1.get(self)?); @@ -630,8 +644,8 @@ impl Evaluator<'_> { } "powi" => { let [arg1, arg2] = args else { - return Err(MirEvalError::TypeError( - "powif64 signature doesn't match fn (f64, i32) -> f64", + return Err(MirEvalError::InternalError( + "powif64 signature doesn't match fn (f64, i32) -> f64".into(), )); }; let arg1 = from_bytes!(f64, arg1.get(self)?); @@ -640,8 +654,8 @@ impl Evaluator<'_> { } "fma" => { let [arg1, arg2, arg3] = args else { - return Err(MirEvalError::TypeError( - "fmaf64 signature doesn't match fn (f64, f64, f64) -> f64", + return Err(MirEvalError::InternalError( + "fmaf64 signature doesn't match fn (f64, f64, f64) -> f64".into(), )); }; let arg1 = from_bytes!(f64, arg1.get(self)?); @@ -658,8 +672,8 @@ impl Evaluator<'_> { "sqrt" | "sin" | "cos" | "exp" | "exp2" | "log" | "log10" | "log2" | "fabs" | "floor" | "ceil" | "trunc" | "rint" | "nearbyint" | "round" | "roundeven" => { let [arg] = args else { - return Err(MirEvalError::TypeError( - "f32 intrinsic signature doesn't match fn (f32) -> f32", + return Err(MirEvalError::InternalError( + "f32 intrinsic signature doesn't match fn (f32) -> f32".into(), )); }; let arg = from_bytes!(f32, arg.get(self)?); @@ -686,8 +700,8 @@ impl Evaluator<'_> { } "pow" | "minnum" | "maxnum" | "copysign" => { let [arg1, arg2] = args else { - return Err(MirEvalError::TypeError( - "f32 intrinsic signature doesn't match fn (f32, f32) -> f32", + return Err(MirEvalError::InternalError( + "f32 intrinsic signature doesn't match fn (f32, f32) -> f32".into(), )); }; let arg1 = from_bytes!(f32, arg1.get(self)?); @@ -702,8 +716,8 @@ impl Evaluator<'_> { } "powi" => { let [arg1, arg2] = args else { - return Err(MirEvalError::TypeError( - "powif32 signature doesn't match fn (f32, i32) -> f32", + return Err(MirEvalError::InternalError( + "powif32 signature doesn't match fn (f32, i32) -> f32".into(), )); }; let arg1 = from_bytes!(f32, arg1.get(self)?); @@ -712,8 +726,8 @@ impl Evaluator<'_> { } "fma" => { let [arg1, arg2, arg3] = args else { - return Err(MirEvalError::TypeError( - "fmaf32 signature doesn't match fn (f32, f32, f32) -> f32", + return Err(MirEvalError::InternalError( + "fmaf32 signature doesn't match fn (f32, f32, f32) -> f32".into(), )); }; let arg1 = from_bytes!(f32, arg1.get(self)?); @@ -730,7 +744,9 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("size_of generic arg is not provided")); + return Err(MirEvalError::InternalError( + "size_of generic arg is not provided".into(), + )); }; let size = self.size_of_sized(ty, locals, "size_of arg")?; destination.write_from_bytes(self, &size.to_le_bytes()[0..destination.size]) @@ -739,7 +755,9 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("align_of generic arg is not provided")); + return Err(MirEvalError::InternalError( + "align_of generic arg is not provided".into(), + )); }; let align = self.layout(ty)?.align.abi.bytes(); destination.write_from_bytes(self, &align.to_le_bytes()[0..destination.size]) @@ -748,10 +766,14 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("size_of_val generic arg is not provided")); + return Err(MirEvalError::InternalError( + "size_of_val generic arg is not provided".into(), + )); }; let [arg] = args else { - return Err(MirEvalError::TypeError("size_of_val args are not provided")); + return Err(MirEvalError::InternalError( + "size_of_val args are not provided".into(), + )); }; if let Some((size, _)) = self.size_align_of(ty, locals)? { destination.write_from_bytes(self, &size.to_le_bytes()) @@ -765,12 +787,14 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "min_align_of_val generic arg is not provided", + return Err(MirEvalError::InternalError( + "min_align_of_val generic arg is not provided".into(), )); }; let [arg] = args else { - return Err(MirEvalError::TypeError("min_align_of_val args are not provided")); + return Err(MirEvalError::InternalError( + "min_align_of_val args are not provided".into(), + )); }; if let Some((_, align)) = self.size_align_of(ty, locals)? { destination.write_from_bytes(self, &align.to_le_bytes()) @@ -784,7 +808,9 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("type_name generic arg is not provided")); + return Err(MirEvalError::InternalError( + "type_name generic arg is not provided".into(), + )); }; let ty_name = match ty.display_source_code( self.db, @@ -808,7 +834,9 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("size_of generic arg is not provided")); + return Err(MirEvalError::InternalError( + "size_of generic arg is not provided".into(), + )); }; let result = !ty.clone().is_copy(self.db, locals.body.owner); destination.write_from_bytes(self, &[u8::from(result)]) @@ -817,14 +845,18 @@ impl Evaluator<'_> { // FIXME: this is wrong for const eval, it should return 2 in some // cases. let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("wrapping_add args are not provided")); + return Err(MirEvalError::InternalError( + "wrapping_add args are not provided".into(), + )); }; let ans = lhs.get(self)? == rhs.get(self)?; destination.write_from_bytes(self, &[u8::from(ans)]) } "saturating_add" | "saturating_sub" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("saturating_add args are not provided")); + return Err(MirEvalError::InternalError( + "saturating_add args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -844,7 +876,9 @@ impl Evaluator<'_> { } "wrapping_add" | "unchecked_add" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("wrapping_add args are not provided")); + return Err(MirEvalError::InternalError( + "wrapping_add args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -853,7 +887,9 @@ impl Evaluator<'_> { } "ptr_offset_from_unsigned" | "ptr_offset_from" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("wrapping_sub args are not provided")); + return Err(MirEvalError::InternalError( + "wrapping_sub args are not provided".into(), + )); }; let lhs = i128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = i128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -861,8 +897,8 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "ptr_offset_from generic arg is not provided", + return Err(MirEvalError::InternalError( + "ptr_offset_from generic arg is not provided".into(), )); }; let size = self.size_of_sized(ty, locals, "ptr_offset_from arg")? as i128; @@ -871,7 +907,9 @@ impl Evaluator<'_> { } "wrapping_sub" | "unchecked_sub" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("wrapping_sub args are not provided")); + return Err(MirEvalError::InternalError( + "wrapping_sub args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -880,7 +918,9 @@ impl Evaluator<'_> { } "wrapping_mul" | "unchecked_mul" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("wrapping_mul args are not provided")); + return Err(MirEvalError::InternalError( + "wrapping_mul args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -890,7 +930,9 @@ impl Evaluator<'_> { "wrapping_shl" | "unchecked_shl" => { // FIXME: signed let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("unchecked_shl args are not provided")); + return Err(MirEvalError::InternalError( + "unchecked_shl args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -900,7 +942,9 @@ impl Evaluator<'_> { "wrapping_shr" | "unchecked_shr" => { // FIXME: signed let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("unchecked_shr args are not provided")); + return Err(MirEvalError::InternalError( + "unchecked_shr args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -910,7 +954,9 @@ impl Evaluator<'_> { "unchecked_rem" => { // FIXME: signed let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("unchecked_rem args are not provided")); + return Err(MirEvalError::InternalError( + "unchecked_rem args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -922,7 +968,9 @@ impl Evaluator<'_> { "unchecked_div" | "exact_div" => { // FIXME: signed let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("unchecked_div args are not provided")); + return Err(MirEvalError::InternalError( + "unchecked_div args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -933,7 +981,9 @@ impl Evaluator<'_> { } "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("const_eval_select args are not provided")); + return Err(MirEvalError::InternalError( + "const_eval_select args are not provided".into(), + )); }; let result_ty = TyKind::Tuple( 2, @@ -954,7 +1004,7 @@ impl Evaluator<'_> { || ans.to_le_bytes()[op_size..].iter().any(|&it| it != 0 && it != 255); let is_overflow = vec![u8::from(is_overflow)]; let layout = self.layout(&result_ty)?; - let result = self.make_by_layout( + let result = self.construct_with_layout( layout.size.bytes_usize(), &layout, None, @@ -966,15 +1016,15 @@ impl Evaluator<'_> { } "copy" | "copy_nonoverlapping" => { let [src, dst, offset] = args else { - return Err(MirEvalError::TypeError( - "copy_nonoverlapping args are not provided", + return Err(MirEvalError::InternalError( + "copy_nonoverlapping args are not provided".into(), )); }; let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "copy_nonoverlapping generic arg is not provided", + return Err(MirEvalError::InternalError( + "copy_nonoverlapping generic arg is not provided".into(), )); }; let src = Address::from_bytes(src.get(self)?)?; @@ -988,18 +1038,22 @@ impl Evaluator<'_> { } "offset" | "arith_offset" => { let [ptr, offset] = args else { - return Err(MirEvalError::TypeError("offset args are not provided")); + return Err(MirEvalError::InternalError("offset args are not provided".into())); }; let ty = if name == "offset" { let Some(ty0) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("offset generic arg is not provided")); + return Err(MirEvalError::InternalError( + "offset generic arg is not provided".into(), + )); }; let Some(ty1) = generic_args.as_slice(Interner).get(1).and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("offset generic arg is not provided")); + return Err(MirEvalError::InternalError( + "offset generic arg is not provided".into(), + )); }; if !matches!( ty1.as_builtin(), @@ -1008,15 +1062,15 @@ impl Evaluator<'_> { | BuiltinType::Uint(BuiltinUint::Usize) ) ) { - return Err(MirEvalError::TypeError( - "offset generic arg is not usize or isize", + return Err(MirEvalError::InternalError( + "offset generic arg is not usize or isize".into(), )); } match ty0.as_raw_ptr() { Some((ty, _)) => ty, None => { - return Err(MirEvalError::TypeError( - "offset generic arg is not a raw pointer", + return Err(MirEvalError::InternalError( + "offset generic arg is not a raw pointer".into(), )); } } @@ -1024,8 +1078,8 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "arith_offset generic arg is not provided", + return Err(MirEvalError::InternalError( + "arith_offset generic arg is not provided".into(), )); }; ty @@ -1046,19 +1100,21 @@ impl Evaluator<'_> { } "transmute" => { let [arg] = args else { - return Err(MirEvalError::TypeError("transmute arg is not provided")); + return Err(MirEvalError::InternalError( + "transmute arg is not provided".into(), + )); }; destination.write_from_interval(self, arg.interval) } "likely" | "unlikely" => { let [arg] = args else { - return Err(MirEvalError::TypeError("likely arg is not provided")); + return Err(MirEvalError::InternalError("likely arg is not provided".into())); }; destination.write_from_interval(self, arg.interval) } "ctpop" => { let [arg] = args else { - return Err(MirEvalError::TypeError("ctpop arg is not provided")); + return Err(MirEvalError::InternalError("ctpop arg is not provided".into())); }; let result = u128::from_le_bytes(pad16(arg.get(self)?, false)).count_ones(); destination @@ -1066,7 +1122,7 @@ impl Evaluator<'_> { } "ctlz" | "ctlz_nonzero" => { let [arg] = args else { - return Err(MirEvalError::TypeError("ctlz arg is not provided")); + return Err(MirEvalError::InternalError("ctlz arg is not provided".into())); }; let result = u128::from_le_bytes(pad16(arg.get(self)?, false)).leading_zeros() as usize; @@ -1076,7 +1132,7 @@ impl Evaluator<'_> { } "cttz" | "cttz_nonzero" => { let [arg] = args else { - return Err(MirEvalError::TypeError("cttz arg is not provided")); + return Err(MirEvalError::InternalError("cttz arg is not provided".into())); }; let result = u128::from_le_bytes(pad16(arg.get(self)?, false)).trailing_zeros(); destination @@ -1084,7 +1140,9 @@ impl Evaluator<'_> { } "rotate_left" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("rotate_left args are not provided")); + return Err(MirEvalError::InternalError( + "rotate_left args are not provided".into(), + )); }; let lhs = &lhs.get(self)?[0..destination.size]; let rhs = rhs.get(self)?[0] as u32; @@ -1114,7 +1172,9 @@ impl Evaluator<'_> { } "rotate_right" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("rotate_right args are not provided")); + return Err(MirEvalError::InternalError( + "rotate_right args are not provided".into(), + )); }; let lhs = &lhs.get(self)?[0..destination.size]; let rhs = rhs.get(self)?[0] as u32; @@ -1144,13 +1204,15 @@ impl Evaluator<'_> { } "discriminant_value" => { let [arg] = args else { - return Err(MirEvalError::TypeError("discriminant_value arg is not provided")); + return Err(MirEvalError::InternalError( + "discriminant_value arg is not provided".into(), + )); }; let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "discriminant_value generic arg is not provided", + return Err(MirEvalError::InternalError( + "discriminant_value generic arg is not provided".into(), )); }; let addr = Address::from_bytes(arg.get(self)?)?; @@ -1161,11 +1223,15 @@ impl Evaluator<'_> { } "const_eval_select" => { let [tuple, const_fn, _] = args else { - return Err(MirEvalError::TypeError("const_eval_select args are not provided")); + return Err(MirEvalError::InternalError( + "const_eval_select args are not provided".into(), + )); }; let mut args = vec![const_fn.clone()]; let TyKind::Tuple(_, fields) = tuple.ty.kind(Interner) else { - return Err(MirEvalError::TypeError("const_eval_select arg[0] is not a tuple")); + return Err(MirEvalError::InternalError( + "const_eval_select arg[0] is not a tuple".into(), + )); }; let layout = self.layout(&tuple.ty)?; for (i, field) in fields.iter(Interner).enumerate() { @@ -1196,21 +1262,25 @@ impl Evaluator<'_> { } "read_via_copy" | "volatile_load" => { let [arg] = args else { - return Err(MirEvalError::TypeError("read_via_copy args are not provided")); + return Err(MirEvalError::InternalError( + "read_via_copy args are not provided".into(), + )); }; let addr = Address::from_bytes(arg.interval.get(self)?)?; destination.write_from_interval(self, Interval { addr, size: destination.size }) } "write_via_move" => { let [ptr, val] = args else { - return Err(MirEvalError::TypeError("write_via_move args are not provided")); + return Err(MirEvalError::InternalError( + "write_via_move args are not provided".into(), + )); }; let dst = Address::from_bytes(ptr.get(self)?)?; let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "write_via_copy generic arg is not provided", + return Err(MirEvalError::InternalError( + "write_via_copy generic arg is not provided".into(), )); }; let size = self.size_of_sized(ty, locals, "write_via_move ptr type")?; @@ -1219,14 +1289,18 @@ impl Evaluator<'_> { } "write_bytes" => { let [dst, val, count] = args else { - return Err(MirEvalError::TypeError("write_bytes args are not provided")); + return Err(MirEvalError::InternalError( + "write_bytes args are not provided".into(), + )); }; let count = from_bytes!(usize, count.get(self)?); let val = from_bytes!(u8, val.get(self)?); let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("write_bytes generic arg is not provided")); + return Err(MirEvalError::InternalError( + "write_bytes generic arg is not provided".into(), + )); }; let dst = Address::from_bytes(dst.get(self)?)?; let size = self.size_of_sized(ty, locals, "copy_nonoverlapping ptr type")?; @@ -1310,10 +1384,14 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("atomic intrinsic generic arg is not provided")); + return Err(MirEvalError::InternalError( + "atomic intrinsic generic arg is not provided".into(), + )); }; let Some(arg0) = args.first() else { - return Err(MirEvalError::TypeError("atomic intrinsic arg0 is not provided")); + return Err(MirEvalError::InternalError( + "atomic intrinsic arg0 is not provided".into(), + )); }; let arg0_addr = Address::from_bytes(arg0.get(self)?)?; let arg0_interval = @@ -1322,7 +1400,9 @@ impl Evaluator<'_> { return destination.write_from_interval(self, arg0_interval); } let Some(arg1) = args.get(1) else { - return Err(MirEvalError::TypeError("atomic intrinsic arg1 is not provided")); + return Err(MirEvalError::InternalError( + "atomic intrinsic arg1 is not provided".into(), + )); }; if name.starts_with("store_") { return arg0_interval.write_from_interval(self, arg1.interval); @@ -1374,7 +1454,9 @@ impl Evaluator<'_> { return arg0_interval.write_from_bytes(self, &ans.to_le_bytes()[0..destination.size]); } let Some(arg2) = args.get(2) else { - return Err(MirEvalError::TypeError("atomic intrinsic arg2 is not provided")); + return Err(MirEvalError::InternalError( + "atomic intrinsic arg2 is not provided".into(), + )); }; if name.starts_with("cxchg_") || name.starts_with("cxchgweak_") { let dest = if arg1.get(self)? == arg0_interval.get(self)? { @@ -1389,7 +1471,7 @@ impl Evaluator<'_> { ) .intern(Interner); let layout = self.layout(&result_ty)?; - let result = self.make_by_layout( + let result = self.construct_with_layout( layout.size.bytes_usize(), &layout, None, diff --git a/crates/hir-ty/src/mir/eval/shim/simd.rs b/crates/hir-ty/src/mir/eval/shim/simd.rs index f9156417f249f..eddfd0acfb98c 100644 --- a/crates/hir-ty/src/mir/eval/shim/simd.rs +++ b/crates/hir-ty/src/mir/eval/shim/simd.rs @@ -10,7 +10,7 @@ macro_rules! from_bytes { ($ty:tt, $value:expr) => { ($ty::from_le_bytes(match ($value).try_into() { Ok(it) => it, - Err(_) => return Err(MirEvalError::TypeError("mismatched size")), + Err(_) => return Err(MirEvalError::InternalError("mismatched size".into())), })) }; } @@ -40,7 +40,9 @@ impl Evaluator<'_> { .substitute(Interner, subst); return Ok((fields.len(), field_ty)); } - return Err(MirEvalError::TypeError("simd type with no len param")); + return Err(MirEvalError::InternalError( + "simd type with no len param".into(), + )); } }; match try_const_usize(self.db, len) { @@ -48,14 +50,18 @@ impl Evaluator<'_> { let Some(ty) = subst.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("simd type with no ty param")); + return Err(MirEvalError::InternalError( + "simd type with no ty param".into(), + )); }; Ok((len as usize, ty.clone())) } - None => Err(MirEvalError::TypeError("simd type with unevaluatable len param")), + None => Err(MirEvalError::InternalError( + "simd type with unevaluatable len param".into(), + )), } } - _ => Err(MirEvalError::TypeError("simd type which is not a struct")), + _ => Err(MirEvalError::InternalError("simd type which is not a struct".into())), } } @@ -71,7 +77,9 @@ impl Evaluator<'_> { match name { "and" | "or" | "xor" => { let [left, right] = args else { - return Err(MirEvalError::TypeError("simd bit op args are not provided")); + return Err(MirEvalError::InternalError( + "simd bit op args are not provided".into(), + )); }; let result = left .get(self)? @@ -88,7 +96,7 @@ impl Evaluator<'_> { } "eq" | "ne" | "lt" | "le" | "gt" | "ge" => { let [left, right] = args else { - return Err(MirEvalError::TypeError("simd args are not provided")); + return Err(MirEvalError::InternalError("simd args are not provided".into())); }; let (len, ty) = self.detect_simd_ty(&left.ty)?; let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_))); @@ -125,7 +133,9 @@ impl Evaluator<'_> { } "bitmask" => { let [op] = args else { - return Err(MirEvalError::TypeError("simd_bitmask args are not provided")); + return Err(MirEvalError::InternalError( + "simd_bitmask args are not provided".into(), + )); }; let (op_len, _) = self.detect_simd_ty(&op.ty)?; let op_count = op.interval.size / op_len; @@ -139,18 +149,20 @@ impl Evaluator<'_> { } "shuffle" => { let [left, right, index] = args else { - return Err(MirEvalError::TypeError("simd_shuffle args are not provided")); + return Err(MirEvalError::InternalError( + "simd_shuffle args are not provided".into(), + )); }; let TyKind::Array(_, index_len) = index.ty.kind(Interner) else { - return Err(MirEvalError::TypeError( - "simd_shuffle index argument has non-array type", + return Err(MirEvalError::InternalError( + "simd_shuffle index argument has non-array type".into(), )); }; let index_len = match try_const_usize(self.db, index_len) { Some(it) => it as usize, None => { - return Err(MirEvalError::TypeError( - "simd type with unevaluatable len param", + return Err(MirEvalError::InternalError( + "simd type with unevaluatable len param".into(), )) } }; @@ -164,8 +176,8 @@ impl Evaluator<'_> { let val = match vector.clone().nth(index) { Some(it) => it, None => { - return Err(MirEvalError::TypeError( - "out of bound access in simd shuffle", + return Err(MirEvalError::InternalError( + "out of bound access in simd shuffle".into(), )) } }; diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 99930798e87ab..f51853107fe92 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -939,7 +939,7 @@ impl<'ctx> MirLowerCtx<'ctx> { Ok(Some(current)) } Expr::BinaryOp { lhs, rhs, op } => { - let op = op.ok_or(MirLowerError::IncompleteExpr)?; + let op: BinaryOp = op.ok_or(MirLowerError::IncompleteExpr)?; let is_builtin = 'b: { // Without adjust here is a hack. We assume that we know every possible adjustment // for binary operator, and use without adjust to simplify our conditions. diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 2cdee5a15a88a..4a6bb0b2e04cb 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -24,18 +24,18 @@ use hir_def::{ }; use hir_expand::name::Name; use intern::Interned; +use ra_ap_rustc_abi::TargetDataLayout; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; use stdx::never; -use triomphe::Arc; use crate::{ consteval::unknown_const, db::HirDatabase, layout::{Layout, TagEncoding}, mir::pad16, - ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitEnvironment, - TraitRef, TraitRefExt, Ty, WhereClause, + ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitRef, TraitRefExt, + Ty, WhereClause, }; pub(crate) fn fn_traits( @@ -431,17 +431,15 @@ impl FallibleTypeFolder for UnevaluatedConstEvaluatorFolder<'_> { pub(crate) fn detect_variant_from_bytes<'a>( layout: &'a Layout, db: &dyn HirDatabase, - trait_env: Arc, + target_data_layout: &TargetDataLayout, b: &[u8], e: EnumId, ) -> Option<(EnumVariantId, &'a Layout)> { - let krate = trait_env.krate; let (var_id, var_layout) = match &layout.variants { hir_def::layout::Variants::Single { index } => { (db.enum_data(e).variants[index.0].0, layout) } hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => { - let target_data_layout = db.target_data_layout(krate)?; let size = tag.size(&*target_data_layout).bytes_usize(); let offset = layout.fields.offset(0).bytes_usize(); // The only field on enum variants is the tag field let tag = i128::from_le_bytes(pad16(&b[offset..offset + size], false)); diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index bf29a53913d1d..2d8f1dbad51a6 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -4,11 +4,12 @@ //! This probably isn't the best way to do this -- ideally, diagnostics should //! be expressed in terms of hir types themselves. pub use hir_ty::diagnostics::{CaseType, IncorrectCase}; +use hir_ty::{db::HirDatabase, diagnostics::BodyValidationDiagnostic, InferenceDiagnostic}; use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use either::Either; -use hir_def::{path::ModPath, AssocItemId}; +use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId}; use hir_expand::{name::Name, HirFileId, InFile}; use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange}; @@ -30,14 +31,28 @@ macro_rules! diagnostics { )* }; } +// FIXME Accept something like the following in the macro call instead +// diagnostics![ +// pub struct BreakOutsideOfLoop { +// pub expr: InFile>, +// pub is_break: bool, +// pub bad_value_break: bool, +// }, ... +// or more concisely +// BreakOutsideOfLoop { +// expr: InFile>, +// is_break: bool, +// bad_value_break: bool, +// }, ... +// ] diagnostics![ BreakOutsideOfLoop, ExpectedFunction, InactiveCode, + IncoherentImpl, IncorrectCase, InvalidDeriveTarget, - IncoherentImpl, MacroDefError, MacroError, MacroExpansionParseError, @@ -55,8 +70,8 @@ diagnostics![ ReplaceFilterMapNextWithFindMap, TraitImplIncorrectSafety, TraitImplMissingAssocItems, - TraitImplRedundantAssocItems, TraitImplOrphan, + TraitImplRedundantAssocItems, TypedHole, TypeMismatch, UndeclaredLabel, @@ -326,3 +341,219 @@ pub struct TraitImplRedundantAssocItems { pub impl_: AstPtr, pub assoc_item: (Name, AssocItem), } + +impl AnyDiagnostic { + pub(crate) fn body_validation_diagnostic( + db: &dyn HirDatabase, + diagnostic: BodyValidationDiagnostic, + source_map: &hir_def::body::BodySourceMap, + ) -> Option { + match diagnostic { + BodyValidationDiagnostic::RecordMissingFields { record, variant, missed_fields } => { + let variant_data = variant.variant_data(db.upcast()); + let missed_fields = missed_fields + .into_iter() + .map(|idx| variant_data.fields()[idx].name.clone()) + .collect(); + + match record { + Either::Left(record_expr) => match source_map.expr_syntax(record_expr) { + Ok(source_ptr) => { + let root = source_ptr.file_syntax(db.upcast()); + if let ast::Expr::RecordExpr(record_expr) = + source_ptr.value.to_node(&root) + { + if record_expr.record_expr_field_list().is_some() { + let field_list_parent_path = + record_expr.path().map(|path| AstPtr::new(&path)); + return Some( + MissingFields { + file: source_ptr.file_id, + field_list_parent: AstPtr::new(&Either::Left( + record_expr, + )), + field_list_parent_path, + missed_fields, + } + .into(), + ); + } + } + } + Err(SyntheticSyntax) => (), + }, + Either::Right(record_pat) => match source_map.pat_syntax(record_pat) { + Ok(source_ptr) => { + if let Some(ptr) = source_ptr.value.cast::() { + let root = source_ptr.file_syntax(db.upcast()); + let record_pat = ptr.to_node(&root); + if record_pat.record_pat_field_list().is_some() { + let field_list_parent_path = + record_pat.path().map(|path| AstPtr::new(&path)); + return Some( + MissingFields { + file: source_ptr.file_id, + field_list_parent: AstPtr::new(&Either::Right( + record_pat, + )), + field_list_parent_path, + missed_fields, + } + .into(), + ); + } + } + } + Err(SyntheticSyntax) => (), + }, + } + } + BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr } => { + if let Ok(next_source_ptr) = source_map.expr_syntax(method_call_expr) { + return Some( + ReplaceFilterMapNextWithFindMap { + file: next_source_ptr.file_id, + next_expr: next_source_ptr.value, + } + .into(), + ); + } + } + BodyValidationDiagnostic::MissingMatchArms { match_expr, uncovered_patterns } => { + match source_map.expr_syntax(match_expr) { + Ok(source_ptr) => { + let root = source_ptr.file_syntax(db.upcast()); + if let ast::Expr::MatchExpr(match_expr) = &source_ptr.value.to_node(&root) { + match match_expr.expr() { + Some(scrut_expr) if match_expr.match_arm_list().is_some() => { + return Some( + MissingMatchArms { + scrutinee_expr: InFile::new( + source_ptr.file_id, + AstPtr::new(&scrut_expr), + ), + uncovered_patterns, + } + .into(), + ); + } + _ => {} + } + } + } + Err(SyntheticSyntax) => (), + } + } + } + None + } + + pub(crate) fn inference_diagnostic( + db: &dyn HirDatabase, + def: DefWithBodyId, + d: &InferenceDiagnostic, + source_map: &hir_def::body::BodySourceMap, + ) -> Option { + let expr_syntax = |expr| source_map.expr_syntax(expr).expect("unexpected synthetic"); + let pat_syntax = |pat| source_map.pat_syntax(pat).expect("unexpected synthetic"); + Some(match d { + &InferenceDiagnostic::NoSuchField { field: expr, private } => { + let expr_or_pat = match expr { + ExprOrPatId::ExprId(expr) => { + source_map.field_syntax(expr).map(AstPtr::wrap_left) + } + ExprOrPatId::PatId(pat) => { + source_map.pat_field_syntax(pat).map(AstPtr::wrap_right) + } + }; + NoSuchField { field: expr_or_pat, private }.into() + } + &InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { + MismatchedArgCount { call_expr: expr_syntax(call_expr), expected, found }.into() + } + &InferenceDiagnostic::PrivateField { expr, field } => { + let expr = expr_syntax(expr); + let field = field.into(); + PrivateField { expr, field }.into() + } + &InferenceDiagnostic::PrivateAssocItem { id, item } => { + let expr_or_pat = match id { + ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), + ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), + }; + let item = item.into(); + PrivateAssocItem { expr_or_pat, item }.into() + } + InferenceDiagnostic::ExpectedFunction { call_expr, found } => { + let call_expr = expr_syntax(*call_expr); + ExpectedFunction { call: call_expr, found: Type::new(db, def, found.clone()) } + .into() + } + InferenceDiagnostic::UnresolvedField { + expr, + receiver, + name, + method_with_same_name_exists, + } => { + let expr = expr_syntax(*expr); + UnresolvedField { + expr, + name: name.clone(), + receiver: Type::new(db, def, receiver.clone()), + method_with_same_name_exists: *method_with_same_name_exists, + } + .into() + } + InferenceDiagnostic::UnresolvedMethodCall { + expr, + receiver, + name, + field_with_same_name, + assoc_func_with_same_name, + } => { + let expr = expr_syntax(*expr); + UnresolvedMethodCall { + expr, + name: name.clone(), + receiver: Type::new(db, def, receiver.clone()), + field_with_same_name: field_with_same_name + .clone() + .map(|ty| Type::new(db, def, ty)), + assoc_func_with_same_name: *assoc_func_with_same_name, + } + .into() + } + &InferenceDiagnostic::UnresolvedAssocItem { id } => { + let expr_or_pat = match id { + ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), + ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), + }; + UnresolvedAssocItem { expr_or_pat }.into() + } + &InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break, bad_value_break } => { + let expr = expr_syntax(expr); + BreakOutsideOfLoop { expr, is_break, bad_value_break }.into() + } + InferenceDiagnostic::TypedHole { expr, expected } => { + let expr = expr_syntax(*expr); + TypedHole { expr, expected: Type::new(db, def, expected.clone()) }.into() + } + &InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => { + let expr_or_pat = match pat { + ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), + ExprOrPatId::PatId(pat) => { + let InFile { file_id, value } = + source_map.pat_syntax(pat).expect("unexpected synthetic"); + + // cast from Either -> Either<_, Pat> + let Some(ptr) = AstPtr::try_from_raw(value.syntax_node_ptr()) else { + return None; + }; + InFile { file_id, value: ptr } + } + }; + MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into() + } + }) + } +} diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c332ab0050cfb..eafba8a88b89d 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -61,7 +61,7 @@ use hir_def::{ use hir_expand::{attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, MacroCallKind}; use hir_ty::{ all_super_traits, autoderef, check_orphan_rules, - consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt}, + consteval::{try_const_usize, unknown_const_as_generic, ConstExt}, diagnostics::BodyValidationDiagnostic, known_const_to_ast, layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, @@ -70,9 +70,9 @@ use hir_ty::{ primitive::UintTy, traits::FnTrait, AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, - GenericArgData, InferenceDiagnostic, Interner, ParamKind, QuantifiedWhereClause, Scalar, - Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, - ValueTyDefId, WhereClause, + GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution, + TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId, + WhereClause, }; use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; @@ -131,8 +131,10 @@ pub use { MacroFileIdExt, }, hir_ty::{ + consteval::ConstEvalError, display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, layout::LayoutError, + mir::{MirEvalError, MirLowerError}, PointerCast, Safety, }, // FIXME: Properly encapsulate mir @@ -1626,116 +1628,8 @@ impl DefWithBody { } let infer = db.infer(self.into()); - let expr_syntax = |expr| source_map.expr_syntax(expr).expect("unexpected synthetic"); - let pat_syntax = |pat| source_map.pat_syntax(pat).expect("unexpected synthetic"); for d in &infer.diagnostics { - acc.push(match d { - &InferenceDiagnostic::NoSuchField { field: expr, private } => { - let expr_or_pat = match expr { - ExprOrPatId::ExprId(expr) => { - source_map.field_syntax(expr).map(AstPtr::wrap_left) - } - ExprOrPatId::PatId(pat) => { - source_map.pat_field_syntax(pat).map(AstPtr::wrap_right) - } - }; - NoSuchField { field: expr_or_pat, private }.into() - } - &InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { - MismatchedArgCount { call_expr: expr_syntax(call_expr), expected, found }.into() - } - &InferenceDiagnostic::PrivateField { expr, field } => { - let expr = expr_syntax(expr); - let field = field.into(); - PrivateField { expr, field }.into() - } - &InferenceDiagnostic::PrivateAssocItem { id, item } => { - let expr_or_pat = match id { - ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), - ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), - }; - let item = item.into(); - PrivateAssocItem { expr_or_pat, item }.into() - } - InferenceDiagnostic::ExpectedFunction { call_expr, found } => { - let call_expr = expr_syntax(*call_expr); - ExpectedFunction { - call: call_expr, - found: Type::new(db, DefWithBodyId::from(self), found.clone()), - } - .into() - } - InferenceDiagnostic::UnresolvedField { - expr, - receiver, - name, - method_with_same_name_exists, - } => { - let expr = expr_syntax(*expr); - UnresolvedField { - expr, - name: name.clone(), - receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), - method_with_same_name_exists: *method_with_same_name_exists, - } - .into() - } - InferenceDiagnostic::UnresolvedMethodCall { - expr, - receiver, - name, - field_with_same_name, - assoc_func_with_same_name, - } => { - let expr = expr_syntax(*expr); - UnresolvedMethodCall { - expr, - name: name.clone(), - receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), - field_with_same_name: field_with_same_name - .clone() - .map(|ty| Type::new(db, DefWithBodyId::from(self), ty)), - assoc_func_with_same_name: *assoc_func_with_same_name, - } - .into() - } - &InferenceDiagnostic::UnresolvedAssocItem { id } => { - let expr_or_pat = match id { - ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), - ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), - }; - UnresolvedAssocItem { expr_or_pat }.into() - } - &InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break, bad_value_break } => { - let expr = expr_syntax(expr); - BreakOutsideOfLoop { expr, is_break, bad_value_break }.into() - } - InferenceDiagnostic::TypedHole { expr, expected } => { - let expr = expr_syntax(*expr); - - TypedHole { - expr, - expected: Type::new(db, DefWithBodyId::from(self), expected.clone()), - } - .into() - } - &InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => { - let expr_or_pat = match pat { - ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), - ExprOrPatId::PatId(pat) => { - let InFile { file_id, value } = - source_map.pat_syntax(pat).expect("unexpected synthetic"); - - // cast from Either -> Either<_, Pat> - let Some(ptr) = AstPtr::try_from_raw(value.syntax_node_ptr()) else { - continue; - }; - InFile { file_id, value: ptr } - } - }; - MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into() - } - }); + acc.extend(AnyDiagnostic::inference_diagnostic(db, self.into(), d, &source_map)); } for (pat_or_expr, mismatch) in infer.type_mismatches() { let expr_or_pat = match pat_or_expr { @@ -1857,109 +1751,7 @@ impl DefWithBody { } for diagnostic in BodyValidationDiagnostic::collect(db, self.into()) { - match diagnostic { - BodyValidationDiagnostic::RecordMissingFields { - record, - variant, - missed_fields, - } => { - let variant_data = variant.variant_data(db.upcast()); - let missed_fields = missed_fields - .into_iter() - .map(|idx| variant_data.fields()[idx].name.clone()) - .collect(); - - match record { - Either::Left(record_expr) => match source_map.expr_syntax(record_expr) { - Ok(source_ptr) => { - let root = source_ptr.file_syntax(db.upcast()); - if let ast::Expr::RecordExpr(record_expr) = - source_ptr.value.to_node(&root) - { - if record_expr.record_expr_field_list().is_some() { - let field_list_parent_path = - record_expr.path().map(|path| AstPtr::new(&path)); - acc.push( - MissingFields { - file: source_ptr.file_id, - field_list_parent: AstPtr::new(&Either::Left( - record_expr, - )), - field_list_parent_path, - missed_fields, - } - .into(), - ) - } - } - } - Err(SyntheticSyntax) => (), - }, - Either::Right(record_pat) => match source_map.pat_syntax(record_pat) { - Ok(source_ptr) => { - if let Some(ptr) = source_ptr.value.cast::() { - let root = source_ptr.file_syntax(db.upcast()); - let record_pat = ptr.to_node(&root); - if record_pat.record_pat_field_list().is_some() { - let field_list_parent_path = - record_pat.path().map(|path| AstPtr::new(&path)); - acc.push( - MissingFields { - file: source_ptr.file_id, - field_list_parent: AstPtr::new(&Either::Right( - record_pat, - )), - field_list_parent_path, - missed_fields, - } - .into(), - ) - } - } - } - Err(SyntheticSyntax) => (), - }, - } - } - BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr } => { - if let Ok(next_source_ptr) = source_map.expr_syntax(method_call_expr) { - acc.push( - ReplaceFilterMapNextWithFindMap { - file: next_source_ptr.file_id, - next_expr: next_source_ptr.value, - } - .into(), - ); - } - } - BodyValidationDiagnostic::MissingMatchArms { match_expr, uncovered_patterns } => { - match source_map.expr_syntax(match_expr) { - Ok(source_ptr) => { - let root = source_ptr.file_syntax(db.upcast()); - if let ast::Expr::MatchExpr(match_expr) = - &source_ptr.value.to_node(&root) - { - match match_expr.expr() { - Some(scrut_expr) if match_expr.match_arm_list().is_some() => { - acc.push( - MissingMatchArms { - scrutinee_expr: InFile::new( - source_ptr.file_id, - AstPtr::new(&scrut_expr), - ), - uncovered_patterns, - } - .into(), - ); - } - _ => {} - } - } - } - Err(SyntheticSyntax) => (), - } - } - } + acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, &source_map)); } let def: ModuleDef = match self { @@ -1975,7 +1767,6 @@ impl DefWithBody { } } } - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Function { pub(crate) id: FunctionId, diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 348308d7100ad..9f4427090e9e8 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -7196,8 +7196,8 @@ impl Iterator for S { file_id: FileId( 1, ), - full_range: 6012..6220, - focus_range: 6077..6083, + full_range: 6156..6364, + focus_range: 6221..6227, name: "Future", kind: Trait, container_name: "future", @@ -7210,8 +7210,8 @@ impl Iterator for S { file_id: FileId( 1, ), - full_range: 6850..7316, - focus_range: 6894..6902, + full_range: 6994..7460, + focus_range: 7038..7046, name: "Iterator", kind: Trait, container_name: "iterator", diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index f42e14f2e51ea..c33fbddceff2e 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -302,13 +302,13 @@ impl flags::AnalysisStats { let mut fail = 0; for &c in consts { all += 1; - let Err(e) = c.render_eval(db) else { + let Err(error) = c.render_eval(db) else { continue; }; if verbosity.is_spammy() { let full_name = full_name_of_item(db, c.module(db), c.name(db).unwrap_or(Name::missing())); - println!("Const eval for {full_name} failed due {e:?}"); + println!("Const eval for {full_name} failed due {error:?}"); } fail += 1; } diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs index b015dd69b528a..9c25d88cb8428 100644 --- a/crates/test-utils/src/minicore.rs +++ b/crates/test-utils/src/minicore.rs @@ -28,7 +28,7 @@ //! env: option //! eq: sized //! error: fmt -//! fmt: result, transmute, coerce_unsized +//! fmt: option, result, transmute, coerce_unsized //! fn: //! from: sized //! future: pin @@ -987,6 +987,10 @@ pub mod fmt { Arguments { pieces, fmt: None, args } } + pub const fn new_const(pieces: &'a [&'static str]) -> Arguments<'a> { + Arguments { pieces, fmt: None, args: &[] } + } + pub fn new_v1_formatted( pieces: &'a [&'static str], args: &'a [rt::Argument<'a>], @@ -1346,6 +1350,9 @@ pub mod iter { // region:panic mod panic { pub macro panic_2021 { + () => ( + $crate::panicking::panic("explicit panic") + ), ($($t:tt)+) => ( $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)) ), @@ -1357,6 +1364,11 @@ mod panicking { pub const fn panic_fmt(_fmt: crate::fmt::Arguments<'_>) -> ! { loop {} } + + #[lang = "panic"] + pub const fn panic(expr: &'static str) -> ! { + panic_fmt(crate::fmt::Arguments::new_const(&[expr])) + } } // endregion:panic From 64b6b5b6ce078684dea0d312e3ac0911e1d6a0df Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 25 Jan 2024 19:16:38 +0300 Subject: [PATCH 113/246] hir: Simplify `hir_owner_nodes` query The query accept arbitrary DefIds, not just owner DefIds. The return can be an `Option` because if there are no nodes, then it doesn't matter whether it's due to NonOwner or Phantom. Also rename the query to `opt_hir_owner_nodes`. --- .../rustc_incremental/src/assert_dep_graph.rs | 2 +- .../src/persist/dirty_clean.rs | 4 +- compiler/rustc_middle/src/hir/map/mod.rs | 8 +- compiler/rustc_middle/src/hir/mod.rs | 9 +- compiler/rustc_middle/src/query/mod.rs | 4 +- .../rustc_mir_transform/src/coverage/mod.rs | 2 +- .../clippy_lints/src/min_ident_chars.rs | 2 +- tests/incremental/dirty_clean.rs | 4 +- tests/incremental/hash-module-order.rs | 4 +- tests/incremental/hashes/call_expressions.rs | 38 +- .../incremental/hashes/closure_expressions.rs | 24 +- tests/incremental/hashes/consts.rs | 18 +- tests/incremental/hashes/enum_constructors.rs | 60 +-- tests/incremental/hashes/enum_defs.rs | 138 +++---- tests/incremental/hashes/exported_vs_not.rs | 14 +- tests/incremental/hashes/extern_mods.rs | 12 +- tests/incremental/hashes/for_loops.rs | 44 +- .../incremental/hashes/function_interfaces.rs | 76 ++-- tests/incremental/hashes/if_expressions.rs | 32 +- .../hashes/indexing_expressions.rs | 28 +- tests/incremental/hashes/inherent_impls.rs | 160 +++---- tests/incremental/hashes/inline_asm.rs | 24 +- tests/incremental/hashes/let_expressions.rs | 48 +-- tests/incremental/hashes/loop_expressions.rs | 32 +- tests/incremental/hashes/match_expressions.rs | 52 +-- tests/incremental/hashes/panic_exprs.rs | 18 +- tests/incremental/hashes/statics.rs | 38 +- .../incremental/hashes/struct_constructors.rs | 36 +- tests/incremental/hashes/struct_defs.rs | 66 +-- tests/incremental/hashes/trait_defs.rs | 390 +++++++++--------- tests/incremental/hashes/trait_impls.rs | 112 ++--- tests/incremental/hashes/type_defs.rs | 32 +- .../hashes/unary_and_binary_exprs.rs | 112 ++--- tests/incremental/hashes/while_let_loops.rs | 36 +- tests/incremental/hashes/while_loops.rs | 36 +- .../hygiene/auxiliary/cached_hygiene.rs | 2 +- tests/incremental/ich_nested_items.rs | 2 +- tests/incremental/ich_resolve_results.rs | 4 +- tests/incremental/source_loc_macros.rs | 4 +- tests/incremental/string_constant.rs | 2 +- 40 files changed, 862 insertions(+), 867 deletions(-) diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 6f909a0cc9db4..aa6f184a2d7d1 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -131,7 +131,7 @@ impl<'tcx> IfThisChanged<'tcx> { None => DepNode::from_def_path_hash( self.tcx, def_path_hash, - dep_kinds::hir_owner_nodes, + dep_kinds::opt_hir_owner_nodes, ), Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 842cc9fae9b4d..14cc8c260e218 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -57,8 +57,8 @@ const BASE_FN: &[&str] = &[ /// DepNodes for Hir, which is pretty much everything const BASE_HIR: &[&str] = &[ - // hir_owner_nodes should be computed for all nodes - label_strs::hir_owner_nodes, + // opt_hir_owner_nodes should be computed for all nodes + label_strs::opt_hir_owner_nodes, ]; /// `impl` implementation of struct/trait diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 949b786e3a7d2..db73e1b936b6b 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -135,12 +135,12 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { impl<'tcx> TyCtxt<'tcx> { #[inline] fn hir_owner(self, owner: OwnerId) -> Option> { - Some(self.hir_owner_nodes(owner).as_owner()?.node()) + Some(self.opt_hir_owner_nodes(owner.def_id)?.node()) } /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. pub fn opt_hir_node(self, id: HirId) -> Option> { - let owner = self.hir_owner_nodes(id.owner).as_owner()?; + let owner = self.opt_hir_owner_nodes(id.owner)?; let node = owner.nodes[id.local_id].as_ref()?; Some(node.node) } @@ -213,7 +213,7 @@ impl<'hir> Map<'hir> { if id.local_id == ItemLocalId::from_u32(0) { Some(self.tcx.hir_owner_parent(id.owner)) } else { - let owner = self.tcx.hir_owner_nodes(id.owner).as_owner()?; + let owner = self.tcx.opt_hir_owner_nodes(id.owner)?; let node = owner.nodes[id.local_id].as_ref()?; let hir_id = HirId { owner: id.owner, local_id: node.parent }; // HIR indexing should have checked that. @@ -266,7 +266,7 @@ impl<'hir> Map<'hir> { } pub fn body(self, id: BodyId) -> &'hir Body<'hir> { - self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[&id.hir_id.local_id] + self.tcx.opt_hir_owner_nodes(id.hir_id.owner).unwrap().bodies[&id.hir_id.local_id] } #[track_caller] diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 2d4d5deaefa93..b54e438f6144d 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -135,13 +135,8 @@ pub fn provide(providers: &mut Providers) { MaybeOwner::NonOwner(hir_id) => hir_id, }) }; - providers.hir_owner_nodes = |tcx, id| { - if let Some(i) = tcx.hir_crate(()).owners.get(id.def_id) { - i.map(|i| &i.nodes) - } else { - MaybeOwner::Phantom - } - }; + providers.opt_hir_owner_nodes = + |tcx, id| tcx.hir_crate(()).owners.get(id)?.as_owner().map(|i| &i.nodes); providers.hir_owner_parent = |tcx, id| { // Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash. tcx.opt_local_parent(id.def_id).map_or(CRATE_HIR_ID, |parent| { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1122f571fff8a..658549e598e66 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -190,11 +190,11 @@ rustc_queries! { desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) } } - /// Gives access to the HIR nodes and bodies inside the HIR owner `key`. + /// Gives access to the HIR nodes and bodies inside `key` if it's a HIR owner. /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_owner_nodes(key: hir::OwnerId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> { + query opt_hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> { desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index ad5fcc3acf12f..3d8012cdb64cc 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -452,7 +452,7 @@ fn get_body_span<'tcx>( fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 { // FIXME(cjgillot) Stop hashing HIR manually here. let owner = hir_body.id().hir_id.owner; - tcx.hir_owner_nodes(owner) + tcx.opt_hir_owner_nodes(owner) .unwrap() .opt_hash_including_bodies .unwrap() diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs index 34b8e0dbe6a7e..2b0063f62d943 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -93,7 +93,7 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { // reimplement it even if we wanted to cx.tcx.opt_hir_node(hir_id) } else { - let Some(owner) = cx.tcx.hir_owner_nodes(hir_id.owner).as_owner() else { + let Some(owner) = cx.tcx.opt_hir_owner_nodes(hir_id.owner) else { return; }; owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node) diff --git a/tests/incremental/dirty_clean.rs b/tests/incremental/dirty_clean.rs index 87a8696b1899f..e6379286805e1 100644 --- a/tests/incremental/dirty_clean.rs +++ b/tests/incremental/dirty_clean.rs @@ -26,11 +26,11 @@ mod y { use x; #[rustc_clean( - except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig", + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig", cfg="cfail2", )] pub fn y() { - //[cfail2]~^ ERROR `hir_owner_nodes(y)` should be dirty but is not + //[cfail2]~^ ERROR `opt_hir_owner_nodes(y)` should be dirty but is not //[cfail2]~| ERROR `generics_of(y)` should be dirty but is not //[cfail2]~| ERROR `predicates_of(y)` should be dirty but is not //[cfail2]~| ERROR `type_of(y)` should be dirty but is not diff --git a/tests/incremental/hash-module-order.rs b/tests/incremental/hash-module-order.rs index f9244d8adbf35..2e71884a531ae 100644 --- a/tests/incremental/hash-module-order.rs +++ b/tests/incremental/hash-module-order.rs @@ -12,14 +12,14 @@ #![feature(rustc_attrs)] #[cfg(rpass1)] -#[rustc_clean(cfg="rpass1",except="hir_owner_nodes")] +#[rustc_clean(cfg="rpass1",except="opt_hir_owner_nodes")] mod foo { struct First; struct Second; } #[cfg(rpass2)] -#[rustc_clean(cfg="rpass2",except="hir_owner_nodes")] +#[rustc_clean(cfg="rpass2",except="opt_hir_owner_nodes")] mod foo { struct Second; struct First; diff --git a/tests/incremental/hashes/call_expressions.rs b/tests/incremental/hashes/call_expressions.rs index a42cf6aa477c5..bad2e10e497d9 100644 --- a/tests/incremental/hashes/call_expressions.rs +++ b/tests/incremental/hashes/call_expressions.rs @@ -28,9 +28,9 @@ pub fn change_callee_function() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_callee_function() { callee2(1, 2) @@ -45,9 +45,9 @@ pub fn change_argument_function() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_argument_function() { callee1(1, 3) @@ -62,9 +62,9 @@ mod change_callee_indirectly_function { #[cfg(not(any(cfail1,cfail4)))] use super::callee2 as callee; - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn change_callee_indirectly_function() { callee(1, 2) @@ -86,9 +86,9 @@ pub fn change_callee_method() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_callee_method() { let s = Struct; @@ -105,9 +105,9 @@ pub fn change_argument_method() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_argument_method() { let s = Struct; @@ -124,9 +124,9 @@ pub fn change_ufcs_callee_method() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_ufcs_callee_method() { let s = Struct; @@ -143,9 +143,9 @@ pub fn change_argument_method_ufcs() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_argument_method_ufcs() { let s = Struct; @@ -162,11 +162,11 @@ pub fn change_to_ufcs() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] -// One might think this would be expanded in the hir_owner_nodes/Mir, but it actually +// One might think this would be expanded in the opt_hir_owner_nodes/Mir, but it actually // results in slightly different hir_owner/Mir. pub fn change_to_ufcs() { let s = Struct; @@ -186,9 +186,9 @@ pub mod change_ufcs_callee_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::Struct2 as Struct; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_ufcs_callee_indirectly() { let s = Struct; diff --git a/tests/incremental/hashes/closure_expressions.rs b/tests/incremental/hashes/closure_expressions.rs index 927bcd96e6f4b..0173d129b2392 100644 --- a/tests/incremental/hashes/closure_expressions.rs +++ b/tests/incremental/hashes/closure_expressions.rs @@ -24,9 +24,9 @@ pub fn change_closure_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_closure_body() { let _ = || 3u32; @@ -42,9 +42,9 @@ pub fn add_parameter() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_parameter() { let x = 0u32; @@ -60,9 +60,9 @@ pub fn change_parameter_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_parameter_pattern() { let _ = |(x,): (u32,)| x; @@ -77,9 +77,9 @@ pub fn add_move() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_move() { let _ = move || 1; @@ -95,9 +95,9 @@ pub fn add_type_ascription_to_parameter() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg = "cfail6")] pub fn add_type_ascription_to_parameter() { let closure = |x: u32| x + 1u32; @@ -114,9 +114,9 @@ pub fn change_parameter_type() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_parameter_type() { let closure = |x: u16| (x as u64) + 1; diff --git a/tests/incremental/hashes/consts.rs b/tests/incremental/hashes/consts.rs index 7cba3c159e600..138618a982d28 100644 --- a/tests/incremental/hashes/consts.rs +++ b/tests/incremental/hashes/consts.rs @@ -19,7 +19,7 @@ const CONST_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub const CONST_VISIBILITY: u8 = 0; @@ -29,7 +29,7 @@ pub const CONST_VISIBILITY: u8 = 0; const CONST_CHANGE_TYPE_1: i32 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_1: u32 = 0; @@ -39,13 +39,13 @@ const CONST_CHANGE_TYPE_1: u32 = 0; const CONST_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_2: Option = None; // Change value between simple literals -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_1: i16 = { #[cfg(cfail1)] @@ -57,7 +57,7 @@ const CONST_CHANGE_VALUE_1: i16 = { // Change value between expressions -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_2: i16 = { #[cfg(cfail1)] @@ -67,7 +67,7 @@ const CONST_CHANGE_VALUE_2: i16 = { { 1 + 2 } }; -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_3: i16 = { #[cfg(cfail1)] @@ -77,7 +77,7 @@ const CONST_CHANGE_VALUE_3: i16 = { { 2 * 3 } }; -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_4: i16 = { #[cfg(cfail1)] @@ -99,11 +99,11 @@ mod const_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/tests/incremental/hashes/enum_constructors.rs b/tests/incremental/hashes/enum_constructors.rs index 0a88dd4e15537..1e0db8ffc9284 100644 --- a/tests/incremental/hashes/enum_constructors.rs +++ b/tests/incremental/hashes/enum_constructors.rs @@ -37,9 +37,9 @@ pub fn change_field_value_struct_like() -> Enum { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_field_value_struct_like() -> Enum { Enum::Struct { @@ -62,9 +62,9 @@ pub fn change_field_order_struct_like() -> Enum { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] // FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it // would if it were not all constants @@ -103,9 +103,9 @@ pub fn change_constructor_path_struct_like() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_struct_like() { let _ = Enum2::Struct { @@ -128,9 +128,9 @@ pub fn change_constructor_variant_struct_like() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_variant_struct_like() { let _ = Enum2::Struct2 { @@ -148,9 +148,9 @@ pub mod change_constructor_path_indirectly_struct_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2 as TheEnum; - #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::Struct { @@ -170,9 +170,9 @@ pub mod change_constructor_variant_indirectly_struct_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2::Struct2 as Variant; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn function() -> Enum2 { Variant { @@ -191,9 +191,9 @@ pub fn change_field_value_tuple_like() -> Enum { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_field_value_tuple_like() -> Enum { Enum::Tuple(0, 1, 3) @@ -210,12 +210,12 @@ pub fn change_constructor_path_tuple_like() { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,typeck" + except="opt_hir_owner_nodes,typeck" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,typeck" + except="opt_hir_owner_nodes,typeck" )] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_tuple_like() { @@ -233,12 +233,12 @@ pub fn change_constructor_variant_tuple_like() { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,typeck" + except="opt_hir_owner_nodes,typeck" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,typeck" + except="opt_hir_owner_nodes,typeck" )] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_variant_tuple_like() { @@ -253,9 +253,9 @@ pub mod change_constructor_path_indirectly_tuple_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2 as TheEnum; - #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::Tuple(0, 1, 2) @@ -272,9 +272,9 @@ pub mod change_constructor_variant_indirectly_tuple_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2::Tuple2 as Variant; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> Enum2 { Variant(0, 1, 2) @@ -301,9 +301,9 @@ pub fn change_constructor_path_c_like() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_c_like() { let _x = Clike2::B; @@ -318,9 +318,9 @@ pub fn change_constructor_variant_c_like() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_variant_c_like() { let _x = Clike::C; @@ -334,9 +334,9 @@ pub mod change_constructor_path_indirectly_c_like { #[cfg(not(any(cfail1,cfail4)))] use super::Clike2 as TheEnum; - #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::B @@ -353,9 +353,9 @@ pub mod change_constructor_variant_indirectly_c_like { #[cfg(not(any(cfail1,cfail4)))] use super::Clike::B as Variant; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn function() -> Clike { Variant diff --git a/tests/incremental/hashes/enum_defs.rs b/tests/incremental/hashes/enum_defs.rs index cb7a4e61e4f57..2293d15b97f27 100644 --- a/tests/incremental/hashes/enum_defs.rs +++ b/tests/incremental/hashes/enum_defs.rs @@ -31,7 +31,7 @@ enum EnumVisibility { A } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub enum EnumVisibility { A } @@ -45,9 +45,9 @@ enum EnumChangeNameCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameCStyleVariant { Variant1, @@ -64,9 +64,9 @@ enum EnumChangeNameTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameTupleStyleVariant { Variant1, @@ -83,9 +83,9 @@ enum EnumChangeNameStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameStructStyleVariant { Variant1, @@ -102,9 +102,9 @@ enum EnumChangeValueCStyleVariant0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeValueCStyleVariant0 { Variant1, @@ -118,9 +118,9 @@ enum EnumChangeValueCStyleVariant1 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeValueCStyleVariant1 { Variant1, @@ -136,9 +136,9 @@ enum EnumAddCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddCStyleVariant { Variant1, @@ -155,9 +155,9 @@ enum EnumRemoveCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveCStyleVariant { Variant1, @@ -172,9 +172,9 @@ enum EnumAddTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTupleStyleVariant { Variant1, @@ -191,9 +191,9 @@ enum EnumRemoveTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveTupleStyleVariant { Variant1, @@ -208,9 +208,9 @@ enum EnumAddStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddStructStyleVariant { Variant1, @@ -227,9 +227,9 @@ enum EnumRemoveStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveStructStyleVariant { Variant1, @@ -244,9 +244,9 @@ enum EnumChangeFieldTypeTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldTypeTupleStyleVariant { Variant1(u32, @@ -263,9 +263,9 @@ enum EnumChangeFieldTypeStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldTypeStructStyleVariant { Variant1, @@ -284,9 +284,9 @@ enum EnumChangeFieldNameStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldNameStructStyleVariant { Variant1 { a: u32, c: u32 }, @@ -301,9 +301,9 @@ enum EnumChangeOrderTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeOrderTupleStyleVariant { Variant1( @@ -320,9 +320,9 @@ enum EnumChangeFieldOrderStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldOrderStructStyleVariant { Variant1 { b: f32, a: u32 }, @@ -337,9 +337,9 @@ enum EnumAddFieldTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddFieldTupleStyleVariant { Variant1(u32, u32, u32), @@ -354,9 +354,9 @@ enum EnumAddFieldStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddFieldStructStyleVariant { Variant1 { a: u32, b: u32, c: u32 }, @@ -411,9 +411,9 @@ enum EnumChangeNameOfTypeParameter { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameOfTypeParameter { Variant1(T), @@ -429,9 +429,9 @@ enum EnumAddTypeParameter { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTypeParameter { Variant1(S), @@ -447,9 +447,9 @@ enum EnumChangeNameOfLifetimeParameter<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameOfLifetimeParameter<'b> { Variant1(&'b u32), @@ -465,9 +465,9 @@ enum EnumAddLifetimeParameter<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameter<'a, 'b> { Variant1(&'a u32), @@ -484,9 +484,9 @@ enum EnumAddLifetimeParameterBound<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameterBound<'a, 'b: 'a> { Variant1(&'a u32), @@ -501,9 +501,9 @@ enum EnumAddLifetimeBoundToParameter<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameter<'a, T: 'a> { Variant1(T), @@ -519,9 +519,9 @@ enum EnumAddTraitBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTraitBound { Variant1(T), @@ -537,9 +537,9 @@ enum EnumAddLifetimeParameterBoundWhere<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a { Variant1(&'a u32), @@ -556,9 +556,9 @@ enum EnumAddLifetimeBoundToParameterWhere<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a { Variant1(T), @@ -574,9 +574,9 @@ enum EnumAddTraitBoundWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTraitBoundWhere where T: Sync { Variant1(T), @@ -592,9 +592,9 @@ enum EnumSwapUsageTypeParameters { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumSwapUsageTypeParameters { Variant1 { @@ -615,9 +615,9 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumSwapUsageLifetimeParameters<'a, 'b> { Variant1 { @@ -642,9 +642,9 @@ mod change_field_type_indirectly_tuple_style { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum TupleStyle { Variant1( @@ -662,9 +662,9 @@ mod change_field_type_indirectly_struct_style { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum StructStyle { Variant1 { @@ -687,9 +687,9 @@ mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum Enum { Variant1(T) @@ -705,9 +705,9 @@ mod change_trait_bound_indirectly_where { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum Enum where T: Trait { Variant1(T) diff --git a/tests/incremental/hashes/exported_vs_not.rs b/tests/incremental/hashes/exported_vs_not.rs index 9ac9ae24f81bc..358ba1d93d1a7 100644 --- a/tests/incremental/hashes/exported_vs_not.rs +++ b/tests/incremental/hashes/exported_vs_not.rs @@ -10,7 +10,7 @@ #![crate_type="rlib"] // Case 1: The function body is not exported to metadata. If the body changes, -// the hash of the hir_owner_nodes node should change, but not the hash of +// the hash of the opt_hir_owner_nodes node should change, but not the hash of // either the hir_owner or the Metadata node. #[cfg(any(cfail1,cfail4))] @@ -19,9 +19,9 @@ pub fn body_not_exported_to_metadata() -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn body_not_exported_to_metadata() -> u32 { 2 @@ -40,9 +40,9 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] #[inline] pub fn body_exported_to_metadata_because_of_inline() -> u32 { @@ -62,9 +62,9 @@ pub fn body_exported_to_metadata_because_of_generic() -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] #[inline] pub fn body_exported_to_metadata_because_of_generic() -> u32 { diff --git a/tests/incremental/hashes/extern_mods.rs b/tests/incremental/hashes/extern_mods.rs index 93a8fcfea3214..efac5c91658c6 100644 --- a/tests/incremental/hashes/extern_mods.rs +++ b/tests/incremental/hashes/extern_mods.rs @@ -24,9 +24,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "C" { pub fn change_function_name2(c: i64) -> i32; @@ -129,9 +129,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "rust-call" { pub fn change_calling_convention(c: (i32,)); @@ -159,9 +159,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "C" { pub fn add_function1(c: i32); diff --git a/tests/incremental/hashes/for_loops.rs b/tests/incremental/hashes/for_loops.rs index 84a04ff913b84..e297fcdd329db 100644 --- a/tests/incremental/hashes/for_loops.rs +++ b/tests/incremental/hashes/for_loops.rs @@ -28,9 +28,9 @@ pub fn change_loop_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; @@ -53,9 +53,9 @@ pub fn change_iteration_variable_name() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_iteration_variable_name() { let mut _x = 0; @@ -78,9 +78,9 @@ pub fn change_iteration_variable_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_iteration_variable_pattern() { let mut _x = 0; @@ -103,9 +103,9 @@ pub fn change_iterable() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, promoted_mir, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, promoted_mir, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, promoted_mir, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, promoted_mir, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_iterable() { let mut _x = 0; @@ -128,9 +128,9 @@ pub fn add_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; @@ -153,9 +153,9 @@ pub fn add_loop_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label() { let mut _x = 0; @@ -178,9 +178,9 @@ pub fn add_loop_label_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -205,9 +205,9 @@ pub fn change_break_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; @@ -232,9 +232,9 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -259,9 +259,9 @@ pub fn change_continue_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; @@ -286,9 +286,9 @@ pub fn change_continue_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/tests/incremental/hashes/function_interfaces.rs b/tests/incremental/hashes/function_interfaces.rs index 2aaaf94492c2f..5ba4781c5f1ca 100644 --- a/tests/incremental/hashes/function_interfaces.rs +++ b/tests/incremental/hashes/function_interfaces.rs @@ -25,12 +25,12 @@ pub fn add_parameter() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn add_parameter(p: i32) {} @@ -41,9 +41,9 @@ pub fn add_parameter(p: i32) {} pub fn add_return_type() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg = "cfail6")] pub fn add_return_type() -> () {} @@ -55,12 +55,12 @@ pub fn type_of_parameter(p: i32) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn type_of_parameter(p: i64) {} @@ -73,12 +73,12 @@ pub fn type_of_parameter_ref(p: &i32) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn type_of_parameter_ref(p: &mut i32) {} @@ -91,12 +91,12 @@ pub fn order_of_parameters(p1: i32, p2: i64) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn order_of_parameters(p2: i64, p1: i32) {} @@ -109,12 +109,12 @@ pub fn make_unsafe() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub unsafe fn make_unsafe() {} @@ -125,9 +125,9 @@ pub unsafe fn make_unsafe() {} pub fn make_extern() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail6")] pub extern "C" fn make_extern() {} @@ -139,12 +139,12 @@ pub fn type_parameter () {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, generics_of, type_of, predicates_of" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, generics_of, type_of, predicates_of" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of" )] #[rustc_clean(cfg = "cfail6")] pub fn type_parameter() {} @@ -155,9 +155,9 @@ pub fn type_parameter() {} pub fn lifetime_parameter () {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, generics_of,fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, generics_of,fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, generics_of,fn_sig")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, generics_of,fn_sig")] #[rustc_clean(cfg = "cfail6")] pub fn lifetime_parameter<'a>() {} @@ -167,7 +167,7 @@ pub fn lifetime_parameter<'a>() {} pub fn trait_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn trait_bound() {} @@ -177,9 +177,9 @@ pub fn trait_bound() {} pub fn builtin_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn builtin_bound() {} @@ -191,12 +191,12 @@ pub fn lifetime_bound<'a, T>() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir" )] #[rustc_clean(cfg = "cfail6")] pub fn lifetime_bound<'a, T: 'a>() {} @@ -207,7 +207,7 @@ pub fn lifetime_bound<'a, T: 'a>() {} pub fn second_trait_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_trait_bound() {} @@ -217,9 +217,9 @@ pub fn second_trait_bound() {} pub fn second_builtin_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn second_builtin_bound() {} @@ -231,12 +231,12 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a >() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} @@ -302,9 +302,9 @@ pub fn return_impl_trait() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck, fn_sig, optimized_mir")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, typeck, fn_sig, optimized_mir")] #[rustc_clean(cfg = "cfail6")] pub fn return_impl_trait() -> impl Clone { 0 @@ -339,12 +339,12 @@ pub mod change_return_type_indirectly { #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn indirect_return_type() -> ReturnType { @@ -362,12 +362,12 @@ pub mod change_parameter_type_indirectly { #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn indirect_parameter_type(p: ParameterType) {} @@ -384,9 +384,9 @@ pub mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] - #[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn indirect_trait_bound(p: T) {} } @@ -399,9 +399,9 @@ pub mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] - #[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn indirect_trait_bound_where(p: T) where diff --git a/tests/incremental/hashes/if_expressions.rs b/tests/incremental/hashes/if_expressions.rs index cd80f8aa00a59..430a6015bd5a9 100644 --- a/tests/incremental/hashes/if_expressions.rs +++ b/tests/incremental/hashes/if_expressions.rs @@ -27,9 +27,9 @@ pub fn change_condition(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_condition(x: bool) -> u32 { if !x { @@ -50,9 +50,9 @@ pub fn change_then_branch(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_then_branch(x: bool) -> u32 { if x { @@ -75,9 +75,9 @@ pub fn change_else_branch(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_else_branch(x: bool) -> u32 { if x { @@ -103,9 +103,9 @@ pub fn add_else_branch(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_else_branch(x: bool) -> u32 { let mut ret = 1; @@ -131,9 +131,9 @@ pub fn change_condition_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_condition_if_let(x: Option) -> u32 { if let Some(_ ) = x { @@ -156,9 +156,9 @@ pub fn change_then_branch_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_then_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -181,9 +181,9 @@ pub fn change_else_branch_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_else_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -209,9 +209,9 @@ pub fn add_else_branch_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_else_branch_if_let(x: Option) -> u32 { let mut ret = 1; diff --git a/tests/incremental/hashes/indexing_expressions.rs b/tests/incremental/hashes/indexing_expressions.rs index 4bccec61a7ce3..f07550305f12c 100644 --- a/tests/incremental/hashes/indexing_expressions.rs +++ b/tests/incremental/hashes/indexing_expressions.rs @@ -23,9 +23,9 @@ fn change_simple_index(slice: &[u32]) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn change_simple_index(slice: &[u32]) -> u32 { slice[4] @@ -40,9 +40,9 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn change_lower_bound(slice: &[u32]) -> &[u32] { &slice[2..5] @@ -57,9 +57,9 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn change_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] @@ -74,9 +74,9 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn add_lower_bound(slice: &[u32]) -> &[u32] { &slice[3..4] @@ -91,9 +91,9 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn add_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] @@ -108,9 +108,9 @@ fn change_mutability(slice: &mut [u32]) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn change_mutability(slice: &mut [u32]) -> u32 { (& slice[3..5])[0] @@ -125,9 +125,9 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { &slice[3..=7] diff --git a/tests/incremental/hashes/inherent_impls.rs b/tests/incremental/hashes/inherent_impls.rs index 853fbc79fc878..a2b3dcdc1587a 100644 --- a/tests/incremental/hashes/inherent_impls.rs +++ b/tests/incremental/hashes/inherent_impls.rs @@ -26,9 +26,9 @@ impl Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail3")] @@ -41,9 +41,9 @@ impl Foo { // This should affect the method itself, but not the impl. #[cfg(any(cfail1,cfail4))] impl Foo { - //-------------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------------ //-------------------------- - //-------------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------------ //-------------------------- pub fn method_body() { // ----------------------- @@ -56,9 +56,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,promoted_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,promoted_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn method_body() { println!("Hello, world!"); @@ -73,12 +73,12 @@ impl Foo { impl Foo { //------------ //--------------- - //------------------------------------------------------------ + //---------------------------------------------------------------- // //-------------------------- //------------ //--------------- - //------------------------------------------------------------ + //---------------------------------------------------------------- // //-------------------------- #[inline] @@ -95,12 +95,12 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,optimized_mir,promoted_mir,typeck" + except="opt_hir_owner_nodes,optimized_mir,promoted_mir,typeck" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,optimized_mir,promoted_mir,typeck" + except="opt_hir_owner_nodes,optimized_mir,promoted_mir,typeck" )] #[rustc_clean(cfg="cfail6")] #[inline] @@ -115,7 +115,7 @@ impl Foo { impl Foo { //-------------------------- //-------------------------- - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- pub fn method_privacy() { } } @@ -128,7 +128,7 @@ impl Foo { impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] fn method_privacy() { } } @@ -138,31 +138,31 @@ impl Foo { impl Foo { //------------ //--------------- - //----------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------- // //-------------------------- //------------ //--------------- - //----------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------- // //-------------------------- pub fn method_selfness() { } } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", + except="opt_hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", + except="opt_hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", )] #[rustc_clean(cfg="cfail6")] pub fn method_selfness(&self) { } @@ -171,9 +171,9 @@ impl Foo { // Change Method Selfmutness --------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- pub fn method_selfmutness(& self) { } } @@ -184,9 +184,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn method_selfmutness(&mut self) { } } @@ -200,9 +200,9 @@ impl Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2")] @@ -221,9 +221,9 @@ impl Foo { // Add Method Parameter -------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- pub fn add_method_parameter(&self ) { } } @@ -234,9 +234,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_method_parameter(&self, _: i32) { } } @@ -246,9 +246,9 @@ impl Foo { // Change Method Parameter Name ------------------------------------------------ #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- pub fn change_method_parameter_name(&self, a: i64) { } } @@ -259,9 +259,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_method_parameter_name(&self, b: i64) { } } @@ -271,9 +271,9 @@ impl Foo { // Change Method Return Type --------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- pub fn change_method_return_type(&self) -> u16 { 0 } } @@ -284,9 +284,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_method_return_type(&self) -> u32 { 0 } } @@ -323,9 +323,9 @@ impl Foo { // Change order of parameters ------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- pub fn change_method_parameter_order(&self, a: i64, b: i64) { } } @@ -336,9 +336,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_method_parameter_order(&self, b: i64, a: i64) { } } @@ -348,9 +348,9 @@ impl Foo { // Make method unsafe ---------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- pub fn make_method_unsafe(&self) { } } @@ -361,9 +361,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub unsafe fn make_method_unsafe(&self) { } } @@ -373,9 +373,9 @@ impl Foo { // Make method extern ---------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- pub fn make_method_extern(&self) { } } @@ -386,9 +386,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail6")] pub extern "C" fn make_method_extern(&self) { } } @@ -398,9 +398,9 @@ impl Foo { // Change method calling convention -------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- pub extern "C" fn change_method_calling_convention(&self) { } } @@ -411,9 +411,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail6")] pub extern "system" fn change_method_calling_convention(&self) { } } @@ -432,9 +432,9 @@ impl Foo { // ---------------------------------------------------------- // ----------------------------------------------------------- // ---------------------------------------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // ------------------------- pub fn add_lifetime_parameter_to_method (&self) { } } @@ -454,9 +454,9 @@ impl Foo { // if we lower generics before the body, then the `HirId` for // things in the body will be affected. So if you start to see // `typeck` appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,generics_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,generics_of")] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } @@ -477,12 +477,12 @@ impl Foo { // ------------------------------------------------- // ----------- // -------------- - // ------------------------------------------------------------ + // ---------------------------------------------------------------- // // ------------------------- // ----------- // -------------- - // ------------------------------------------------------------ + // ---------------------------------------------------------------- // // ------------------------- pub fn add_type_parameter_to_method (&self) { } @@ -505,12 +505,12 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,generics_of,predicates_of,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,generics_of,predicates_of,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail6")] pub fn add_type_parameter_to_method(&self) { } @@ -523,12 +523,12 @@ impl Foo { impl Foo { //------------ //--------------- - //------------------------------------------------------------------- + //----------------------------------------------------------------------- // //-------------------------- //------------ //--------------- - //------------------------------------------------------------------- + //----------------------------------------------------------------------- // //-------------------------- pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b >(&self) { } @@ -542,12 +542,12 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } @@ -569,12 +569,12 @@ impl Foo { // ------------------------------------------------- // ----------- // -------------- - // ------------------------------------------------------------------ + // ---------------------------------------------------------------------- // // ------------------------- // ----------- // -------------- - // ------------------------------------------------------------------ + // ---------------------------------------------------------------------- // // ------------------------- pub fn add_lifetime_bound_to_type_param_of_method<'a, T >(&self) { } @@ -597,12 +597,12 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } @@ -622,9 +622,9 @@ impl Foo { // ------------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- pub fn add_trait_bound_to_type_param_of_method(&self) { } } @@ -644,9 +644,9 @@ impl Foo { // generics before the body, then the `HirId` for things in the // body will be affected. So if you start to see `typeck` // appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] pub fn add_trait_bound_to_type_param_of_method(&self) { } } @@ -689,9 +689,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean( @@ -716,9 +716,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,typeck")] @@ -737,9 +737,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2")] @@ -758,9 +758,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2")] diff --git a/tests/incremental/hashes/inline_asm.rs b/tests/incremental/hashes/inline_asm.rs index 3118aa1356452..1570030dbeae3 100644 --- a/tests/incremental/hashes/inline_asm.rs +++ b/tests/incremental/hashes/inline_asm.rs @@ -33,9 +33,9 @@ pub fn change_template(_a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_template(_a: i32) -> i32 { @@ -66,9 +66,9 @@ pub fn change_output(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_output(a: i32) -> i32 { @@ -100,9 +100,9 @@ pub fn change_input(_a: i32, _b: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input(_a: i32, _b: i32) -> i32 { @@ -133,9 +133,9 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { @@ -166,9 +166,9 @@ pub fn change_clobber(_a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_clobber(_a: i32) -> i32 { @@ -201,9 +201,9 @@ pub fn change_options(_a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_options(_a: i32) -> i32 { diff --git a/tests/incremental/hashes/let_expressions.rs b/tests/incremental/hashes/let_expressions.rs index a835b8eef8ce7..62a91bf75f8a3 100644 --- a/tests/incremental/hashes/let_expressions.rs +++ b/tests/incremental/hashes/let_expressions.rs @@ -23,9 +23,9 @@ pub fn change_name() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_name() { let _y = 2u64; @@ -40,9 +40,9 @@ pub fn add_type() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_type() { let _x: u32 = 2u32; @@ -57,9 +57,9 @@ pub fn change_type() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_type() { let _x: u8 = 2; @@ -74,9 +74,9 @@ pub fn change_mutability_of_reference_type() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_reference_type() { let _x: &mut u64; @@ -91,9 +91,9 @@ pub fn change_mutability_of_slot() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_slot() { let _x: u64 = 0; @@ -108,9 +108,9 @@ pub fn change_simple_binding_to_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_simple_binding_to_pattern() { let (_a, _b) = (0u8, 'x'); @@ -125,9 +125,9 @@ pub fn change_name_in_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_name_in_pattern() { let (_a, _c) = (1u8, 'y'); @@ -142,9 +142,9 @@ pub fn add_ref_in_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_ref_in_pattern() { let (ref _a, _b) = (1u8, 'y'); @@ -159,9 +159,9 @@ pub fn add_amp_in_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_amp_in_pattern() { let (&_a, _b) = (&1u8, 'y'); @@ -176,9 +176,9 @@ pub fn change_mutability_of_binding_in_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_binding_in_pattern() { let (mut _a, _b) = (99u8, 'q'); @@ -193,9 +193,9 @@ pub fn add_initializer() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_initializer() { let _x: i16 = 3i16; @@ -210,9 +210,9 @@ pub fn change_initializer() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_initializer() { let _x = 5u16; diff --git a/tests/incremental/hashes/loop_expressions.rs b/tests/incremental/hashes/loop_expressions.rs index 13e37bd59f8e8..810ba877061c6 100644 --- a/tests/incremental/hashes/loop_expressions.rs +++ b/tests/incremental/hashes/loop_expressions.rs @@ -28,9 +28,9 @@ pub fn change_loop_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; @@ -53,9 +53,9 @@ pub fn add_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; @@ -78,9 +78,9 @@ pub fn add_loop_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label() { let mut _x = 0; @@ -103,9 +103,9 @@ pub fn add_loop_label_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -130,9 +130,9 @@ pub fn change_break_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; @@ -157,9 +157,9 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -184,9 +184,9 @@ pub fn change_continue_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; @@ -211,9 +211,9 @@ pub fn change_continue_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, typeck, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, typeck, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/tests/incremental/hashes/match_expressions.rs b/tests/incremental/hashes/match_expressions.rs index ebcf1708a7aaa..c77ac27d49623 100644 --- a/tests/incremental/hashes/match_expressions.rs +++ b/tests/incremental/hashes/match_expressions.rs @@ -28,9 +28,9 @@ pub fn add_arm(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_arm(x: u32) -> u32 { match x { @@ -54,9 +54,9 @@ pub fn change_order_of_arms(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_order_of_arms(x: u32) -> u32 { match x { @@ -79,9 +79,9 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -104,9 +104,9 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -129,9 +129,9 @@ pub fn add_at_binding(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_at_binding(x: u32) -> u32 { match x { @@ -154,9 +154,9 @@ pub fn change_name_of_at_binding(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_name_of_at_binding(x: u32) -> u32 { match x { @@ -178,9 +178,9 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_simple_name_to_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -202,9 +202,9 @@ pub fn change_name_in_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_name_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -227,9 +227,9 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 { // Ignore optimized_mir in cfail2, the only change to optimized MIR is a span. #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -250,9 +250,9 @@ pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -273,9 +273,9 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { match (&x, x & 1) { @@ -297,9 +297,9 @@ pub fn change_rhs_of_arm(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_rhs_of_arm(x: u32) -> u32 { match x { @@ -322,9 +322,9 @@ pub fn add_alternative_to_arm(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_alternative_to_arm(x: u32) -> u32 { match x { diff --git a/tests/incremental/hashes/panic_exprs.rs b/tests/incremental/hashes/panic_exprs.rs index 37d10d922c177..440a7b6fbf41f 100644 --- a/tests/incremental/hashes/panic_exprs.rs +++ b/tests/incremental/hashes/panic_exprs.rs @@ -18,7 +18,7 @@ // Indexing expression -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn indexing(slice: &[u8]) -> u8 { #[cfg(cfail1)] @@ -33,7 +33,7 @@ pub fn indexing(slice: &[u8]) -> u8 { // Arithmetic overflow plus -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_plus(val: i32) -> i32 { #[cfg(cfail1)] @@ -48,7 +48,7 @@ pub fn arithmetic_overflow_plus(val: i32) -> i32 { // Arithmetic overflow minus -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_minus(val: i32) -> i32 { #[cfg(cfail1)] @@ -63,7 +63,7 @@ pub fn arithmetic_overflow_minus(val: i32) -> i32 { // Arithmetic overflow mult -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_mult(val: i32) -> i32 { #[cfg(cfail1)] @@ -78,7 +78,7 @@ pub fn arithmetic_overflow_mult(val: i32) -> i32 { // Arithmetic overflow negation -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_negation(val: i32) -> i32 { #[cfg(cfail1)] @@ -93,7 +93,7 @@ pub fn arithmetic_overflow_negation(val: i32) -> i32 { // Division by zero -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn division_by_zero(val: i32) -> i32 { #[cfg(cfail1)] @@ -107,7 +107,7 @@ pub fn division_by_zero(val: i32) -> i32 { } // Division by zero -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn mod_by_zero(val: i32) -> i32 { #[cfg(cfail1)] @@ -122,7 +122,7 @@ pub fn mod_by_zero(val: i32) -> i32 { // shift left -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_left(val: i32, shift: usize) -> i32 { #[cfg(cfail1)] @@ -137,7 +137,7 @@ pub fn shift_left(val: i32, shift: usize) -> i32 { // shift right -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_right(val: i32, shift: usize) -> i32 { #[cfg(cfail1)] diff --git a/tests/incremental/hashes/statics.rs b/tests/incremental/hashes/statics.rs index 2adf05390bc4e..7e2ccc4ce6f20 100644 --- a/tests/incremental/hashes/statics.rs +++ b/tests/incremental/hashes/statics.rs @@ -26,7 +26,7 @@ static STATIC_VISIBILITY: u8 = 0; #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub static STATIC_VISIBILITY: u8 = 0; @@ -36,9 +36,9 @@ pub static STATIC_VISIBILITY: u8 = 0; static STATIC_MUTABILITY: u8 = 0; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static mut STATIC_MUTABILITY: u8 = 0; @@ -87,9 +87,9 @@ static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_CHANGE_TYPE_1: i16 = 0; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_1: u64 = 0; @@ -99,17 +99,17 @@ static STATIC_CHANGE_TYPE_1: u64 = 0; static STATIC_CHANGE_TYPE_2: Option = None; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_2: Option = None; // Change value between simple literals -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_1: i16 = { #[cfg(any(cfail1,cfail4))] @@ -121,9 +121,9 @@ static STATIC_CHANGE_VALUE_1: i16 = { // Change value between expressions -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_2: i16 = { #[cfg(any(cfail1,cfail4))] @@ -133,9 +133,9 @@ static STATIC_CHANGE_VALUE_2: i16 = { { 1 + 2 } }; -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_3: i16 = { #[cfg(any(cfail1,cfail4))] @@ -145,9 +145,9 @@ static STATIC_CHANGE_VALUE_3: i16 = { { 2 * 3 } }; -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_4: i16 = { #[cfg(any(cfail1,cfail4))] @@ -169,15 +169,15 @@ mod static_change_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/tests/incremental/hashes/struct_constructors.rs b/tests/incremental/hashes/struct_constructors.rs index eabb8683e0296..458f4d1a6d7de 100644 --- a/tests/incremental/hashes/struct_constructors.rs +++ b/tests/incremental/hashes/struct_constructors.rs @@ -34,9 +34,9 @@ pub fn change_field_value_regular_struct() -> RegularStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_field_value_regular_struct() -> RegularStruct { RegularStruct { @@ -59,9 +59,9 @@ pub fn change_field_order_regular_struct() -> RegularStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_field_order_regular_struct() -> RegularStruct { RegularStruct { @@ -90,9 +90,9 @@ pub fn add_field_regular_struct() -> RegularStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_field_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -127,9 +127,9 @@ pub fn change_field_label_regular_struct() -> RegularStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_field_label_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -164,9 +164,9 @@ pub fn change_constructor_path_regular_struct() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_regular_struct() { let _ = RegularStruct2 { @@ -185,9 +185,9 @@ pub mod change_constructor_path_indirectly_regular_struct { #[cfg(not(any(cfail1,cfail4)))] use super::RegularStruct2 as Struct; - #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> Struct { Struct { @@ -209,9 +209,9 @@ pub fn change_field_value_tuple_struct() -> TupleStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_field_value_tuple_struct() -> TupleStruct { TupleStruct(0, 1, 3) @@ -228,9 +228,9 @@ pub fn change_constructor_path_tuple_struct() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_tuple_struct() { let _ = TupleStruct2(0, 1, 2); @@ -245,9 +245,9 @@ pub mod change_constructor_path_indirectly_tuple_struct { #[cfg(not(any(cfail1,cfail4)))] use super::TupleStruct2 as Struct; - #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] - #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] pub fn function() -> Struct { Struct(0, 1, 2) diff --git a/tests/incremental/hashes/struct_defs.rs b/tests/incremental/hashes/struct_defs.rs index 6ea4d890e4d54..113ada2855d1e 100644 --- a/tests/incremental/hashes/struct_defs.rs +++ b/tests/incremental/hashes/struct_defs.rs @@ -51,9 +51,9 @@ struct LayoutC; struct TupleStructFieldType(i32); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] // Note that changing the type of a field does not change the type of the struct or enum, but // adding/removing fields or changing a fields name or visibility does. @@ -68,9 +68,9 @@ struct TupleStructFieldType( struct TupleStructAddField(i32); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct TupleStructAddField( i32, @@ -86,7 +86,7 @@ struct TupleStructFieldVisibility( char); #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] struct TupleStructFieldVisibility(pub char); @@ -97,9 +97,9 @@ struct TupleStructFieldVisibility(pub char); struct RecordStructFieldType { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] // Note that changing the type of a field does not change the type of the struct or enum, but // adding/removing fields or changing a fields name or visibility does. @@ -114,9 +114,9 @@ struct RecordStructFieldType { struct RecordStructFieldName { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStructFieldName { y: f32 } @@ -127,9 +127,9 @@ struct RecordStructFieldName { y: f32 } struct RecordStructAddField { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStructAddField { x: f32, @@ -144,7 +144,7 @@ struct RecordStructFieldVisibility { x: f32 } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] struct RecordStructFieldVisibility { pub x: f32 } @@ -155,9 +155,9 @@ struct RecordStructFieldVisibility { pub x: f32 } struct AddLifetimeParameter<'a>(&'a f32, &'a f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,type_of,generics_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,type_of,generics_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64); @@ -168,9 +168,9 @@ struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64); struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameterBound<'a, 'b: 'a>( &'a f32, @@ -181,9 +181,9 @@ struct AddLifetimeParameterBound<'a, 'b: 'a>( struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameterBoundWhereClause<'a, 'b>( &'a f32, @@ -197,9 +197,9 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>( struct AddTypeParameter(T1, T1); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameter( // The field contains the parent's Generics, so it's dirty even though its @@ -215,9 +215,9 @@ struct AddTypeParameter( struct AddTypeParameterBound(T); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameterBound( T @@ -228,9 +228,9 @@ struct AddTypeParameterBound( struct AddTypeParameterBoundWhereClause(T); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameterBoundWhereClause( T @@ -257,7 +257,7 @@ struct Visibility; #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub struct Visibility; @@ -271,9 +271,9 @@ mod tuple_struct_change_field_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct TupleStruct( FieldType @@ -288,9 +288,9 @@ mod record_struct_change_field_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStruct { _x: FieldType @@ -310,9 +310,9 @@ mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct Struct(T); } @@ -324,9 +324,9 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct Struct(T) where T : Trait; } diff --git a/tests/incremental/hashes/trait_defs.rs b/tests/incremental/hashes/trait_defs.rs index 0a5eba7397722..49c388600de05 100644 --- a/tests/incremental/hashes/trait_defs.rs +++ b/tests/incremental/hashes/trait_defs.rs @@ -30,7 +30,7 @@ trait TraitVisibility { } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub trait TraitVisibility { } @@ -41,9 +41,9 @@ pub trait TraitVisibility { } trait TraitUnsafety { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] unsafe trait TraitUnsafety { } @@ -55,9 +55,9 @@ trait TraitAddMethod { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait TraitAddMethod { fn method(); @@ -72,9 +72,9 @@ trait TraitChangeMethodName { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodName { fn methodChanged(); @@ -85,9 +85,9 @@ trait TraitChangeMethodName { // Add return type to method #[cfg(any(cfail1,cfail4))] trait TraitAddReturnType { - //----------------------------------------------------------- + //--------------------------------------------------------------- //-------------------------- - //----------------------------------------------------------- + //--------------------------------------------------------------- //-------------------------- fn method() ; } @@ -98,9 +98,9 @@ trait TraitAddReturnType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddReturnType { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> u32; } @@ -110,9 +110,9 @@ trait TraitAddReturnType { // Change return type of method #[cfg(any(cfail1,cfail4))] trait TraitChangeReturnType { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method() -> u32; } @@ -123,9 +123,9 @@ trait TraitChangeReturnType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeReturnType { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> u64; } @@ -135,9 +135,9 @@ trait TraitChangeReturnType { // Add parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddParameterToMethod { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method( ); } @@ -148,9 +148,9 @@ trait TraitAddParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddParameterToMethod { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: u32); } @@ -161,15 +161,15 @@ trait TraitAddParameterToMethod { #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterName { //------------------------------------------------------ - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- fn method(a: u32); - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- fn with_default(x: i32) {} } @@ -181,15 +181,15 @@ trait TraitChangeMethodParameterName { #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterName { // FIXME(#38501) This should preferably always be clean. - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(b: u32); - #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn with_default(y: i32) {} } @@ -199,9 +199,9 @@ trait TraitChangeMethodParameterName { // Change type of method parameter (i32 => i64) #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterType { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(a: i32); } @@ -212,9 +212,9 @@ trait TraitChangeMethodParameterType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterType { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: i64); } @@ -224,9 +224,9 @@ trait TraitChangeMethodParameterType { // Change type of method parameter (&i32 => &mut i32) #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterTypeRef { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(a: & i32); } @@ -237,9 +237,9 @@ trait TraitChangeMethodParameterTypeRef { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterTypeRef { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: &mut i32); } @@ -249,9 +249,9 @@ trait TraitChangeMethodParameterTypeRef { // Change order of method parameters #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParametersOrder { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(a: i32, b: i64); } @@ -262,9 +262,9 @@ trait TraitChangeMethodParametersOrder { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParametersOrder { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(b: i64, a: i32); } @@ -274,9 +274,9 @@ trait TraitChangeMethodParametersOrder { // Add default implementation to method #[cfg(any(cfail1,cfail4))] trait TraitAddMethodAutoImplementation { - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- fn method() ; } @@ -287,9 +287,9 @@ trait TraitAddMethodAutoImplementation { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddMethodAutoImplementation { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() {} } @@ -304,9 +304,9 @@ trait TraitChangeOrderOfMethods { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeOrderOfMethods { fn method1(); @@ -318,9 +318,9 @@ trait TraitChangeOrderOfMethods { // Change mode of self parameter #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfRefToMut { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(& self); } @@ -331,9 +331,9 @@ trait TraitChangeModeSelfRefToMut { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfRefToMut { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(&mut self); } @@ -342,9 +342,9 @@ trait TraitChangeModeSelfRefToMut { #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfOwnToMut: Sized { - // ------------------------------------------------------------------------ + // ---------------------------------------------------------------------------- // ------------------------- - // ------------------------------------------------------------------------ + // ---------------------------------------------------------------------------- // ------------------------- fn method( self) {} } @@ -355,9 +355,9 @@ trait TraitChangeModeSelfOwnToMut: Sized { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfOwnToMut: Sized { - #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(mut self) {} } @@ -366,9 +366,9 @@ trait TraitChangeModeSelfOwnToMut: Sized { #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfOwnToRef { - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // ------------------------- fn method( self); } @@ -379,9 +379,9 @@ trait TraitChangeModeSelfOwnToRef { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfOwnToRef { - #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(&self); } @@ -391,9 +391,9 @@ trait TraitChangeModeSelfOwnToRef { // Add unsafe modifier to method #[cfg(any(cfail1,cfail4))] trait TraitAddUnsafeModifier { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(); } @@ -404,9 +404,9 @@ trait TraitAddUnsafeModifier { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddUnsafeModifier { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] unsafe fn method(); } @@ -416,9 +416,9 @@ trait TraitAddUnsafeModifier { // Add extern modifier to method #[cfg(any(cfail1,cfail4))] trait TraitAddExternModifier { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(); } @@ -429,9 +429,9 @@ trait TraitAddExternModifier { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddExternModifier { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] extern "C" fn method(); } @@ -441,9 +441,9 @@ trait TraitAddExternModifier { // Change extern "C" to extern "stdcall" #[cfg(any(cfail1,cfail4))] trait TraitChangeExternCToRustIntrinsic { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- extern "C" fn method(); } @@ -454,9 +454,9 @@ trait TraitChangeExternCToRustIntrinsic { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeExternCToRustIntrinsic { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] extern "stdcall" fn method(); } @@ -466,10 +466,10 @@ trait TraitChangeExternCToRustIntrinsic { // Add type parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddTypeParameterToMethod { - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // --------------- // ------------------------- - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // --------------- // ------------------------- fn method (); @@ -481,10 +481,10 @@ trait TraitAddTypeParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTypeParameterToMethod { - #[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of,type_of", + #[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of,type_of", + #[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); @@ -495,9 +495,9 @@ trait TraitAddTypeParameterToMethod { // Add lifetime parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeParameterToMethod { - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // ------------------------- fn method (); } @@ -508,9 +508,9 @@ trait TraitAddLifetimeParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeParameterToMethod { - #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method<'a>(); } @@ -524,9 +524,9 @@ trait ReferencedTrait1 { } // Add trait bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToMethodTypeParameter { - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- fn method(); } @@ -537,9 +537,9 @@ trait TraitAddTraitBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -549,9 +549,9 @@ trait TraitAddTraitBoundToMethodTypeParameter { // Add builtin bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddBuiltinBoundToMethodTypeParameter { - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- fn method(); } @@ -562,9 +562,9 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -575,12 +575,12 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToMethodLifetimeParameter { // ----------- - // ------------------------------------------------------------------- + // ----------------------------------------------------------------------- // -------------- // // ------------------------- // ----------- - // ------------------------------------------------------------------- + // ----------------------------------------------------------------------- // -------------- // // ------------------------- @@ -594,12 +594,12 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToMethodLifetimeParameter { #[rustc_clean( - except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -611,9 +611,9 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { // Add second trait bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddSecondTraitBoundToMethodTypeParameter { - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- fn method(); } @@ -624,9 +624,9 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -636,9 +636,9 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { // Add second builtin bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- fn method(); } @@ -649,9 +649,9 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -662,12 +662,12 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { #[cfg(any(cfail1,cfail4))] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { // ----------- - // ------------------------------------------------------------------- + // ----------------------------------------------------------------------- // -------------- // // ------------------------- // ----------- - // ------------------------------------------------------------------- + // ----------------------------------------------------------------------- // -------------- // // ------------------------- @@ -681,12 +681,12 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[rustc_clean( - except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -710,9 +710,9 @@ trait TraitAddAssociatedType { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddAssociatedType { #[rustc_clean(cfg="cfail3")] @@ -731,9 +731,9 @@ trait TraitAddAssociatedType { // Add trait bound to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToAssociatedType { - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- type Associated ; @@ -749,9 +749,9 @@ trait TraitAddTraitBoundToAssociatedType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToAssociatedType { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated: ReferencedTrait0; @@ -763,9 +763,9 @@ trait TraitAddTraitBoundToAssociatedType { // Add lifetime bound to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToAssociatedType<'a> { - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- type Associated ; @@ -778,9 +778,9 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToAssociatedType<'a> { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated: 'a; @@ -792,9 +792,9 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { // Add default to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddDefaultToAssociatedType { - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- type Associated ; @@ -807,9 +807,9 @@ trait TraitAddDefaultToAssociatedType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddDefaultToAssociatedType { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated = ReferenceType0; @@ -825,9 +825,9 @@ trait TraitAddAssociatedConstant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddAssociatedConstant { const Value: u32; @@ -840,9 +840,9 @@ trait TraitAddAssociatedConstant { // Add initializer to associated constant #[cfg(any(cfail1,cfail4))] trait TraitAddInitializerToAssociatedConstant { - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- const Value: u32 ; @@ -859,9 +859,9 @@ trait TraitAddInitializerToAssociatedConstant { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddInitializerToAssociatedConstant { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] const Value: u32 = 1; @@ -877,9 +877,9 @@ trait TraitAddInitializerToAssociatedConstant { // Change type of associated constant #[cfg(any(cfail1,cfail4))] trait TraitChangeTypeOfAssociatedConstant { - // ----------------------------------------------------------- + // --------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------- + // --------------------------------------------------------------- // ------------------------- const Value: u32; @@ -896,9 +896,9 @@ trait TraitChangeTypeOfAssociatedConstant { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTypeOfAssociatedConstant { - #[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] const Value: f64; @@ -916,9 +916,9 @@ trait TraitChangeTypeOfAssociatedConstant { trait TraitAddSuperTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSuperTrait : ReferencedTrait0 { } @@ -929,9 +929,9 @@ trait TraitAddSuperTrait : ReferencedTrait0 { } trait TraitAddBuiltiBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltiBound : Send { } @@ -942,9 +942,9 @@ trait TraitAddBuiltiBound : Send { } trait TraitAddStaticLifetimeBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticLifetimeBound : 'static { } @@ -955,9 +955,9 @@ trait TraitAddStaticLifetimeBound : 'static { } trait TraitAddTraitAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { } @@ -965,9 +965,9 @@ trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { } trait TraitAddTraitAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } @@ -978,9 +978,9 @@ trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { } @@ -988,9 +988,9 @@ trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { } trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } @@ -1001,9 +1001,9 @@ trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { } @@ -1011,9 +1011,9 @@ trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { } trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } @@ -1024,9 +1024,9 @@ trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } trait TraitAddTypeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTypeParameterToTrait { } @@ -1037,9 +1037,9 @@ trait TraitAddTypeParameterToTrait { } trait TraitAddLifetimeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeParameterToTrait<'a> { } @@ -1050,9 +1050,9 @@ trait TraitAddLifetimeParameterToTrait<'a> { } trait TraitAddTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToTypeParameterOfTrait { } @@ -1063,9 +1063,9 @@ trait TraitAddTraitBoundToTypeParameterOfTrait { } trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } @@ -1076,9 +1076,9 @@ trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } @@ -1089,9 +1089,9 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } trait TraitAddBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToTypeParameterOfTrait { } @@ -1102,9 +1102,9 @@ trait TraitAddBuiltinBoundToTypeParameterOfTrait { } trait TraitAddSecondTypeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTypeParameterToTrait { } @@ -1115,9 +1115,9 @@ trait TraitAddSecondTypeParameterToTrait { } trait TraitAddSecondLifetimeParameterToTrait<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } @@ -1128,9 +1128,9 @@ trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } @@ -1141,9 +1141,9 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } @@ -1154,9 +1154,9 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { } @@ -1167,9 +1167,9 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } @@ -1185,9 +1185,9 @@ struct ReferenceType1 {} trait TraitAddTraitBoundToTypeParameterOfTraitWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } @@ -1198,9 +1198,9 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } @@ -1211,9 +1211,9 @@ trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { } @@ -1224,9 +1224,9 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } @@ -1237,9 +1237,9 @@ trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 + ReferencedTrait1 { } @@ -1251,9 +1251,9 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { } @@ -1264,9 +1264,9 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { } @@ -1277,9 +1277,9 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> whe trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send + Sync { } @@ -1296,9 +1296,9 @@ mod change_return_type_of_method_indirectly_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeReturnType { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> ReturnType; } @@ -1318,9 +1318,9 @@ mod change_method_parameter_type_indirectly_by_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeArgType { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: ArgType); } @@ -1340,9 +1340,9 @@ mod change_method_parameter_type_bound_indirectly_by_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeBoundOfMethodTypeParameter { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: T); } @@ -1363,9 +1363,9 @@ mod change_method_parameter_type_bound_indirectly_by_use_where { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeBoundOfMethodTypeParameterWhere { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: T) where T: Bound; } @@ -1380,9 +1380,9 @@ mod change_method_type_parameter_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTraitBound { fn method(a: T); @@ -1399,9 +1399,9 @@ mod change_method_type_parameter_bound_indirectly_where { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTraitBoundWhere where T: Bound { fn method(a: T); diff --git a/tests/incremental/hashes/trait_impls.rs b/tests/incremental/hashes/trait_impls.rs index 028598244de73..2e97a35d36bb7 100644 --- a/tests/incremental/hashes/trait_impls.rs +++ b/tests/incremental/hashes/trait_impls.rs @@ -32,9 +32,9 @@ impl ChangeMethodNameTrait for Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait ChangeMethodNameTrait { #[rustc_clean(cfg="cfail3")] @@ -43,9 +43,9 @@ pub trait ChangeMethodNameTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodNameTrait for Foo { #[rustc_clean(cfg="cfail3")] @@ -63,9 +63,9 @@ pub trait ChangeMethodBodyTrait { #[cfg(any(cfail1,cfail4))] impl ChangeMethodBodyTrait for Foo { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method_name() { // @@ -78,9 +78,9 @@ impl ChangeMethodBodyTrait for Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodBodyTrait for Foo { - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name() { () @@ -97,9 +97,9 @@ pub trait ChangeMethodBodyTraitInlined { #[cfg(any(cfail1,cfail4))] impl ChangeMethodBodyTraitInlined for Foo { - // ------------------------------------------------------------------------ + // ---------------------------------------------------------------------------- // ------------------------- - // ------------------------------------------------------------------------ + // ---------------------------------------------------------------------------- // ------------------------- #[inline] fn method_name() { @@ -113,9 +113,9 @@ impl ChangeMethodBodyTraitInlined for Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodBodyTraitInlined for Foo { - #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] #[inline] fn method_name() { @@ -141,18 +141,18 @@ pub trait ChangeMethodSelfnessTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodSelfnessTrait for Foo { #[rustc_clean( - except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="opt_hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="opt_hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -179,18 +179,18 @@ pub trait RemoveMethodSelfnessTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl RemoveMethodSelfnessTrait for Foo { #[rustc_clean( - except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="opt_hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="opt_hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -206,9 +206,9 @@ pub trait ChangeMethodSelfmutnessTrait { #[cfg(any(cfail1,cfail4))] impl ChangeMethodSelfmutnessTrait for Foo { - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- fn method_name(& self) {} } @@ -224,9 +224,9 @@ pub trait ChangeMethodSelfmutnessTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodSelfmutnessTrait for Foo { - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&mut self) {} } @@ -249,9 +249,9 @@ pub trait ChangeItemKindTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeItemKindTrait for Foo { type name = (); @@ -277,9 +277,9 @@ pub trait RemoveItemTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl RemoveItemTrait for Foo { type TypeName = (); @@ -304,9 +304,9 @@ pub trait AddItemTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddItemTrait for Foo { type TypeName = (); @@ -317,9 +317,9 @@ impl AddItemTrait for Foo { #[cfg(any(cfail1,cfail4))] pub trait ChangeHasValueTrait { - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- fn method_name() ; } @@ -335,9 +335,9 @@ impl ChangeHasValueTrait for Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait ChangeHasValueTrait { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name() { } } @@ -359,9 +359,9 @@ pub trait AddDefaultTrait { #[cfg(any(cfail1,cfail4))] impl AddDefaultTrait for Foo { - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- fn method_name() { } } @@ -372,9 +372,9 @@ impl AddDefaultTrait for Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddDefaultTrait for Foo { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] default fn method_name() { } } @@ -388,9 +388,9 @@ pub trait AddArgumentTrait { #[cfg(any(cfail1,cfail4))] impl AddArgumentTrait for Foo { - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- fn method_name(&self ) { } } @@ -406,9 +406,9 @@ pub trait AddArgumentTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddArgumentTrait for Foo { - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&self, _x: u32) { } } @@ -422,9 +422,9 @@ pub trait ChangeArgumentTypeTrait { #[cfg(any(cfail1,cfail4))] impl ChangeArgumentTypeTrait for Foo { - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- fn method_name(&self, _x: u32 ) { } } @@ -440,9 +440,9 @@ pub trait ChangeArgumentTypeTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeArgumentTypeTrait for Foo { - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&self, _x: char) { } } @@ -462,18 +462,18 @@ impl AddTypeParameterToImpl for Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddTypeParameterToImpl for Bar { #[rustc_clean( - except="hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", + except="opt_hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", + except="opt_hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -493,9 +493,9 @@ impl ChangeSelfTypeOfImpl for u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,impl_trait_ref", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_ref", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_ref", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeSelfTypeOfImpl for u64 { #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")] @@ -518,9 +518,9 @@ impl AddLifetimeBoundToImplParameter for T { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddLifetimeBoundToImplParameter for T { #[rustc_clean(cfg="cfail2")] @@ -543,9 +543,9 @@ impl AddTraitBoundToImplParameter for T { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddTraitBoundToImplParameter for T { #[rustc_clean(cfg="cfail2")] diff --git a/tests/incremental/hashes/type_defs.rs b/tests/incremental/hashes/type_defs.rs index 206c0595d5464..6b0dac1fe69b5 100644 --- a/tests/incremental/hashes/type_defs.rs +++ b/tests/incremental/hashes/type_defs.rs @@ -24,7 +24,7 @@ type ChangePrimitiveType = i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangePrimitiveType = i64; @@ -35,7 +35,7 @@ type ChangePrimitiveType = i64; type ChangeMutability = &'static i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeMutability = &'static mut i32; @@ -46,7 +46,7 @@ type ChangeMutability = &'static mut i32; type ChangeLifetime<'a> = (&'static i32, &'a i32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeLifetime<'a> = (&'a i32, &'a i32); @@ -60,7 +60,7 @@ struct Struct2; type ChangeTypeStruct = Struct1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeStruct = Struct2; @@ -71,7 +71,7 @@ type ChangeTypeStruct = Struct2; type ChangeTypeTuple = (u32, u64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeTuple = (u32, i64); @@ -91,7 +91,7 @@ enum Enum2 { type ChangeTypeEnum = Enum1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeEnum = Enum2; @@ -102,7 +102,7 @@ type ChangeTypeEnum = Enum2; type AddTupleField = (i32, i64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTupleField = (i32, i64, i16); @@ -113,7 +113,7 @@ type AddTupleField = (i32, i64, i16); type ChangeNestedTupleField = (i32, (i64, i16)); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeNestedTupleField = (i32, (i64, i8)); @@ -124,7 +124,7 @@ type ChangeNestedTupleField = (i32, (i64, i8)); type AddTypeParam = (T1, T1); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParam = (T1, T2); @@ -135,7 +135,7 @@ type AddTypeParam = (T1, T2); type AddTypeParamBound = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBound = (T1, u32); @@ -146,7 +146,7 @@ type AddTypeParamBound = (T1, u32); type AddTypeParamBoundWhereClause where T1: Clone = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); @@ -157,7 +157,7 @@ type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); type AddLifetimeParam<'a> = (&'a u32, &'a u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); @@ -168,7 +168,7 @@ type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); type AddLifetimeParamBound<'a, 'b> = (&'a u32, &'b u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBound<'a, 'b: 'a> = (&'a u32, &'b u32); @@ -181,7 +181,7 @@ where 'b: 'a = (&'a u32, &'b u32, &'c u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBoundWhereClause<'a, 'b, 'c> where 'b: 'a, @@ -200,7 +200,7 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly = (T, u32); } @@ -214,7 +214,7 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly where T : Trait = (T, u32); } diff --git a/tests/incremental/hashes/unary_and_binary_exprs.rs b/tests/incremental/hashes/unary_and_binary_exprs.rs index 58af51eef077f..3d48f2d28a37b 100644 --- a/tests/incremental/hashes/unary_and_binary_exprs.rs +++ b/tests/incremental/hashes/unary_and_binary_exprs.rs @@ -24,9 +24,9 @@ pub fn const_negation() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn const_negation() -> i32 { -1 @@ -41,9 +41,9 @@ pub fn const_bitwise_not() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn const_bitwise_not() -> i32 { !99 @@ -58,9 +58,9 @@ pub fn var_negation(x: i32, y: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn var_negation(x: i32, y: i32) -> i32 { -y @@ -75,9 +75,9 @@ pub fn var_bitwise_not(x: i32, y: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn var_bitwise_not(x: i32, y: i32) -> i32 { !y @@ -92,9 +92,9 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn var_deref(x: &i32, y: &i32) -> i32 { *y @@ -109,9 +109,9 @@ pub fn first_const_add() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn first_const_add() -> i32 { 2 + 3 @@ -126,9 +126,9 @@ pub fn second_const_add() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn second_const_add() -> i32 { 1 + 3 @@ -143,9 +143,9 @@ pub fn first_var_add(a: i32, b: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn first_var_add(a: i32, b: i32) -> i32 { b + 2 @@ -160,9 +160,9 @@ pub fn second_var_add(a: i32, b: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn second_var_add(a: i32, b: i32) -> i32 { 1 + b @@ -177,9 +177,9 @@ pub fn plus_to_minus(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn plus_to_minus(a: i32) -> i32 { 1 - a @@ -194,9 +194,9 @@ pub fn plus_to_mult(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn plus_to_mult(a: i32) -> i32 { 1 * a @@ -211,9 +211,9 @@ pub fn plus_to_div(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn plus_to_div(a: i32) -> i32 { 1 / a @@ -228,9 +228,9 @@ pub fn plus_to_mod(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn plus_to_mod(a: i32) -> i32 { 1 % a @@ -245,9 +245,9 @@ pub fn and_to_or(a: bool, b: bool) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn and_to_or(a: bool, b: bool) -> bool { a || b @@ -262,9 +262,9 @@ pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 { 1 | a @@ -279,9 +279,9 @@ pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 { 1 ^ a @@ -296,9 +296,9 @@ pub fn bitwise_and_to_lshift(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_lshift(a: i32) -> i32 { a << 1 @@ -313,9 +313,9 @@ pub fn bitwise_and_to_rshift(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_rshift(a: i32) -> i32 { a >> 1 @@ -330,9 +330,9 @@ pub fn eq_to_uneq(a: i32) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn eq_to_uneq(a: i32) -> bool { a != 1 @@ -347,9 +347,9 @@ pub fn eq_to_lt(a: i32) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn eq_to_lt(a: i32) -> bool { a < 1 @@ -364,9 +364,9 @@ pub fn eq_to_gt(a: i32) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn eq_to_gt(a: i32) -> bool { a > 1 @@ -381,9 +381,9 @@ pub fn eq_to_le(a: i32) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn eq_to_le(a: i32) -> bool { a <= 1 @@ -398,9 +398,9 @@ pub fn eq_to_ge(a: i32) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn eq_to_ge(a: i32) -> bool { a >= 1 @@ -417,9 +417,9 @@ pub fn type_cast(a: u8) -> u64 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn type_cast(a: u8) -> u64 { let b = a as u32; @@ -436,9 +436,9 @@ pub fn value_cast(a: u32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn value_cast(a: u32) -> i32 { 2 as i32 @@ -456,9 +456,9 @@ pub fn place() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn place() -> i32 { let mut x = 10; @@ -478,9 +478,9 @@ pub fn rvalue() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn rvalue() -> i32 { let mut x = 10; @@ -497,9 +497,9 @@ pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 { s[j] diff --git a/tests/incremental/hashes/while_let_loops.rs b/tests/incremental/hashes/while_let_loops.rs index c81b0d0afb811..64ba3f6e7ef83 100644 --- a/tests/incremental/hashes/while_let_loops.rs +++ b/tests/incremental/hashes/while_let_loops.rs @@ -28,9 +28,9 @@ pub fn change_loop_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; @@ -53,9 +53,9 @@ pub fn change_loop_condition() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_condition() { let mut _x = 0; @@ -78,9 +78,9 @@ pub fn add_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; @@ -103,9 +103,9 @@ pub fn add_loop_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label() { let mut _x = 0; @@ -128,9 +128,9 @@ pub fn add_loop_label_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -155,9 +155,9 @@ pub fn change_break_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; @@ -180,9 +180,9 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -207,9 +207,9 @@ pub fn change_continue_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; @@ -234,9 +234,9 @@ pub fn change_continue_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/tests/incremental/hashes/while_loops.rs b/tests/incremental/hashes/while_loops.rs index 077d76fdd43a1..534f61b84bdee 100644 --- a/tests/incremental/hashes/while_loops.rs +++ b/tests/incremental/hashes/while_loops.rs @@ -28,9 +28,9 @@ pub fn change_loop_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; @@ -53,9 +53,9 @@ pub fn change_loop_condition() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_condition() { let mut _x = 0; @@ -78,9 +78,9 @@ pub fn add_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; @@ -103,9 +103,9 @@ pub fn add_loop_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label() { let mut _x = 0; @@ -128,9 +128,9 @@ pub fn add_loop_label_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -155,9 +155,9 @@ pub fn change_break_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; @@ -182,9 +182,9 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -209,9 +209,9 @@ pub fn change_continue_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; @@ -236,9 +236,9 @@ pub fn change_continue_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/tests/incremental/hygiene/auxiliary/cached_hygiene.rs b/tests/incremental/hygiene/auxiliary/cached_hygiene.rs index b31f60e972bf0..c1fd47cb2bb46 100644 --- a/tests/incremental/hygiene/auxiliary/cached_hygiene.rs +++ b/tests/incremental/hygiene/auxiliary/cached_hygiene.rs @@ -13,7 +13,7 @@ macro_rules! first_macro { } } -#[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir,promoted_mir", cfg="rpass2")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck,optimized_mir,promoted_mir", cfg="rpass2")] #[inline(always)] pub fn changed_fn() { // This will cause additional hygiene to be generate, diff --git a/tests/incremental/ich_nested_items.rs b/tests/incremental/ich_nested_items.rs index 379c09575edfb..f0310e94015c0 100644 --- a/tests/incremental/ich_nested_items.rs +++ b/tests/incremental/ich_nested_items.rs @@ -8,7 +8,7 @@ #![crate_type = "rlib"] #![feature(rustc_attrs)] -#[rustc_clean(except = "hir_owner_nodes", cfg = "cfail2")] +#[rustc_clean(except = "opt_hir_owner_nodes", cfg = "cfail2")] pub fn foo() { #[cfg(cfail1)] pub fn baz() {} // order is different... diff --git a/tests/incremental/ich_resolve_results.rs b/tests/incremental/ich_resolve_results.rs index e6ab6bcebae09..9b5afcd801216 100644 --- a/tests/incremental/ich_resolve_results.rs +++ b/tests/incremental/ich_resolve_results.rs @@ -30,13 +30,13 @@ mod mod3 { use mod2::Foo; #[rustc_clean(cfg="rpass2")] - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="rpass3")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="rpass3")] fn in_expr() { Foo(0); } #[rustc_clean(cfg="rpass2")] - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="rpass3")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="rpass3")] fn in_type() { test::(); } diff --git a/tests/incremental/source_loc_macros.rs b/tests/incremental/source_loc_macros.rs index e5f04e5dc5818..16ad4d1899e94 100644 --- a/tests/incremental/source_loc_macros.rs +++ b/tests/incremental/source_loc_macros.rs @@ -22,7 +22,7 @@ fn file_same() { let _ = file!(); } -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="rpass2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="rpass2")] fn line_different() { #[cfg(rpass1)] { @@ -34,7 +34,7 @@ fn line_different() { } } -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="rpass2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="rpass2")] fn col_different() { #[cfg(rpass1)] { diff --git a/tests/incremental/string_constant.rs b/tests/incremental/string_constant.rs index 47cd100b13691..325b200e69b49 100644 --- a/tests/incremental/string_constant.rs +++ b/tests/incremental/string_constant.rs @@ -17,7 +17,7 @@ pub mod x { } #[cfg(cfail2)] - #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail2")] + #[rustc_clean(except = "opt_hir_owner_nodes,promoted_mir", cfg = "cfail2")] pub fn x() { println!("{}", "2"); } From 667d5d325f7657e5cdf1cade84e2602c5ebb9a8d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 25 Jan 2024 19:34:49 +0300 Subject: [PATCH 114/246] hir: Add non-optional `hir_owner_nodes` for real `OwnerId`s --- compiler/rustc_middle/src/hir/map/mod.rs | 93 +++++++++++-------- .../rustc_mir_transform/src/coverage/mod.rs | 7 +- .../clippy_lints/src/min_ident_chars.rs | 4 +- 3 files changed, 55 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index db73e1b936b6b..5811dae1b5883 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -107,9 +107,8 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { fn next(&mut self) -> Option { if self.current_id.local_id.index() != 0 { self.current_id.local_id = ItemLocalId::new(0); - if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { - return Some((self.current_id.owner, node)); - } + let node = self.map.tcx.hir_owner_node(self.current_id.owner); + return Some((self.current_id.owner, node)); } if self.current_id == CRATE_HIR_ID { return None; @@ -125,22 +124,42 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { self.current_id = HirId::make_owner(parent_id.def_id); // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`. - if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { - return Some((self.current_id.owner, node)); - } + let node = self.map.tcx.hir_owner_node(self.current_id.owner); + return Some((self.current_id.owner, node)); } } } impl<'tcx> TyCtxt<'tcx> { #[inline] - fn hir_owner(self, owner: OwnerId) -> Option> { - Some(self.opt_hir_owner_nodes(owner.def_id)?.node()) + fn expect_hir_owner_nodes(self, def_id: LocalDefId) -> &'tcx OwnerNodes<'tcx> { + self.opt_hir_owner_nodes(def_id) + .unwrap_or_else(|| span_bug!(self.def_span(def_id), "{def_id:?} is not an owner")) + } + + #[inline] + pub fn hir_owner_nodes(self, owner_id: OwnerId) -> &'tcx OwnerNodes<'tcx> { + self.expect_hir_owner_nodes(owner_id.def_id) + } + + #[inline] + fn opt_hir_owner_node(self, def_id: LocalDefId) -> Option> { + self.opt_hir_owner_nodes(def_id).map(|nodes| nodes.node()) + } + + #[inline] + fn expect_hir_owner_node(self, def_id: LocalDefId) -> OwnerNode<'tcx> { + self.expect_hir_owner_nodes(def_id).node() + } + + #[inline] + fn hir_owner_node(self, owner_id: OwnerId) -> OwnerNode<'tcx> { + self.hir_owner_nodes(owner_id).node() } /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. pub fn opt_hir_node(self, id: HirId) -> Option> { - let owner = self.opt_hir_owner_nodes(id.owner)?; + let owner = self.hir_owner_nodes(id.owner); let node = owner.nodes[id.local_id].as_ref()?; Some(node.node) } @@ -174,8 +193,8 @@ impl<'hir> Map<'hir> { #[inline] pub fn root_module(self) -> &'hir Mod<'hir> { - match self.tcx.hir_owner(CRATE_OWNER_ID) { - Some(OwnerNode::Crate(item)) => item, + match self.tcx.hir_owner_node(CRATE_OWNER_ID) { + OwnerNode::Crate(item) => item, _ => bug!(), } } @@ -213,7 +232,7 @@ impl<'hir> Map<'hir> { if id.local_id == ItemLocalId::from_u32(0) { Some(self.tcx.hir_owner_parent(id.owner)) } else { - let owner = self.tcx.opt_hir_owner_nodes(id.owner)?; + let owner = self.tcx.hir_owner_nodes(id.owner); let node = owner.nodes[id.local_id].as_ref()?; let hir_id = HirId { owner: id.owner, local_id: node.parent }; // HIR indexing should have checked that. @@ -241,32 +260,31 @@ impl<'hir> Map<'hir> { } pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { - let node = self.tcx.hir_owner(OwnerId { def_id: id })?; - node.generics() + self.tcx.opt_hir_owner_node(id)?.generics() } pub fn owner(self, id: OwnerId) -> OwnerNode<'hir> { - self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)) + self.tcx.hir_owner_node(id) } pub fn item(self, id: ItemId) -> &'hir Item<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().expect_item() + self.tcx.hir_owner_node(id.owner_id).expect_item() } pub fn trait_item(self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().expect_trait_item() + self.tcx.hir_owner_node(id.owner_id).expect_trait_item() } pub fn impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().expect_impl_item() + self.tcx.hir_owner_node(id.owner_id).expect_impl_item() } pub fn foreign_item(self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().expect_foreign_item() + self.tcx.hir_owner_node(id.owner_id).expect_foreign_item() } pub fn body(self, id: BodyId) -> &'hir Body<'hir> { - self.tcx.opt_hir_owner_nodes(id.hir_id.owner).unwrap().bodies[&id.hir_id.local_id] + self.tcx.hir_owner_nodes(id.hir_id.owner).bodies[&id.hir_id.local_id] } #[track_caller] @@ -436,9 +454,9 @@ impl<'hir> Map<'hir> { pub fn get_module(self, module: LocalModDefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = HirId::make_owner(module.to_local_def_id()); - match self.tcx.hir_owner(hir_id.owner) { - Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. })) => (m, span, hir_id), - Some(OwnerNode::Crate(item)) => (item, item.spans.inner_span, hir_id), + match self.tcx.hir_owner_node(hir_id.owner) { + OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. }) => (m, span, hir_id), + OwnerNode::Crate(item) => (item, item.spans.inner_span, hir_id), node => panic!("not a module: {node:?}"), } } @@ -726,8 +744,8 @@ impl<'hir> Map<'hir> { pub fn get_foreign_abi(self, hir_id: HirId) -> Abi { let parent = self.get_parent_item(hir_id); - if let Some(node) = self.tcx.hir_owner(parent) - && let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node + if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = + self.tcx.hir_owner_node(parent) { return *abi; } @@ -738,37 +756,32 @@ impl<'hir> Map<'hir> { } pub fn expect_owner(self, def_id: LocalDefId) -> OwnerNode<'hir> { - self.tcx - .hir_owner(OwnerId { def_id }) - .unwrap_or_else(|| bug!("expected owner for {:?}", def_id)) + self.tcx.expect_hir_owner_node(def_id) } pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> { - match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(OwnerNode::Item(item)) => item, + match self.tcx.expect_hir_owner_node(id) { + OwnerNode::Item(item) => item, _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> { - match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(OwnerNode::ImplItem(item)) => item, + match self.tcx.expect_hir_owner_node(id) { + OwnerNode::ImplItem(item) => item, _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> { - match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(OwnerNode::TraitItem(item)) => item, + match self.tcx.expect_hir_owner_node(id) { + OwnerNode::TraitItem(item) => item, _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> { - match self.tcx.hir_owner(OwnerId { def_id }) { - Some(node) => node.fn_decl().map(|fn_decl| &fn_decl.output), - _ => None, - } + Some(&self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.output) } pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> { @@ -779,8 +792,8 @@ impl<'hir> Map<'hir> { } pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> { - match self.tcx.hir_owner(id) { - Some(OwnerNode::ForeignItem(item)) => item, + match self.tcx.hir_owner_node(id) { + OwnerNode::ForeignItem(item) => item, _ => { bug!( "expected foreign item, found {}", diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 3d8012cdb64cc..5fb72fcf0cf3e 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -452,10 +452,5 @@ fn get_body_span<'tcx>( fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 { // FIXME(cjgillot) Stop hashing HIR manually here. let owner = hir_body.id().hir_id.owner; - tcx.opt_hir_owner_nodes(owner) - .unwrap() - .opt_hash_including_bodies - .unwrap() - .to_smaller_hash() - .as_u64() + tcx.hir_owner_nodes(owner).opt_hash_including_bodies.unwrap().to_smaller_hash().as_u64() } diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs index 2b0063f62d943..41168230752a8 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -93,9 +93,7 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { // reimplement it even if we wanted to cx.tcx.opt_hir_node(hir_id) } else { - let Some(owner) = cx.tcx.opt_hir_owner_nodes(hir_id.owner) else { - return; - }; + let owner = cx.tcx.hir_owner_nodes(hir_id.owner); owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node) }; let Some(node) = node else { From db41f4aaa0c7a2506b02407c1b5183d84103d24b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 25 Jan 2024 20:47:03 +0300 Subject: [PATCH 115/246] hir: Remove `hir::Map::{owner,expect_owner}` --- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../src/collect/resolve_bound_vars.rs | 2 +- .../rustc_infer/src/infer/error_reporting/mod.rs | 2 +- .../nice_region_error/static_impl_trait.rs | 2 +- compiler/rustc_lint/src/levels.rs | 2 +- compiler/rustc_middle/src/hir/map/mod.rs | 12 ++---------- compiler/rustc_mir_build/src/check_unsafety.rs | 2 +- .../clippy/clippy_lints/src/methods/iter_nth_zero.rs | 2 +- src/tools/clippy/clippy_lints/src/returns.rs | 2 +- 10 files changed, 11 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 28c8f846c23a9..b74431983113a 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -578,7 +578,7 @@ pub fn check_function_signature<'tcx>( fn_id: LocalDefId, ) -> rustc_span::Span { let mut args = { - let node = tcx.hir().expect_owner(fn_id); + let node = tcx.expect_hir_owner_node(fn_id); let decl = node.fn_decl().unwrap_or_else(|| bug!("expected fn decl, found {:?}", node)); decl.inputs.iter().map(|t| t.span).chain(std::iter::once(decl.output.span())) }; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0978a5e65969a..4253bfbccedac 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -189,7 +189,7 @@ where } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorGuaranteed> { - let node = tcx.hir().owner(def_id); + let node = tcx.hir_owner_node(def_id); let mut res = match node { hir::OwnerNode::Crate(_) => bug!("check_well_formed cannot be applied to the crate root"), hir::OwnerNode::Item(item) => check_item(tcx, item), diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 97d792e49aeaa..3849c0893f471 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -254,7 +254,7 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou map: &mut named_variable_map, scope: &Scope::Root { opt_parent_item: None }, }; - match tcx.hir().owner(local_def_id) { + match tcx.hir_owner_node(local_def_id) { hir::OwnerNode::Item(item) => visitor.visit_item(item), hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), hir::OwnerNode::TraitItem(item) => { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e19177fccefd8..95dab47702f55 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2546,7 +2546,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { add_lt_suggs, new_lt: &new_lt, }; - match self.tcx.hir().expect_owner(lifetime_scope) { + match self.tcx.expect_hir_owner_node(lifetime_scope) { hir::OwnerNode::Item(i) => visitor.visit_item(i), hir::OwnerNode::ForeignItem(i) => visitor.visit_foreign_item(i), hir::OwnerNode::ImplItem(i) => visitor.visit_impl_item(i), diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index a7d1c2ca66695..c8fd4e3a69286 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -443,7 +443,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if let hir::OwnerNode::Item(Item { kind: ItemKind::Impl(hir::Impl { self_ty, .. }), .. - }) = tcx.hir().owner(impl_did) + }) = tcx.hir_owner_node(impl_did) { Some((impl_item.ident, self_ty)) } else { diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index d37f0c151714d..40fb12b21070b 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -181,7 +181,7 @@ fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLe // Otherwise, we need to visit the attributes in source code order, so we fetch HIR and do // a standard visit. // FIXME(#102522) Just iterate on attrs once that iteration order matches HIR's. - _ => match tcx.hir().owner(owner) { + _ => match tcx.hir_owner_node(owner) { hir::OwnerNode::Item(item) => levels.visit_item(item), hir::OwnerNode::ForeignItem(item) => levels.visit_foreign_item(item), hir::OwnerNode::TraitItem(item) => levels.visit_trait_item(item), diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 5811dae1b5883..ba1ae46626b22 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -148,12 +148,12 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - fn expect_hir_owner_node(self, def_id: LocalDefId) -> OwnerNode<'tcx> { + pub fn expect_hir_owner_node(self, def_id: LocalDefId) -> OwnerNode<'tcx> { self.expect_hir_owner_nodes(def_id).node() } #[inline] - fn hir_owner_node(self, owner_id: OwnerId) -> OwnerNode<'tcx> { + pub fn hir_owner_node(self, owner_id: OwnerId) -> OwnerNode<'tcx> { self.hir_owner_nodes(owner_id).node() } @@ -263,10 +263,6 @@ impl<'hir> Map<'hir> { self.tcx.opt_hir_owner_node(id)?.generics() } - pub fn owner(self, id: OwnerId) -> OwnerNode<'hir> { - self.tcx.hir_owner_node(id) - } - pub fn item(self, id: ItemId) -> &'hir Item<'hir> { self.tcx.hir_owner_node(id.owner_id).expect_item() } @@ -755,10 +751,6 @@ impl<'hir> Map<'hir> { ) } - pub fn expect_owner(self, def_id: LocalDefId) -> OwnerNode<'hir> { - self.tcx.expect_hir_owner_node(def_id) - } - pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> { match self.tcx.expect_hir_owner_node(id) { OwnerNode::Item(item) => item, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index ac147afaab313..18eebeff67fa5 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -583,7 +583,7 @@ impl UnsafeOpKind { suggest_unsafe_block: bool, ) { let parent_id = tcx.hir().get_parent_item(hir_id); - let parent_owner = tcx.hir().owner(parent_id); + let parent_owner = tcx.hir_owner_node(parent_id); let should_suggest = parent_owner.fn_sig().is_some_and(|sig| sig.header.is_unsafe()); let unsafe_not_inherited_note = if should_suggest { suggest_unsafe_block.then(|| { diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs index e1f950d5a4a5f..262a57ab591a6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs @@ -11,7 +11,7 @@ use rustc_span::sym; use super::ITER_NTH_ZERO; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) { - if let OwnerNode::Item(item) = cx.tcx.hir().owner(cx.tcx.hir().get_parent_item(expr.hir_id)) + if let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id)) && let def_id = item.owner_id.to_def_id() && is_trait_method(cx, expr, sym::Iterator) && let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 2293b53b42b91..e01750465873d 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -183,7 +183,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { && let ExprKind::Ret(Some(ret)) = expr.kind && let ExprKind::Match(.., MatchSource::TryDesugar(_)) = ret.kind // Ensure this is not the final stmt, otherwise removing it would cause a compile error - && let OwnerNode::Item(item) = cx.tcx.hir().owner(cx.tcx.hir().get_parent_item(expr.hir_id)) + && let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id)) && let ItemKind::Fn(_, _, body) = item.kind && let block = cx.tcx.hir().body(body).value && let ExprKind::Block(block, _) = block.kind From 4facb6253e38d36a09212ea20374a98b84071819 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Tue, 30 Jan 2024 20:33:15 +0800 Subject: [PATCH 116/246] minor: update warning msg --- editors/code/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 6935d529aad8b..c386b9e5d8fb5 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -207,7 +207,7 @@ function checkConflictingExtensions() { if (vscode.extensions.getExtension("panicbit.cargo")) { vscode.window .showWarningMessage( - `You have both the rust-analyzer (rust-lang.rust-analyzer) and Cargo (panicbit.cargo) ` + + `You have both the rust-analyzer (rust-lang.rust-analyzer) and Cargo (panicbit.cargo) plugins enabled` + 'you can disable it or set {"cargo.automaticCheck": false} in settings.json to avoid invoking cargo twice', "Got it", ) From dba3fc4425a5941f683f314758b4a7abc45040e4 Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Tue, 30 Jan 2024 16:15:15 +0300 Subject: [PATCH 117/246] style: remove unnecessary macro --- crates/ide-db/src/imports/merge_imports.rs | 27 ++++++---------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/crates/ide-db/src/imports/merge_imports.rs b/crates/ide-db/src/imports/merge_imports.rs index 029357c607bfc..77c32fd852eed 100644 --- a/crates/ide-db/src/imports/merge_imports.rs +++ b/crates/ide-db/src/imports/merge_imports.rs @@ -256,23 +256,14 @@ pub fn try_normalize_use_tree( Some(use_tree) } -macro_rules! call_and_track_result { - ($call:expr, $tracker: ident) => { - let result = $call; - if !$tracker && result.is_some() { - $tracker = true; - } - }; -} - pub fn try_normalize_use_tree_mut( use_tree: &ast::UseTree, style: NormalizationStyle, ) -> Option<()> { if style == NormalizationStyle::One { let mut modified = false; - call_and_track_result!(use_tree.wrap_in_tree_list(), modified); - call_and_track_result!(recursive_normalize(use_tree, style), modified); + modified |= use_tree.wrap_in_tree_list().is_some(); + modified |= recursive_normalize(use_tree, style).is_some(); if !modified { // Either the use tree was already normalized or its semantically empty. return None; @@ -374,10 +365,9 @@ fn recursive_normalize(use_tree: &ast::UseTree, style: NormalizationStyle) -> Op if let Some(sub_one_tree_list) = one_style_tree_list(&sub_sub_tree) { curr_skipped.extend(sub_one_tree_list.use_trees()); } else { - call_and_track_result!( - recursive_normalize(&sub_sub_tree, NormalizationStyle::Default), - modified - ); + modified |= + recursive_normalize(&sub_sub_tree, NormalizationStyle::Default) + .is_some(); add_element_to_list( sub_sub_tree.syntax().clone().into(), &mut elements, @@ -401,10 +391,7 @@ fn recursive_normalize(use_tree: &ast::UseTree, style: NormalizationStyle) -> Op } modified = true; } else { - call_and_track_result!( - recursive_normalize(&subtree, NormalizationStyle::Default), - modified - ); + modified |= recursive_normalize(&subtree, NormalizationStyle::Default).is_some(); } } @@ -451,7 +438,7 @@ fn recursive_normalize(use_tree: &ast::UseTree, style: NormalizationStyle) -> Op // Merge the remaining subtree into its parent, if its only one and // the normalization style is not "one". if subtrees.len() == 1 && style != NormalizationStyle::One { - call_and_track_result!(merge_subtree_into_parent_tree(&subtrees[0]), modified); + modified |= merge_subtree_into_parent_tree(&subtrees[0]).is_some(); } // Order the remaining subtrees (if necessary). if subtrees.len() > 1 { From db9fd370ee2648c22a715d0558e496761a50c2c7 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Tue, 30 Jan 2024 21:43:43 +0800 Subject: [PATCH 118/246] minor: correct typos --- crates/hir-def/src/hir/format_args.rs | 4 ++-- crates/hir-def/src/lib.rs | 2 +- .../src/macro_expansion_tests/mbe/regression.rs | 2 +- crates/hir-def/src/nameres/path_resolution.rs | 4 ++-- crates/hir-ty/src/mir/eval.rs | 4 ++-- crates/hir-ty/src/utils.rs | 2 +- .../src/handlers/add_missing_impl_members.rs | 12 ++++++------ crates/ide-assists/src/handlers/extract_variable.rs | 2 +- .../src/handlers/generate_delegate_trait.rs | 6 +++--- .../src/handlers/generate_mut_trait_impl.rs | 2 +- .../src/handlers/generate_trait_from_impl.rs | 2 +- crates/ide-completion/src/completions/dot.rs | 10 +++++----- crates/ide-completion/src/tests/expression.rs | 4 ++-- crates/ide-db/src/documentation.rs | 2 +- crates/ide-diagnostics/src/tests.rs | 2 +- crates/ide/src/inlay_hints/implicit_drop.rs | 2 +- crates/mbe/src/expander/transcriber.rs | 2 +- .../proc-macro-srv/src/server/rust_analyzer_span.rs | 2 +- crates/rust-analyzer/src/cli/flags.rs | 2 +- crates/syntax/src/ast/edit_in_place.rs | 6 +++--- crates/syntax/src/ast/node_ext.rs | 2 +- docs/dev/syntax.md | 2 +- lib/lsp-server/src/error.rs | 2 +- 23 files changed, 40 insertions(+), 40 deletions(-) diff --git a/crates/hir-def/src/hir/format_args.rs b/crates/hir-def/src/hir/format_args.rs index c0d1738b5048e..113f9441a0129 100644 --- a/crates/hir-def/src/hir/format_args.rs +++ b/crates/hir-def/src/hir/format_args.rs @@ -214,7 +214,7 @@ pub(crate) fn parse( let mut used = vec![false; args.explicit_args().len()]; let mut invalid_refs = Vec::new(); - let mut numeric_refences_to_named_arg = Vec::new(); + let mut numeric_references_to_named_arg = Vec::new(); enum ArgRef<'a> { Index(usize), @@ -231,7 +231,7 @@ pub(crate) fn parse( used[index] = true; if arg.kind.ident().is_some() { // This was a named argument, but it was used as a positional argument. - numeric_refences_to_named_arg.push((index, span, used_as)); + numeric_references_to_named_arg.push((index, span, used_as)); } Ok(index) } else { diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 243de663977fd..71bc52133361f 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -745,7 +745,7 @@ impl InTypeConstId { } } -/// A constant, which might appears as a const item, an annonymous const block in expressions +/// A constant, which might appears as a const item, an anonymous const block in expressions /// or patterns, or as a constant in types with const generics. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum GeneralConstId { diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs index 71ba49721746d..226aa01827be7 100644 --- a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs +++ b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs @@ -72,7 +72,7 @@ fn main() { } "#]], ); - // FIXME we should ahev testing infra for multi level expansion tests + // FIXME we should have testing infra for multi level expansion tests check( r#" macro_rules! __rust_force_expr { diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 01f79f042f789..2c7e222791375 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -269,7 +269,7 @@ impl DefMap { stdx::never!(module.is_block_module()); if self.block != def_map.block { - // If we have a different `DefMap` from `self` (the orignal `DefMap` we started + // If we have a different `DefMap` from `self` (the original `DefMap` we started // with), resolve the remaining path segments in that `DefMap`. let path = ModPath::from_segments(PathKind::Super(0), path.segments().iter().cloned()); @@ -540,7 +540,7 @@ impl DefMap { } } -/// Given a block module, returns its nearest non-block module and the `DefMap` it blongs to. +/// Given a block module, returns its nearest non-block module and the `DefMap` it belongs to. fn adjust_to_nearest_non_block_module( db: &dyn DefDatabase, def_map: &DefMap, diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 8143dc05c38d4..26d0229698aa4 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -359,8 +359,8 @@ impl MirEvalError { func )?; } - Either::Right(clos) => { - writeln!(f, "In {:?}", clos)?; + Either::Right(close) => { + writeln!(f, "In {:?}", close)?; } } let source_map = db.body_with_source_map(*def).1; diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 2cdee5a15a88a..6ae0960b91599 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -192,7 +192,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { /// and it doesn't store the closure types and fields. /// /// Codes should not assume this ordering, and should always use methods available -/// on this struct for retriving, and `TyBuilder::substs_for_closure` for creating. +/// on this struct for retrieving, and `TyBuilder::substs_for_closure` for creating. pub(crate) struct ClosureSubst<'a>(pub(crate) &'a Substitution); impl<'a> ClosureSubst<'a> { diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 410c623109ea0..e15a3bb2c7bba 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -370,17 +370,17 @@ impl Foo for S { add_missing_impl_members, r#" pub trait Trait<'a, 'b, A, B, C> { - fn foo(&self, one: &'a A, anoter: &'b B) -> &'a C; + fn foo(&self, one: &'a A, another: &'b B) -> &'a C; } impl<'x, 'y, T, V, U> Trait<'x, 'y, T, V, U> for () {$0}"#, r#" pub trait Trait<'a, 'b, A, B, C> { - fn foo(&self, one: &'a A, anoter: &'b B) -> &'a C; + fn foo(&self, one: &'a A, another: &'b B) -> &'a C; } impl<'x, 'y, T, V, U> Trait<'x, 'y, T, V, U> for () { - fn foo(&self, one: &'x T, anoter: &'y V) -> &'x U { + fn foo(&self, one: &'x T, another: &'y V) -> &'x U { ${0:todo!()} } }"#, @@ -393,7 +393,7 @@ impl<'x, 'y, T, V, U> Trait<'x, 'y, T, V, U> for () { add_missing_default_members, r#" pub trait Trait<'a, 'b, A, B, C: Default> { - fn foo(&self, _one: &'a A, _anoter: &'b B) -> (C, &'a i32) { + fn foo(&self, _one: &'a A, _another: &'b B) -> (C, &'a i32) { let value: &'a i32 = &0; (C::default(), value) } @@ -402,14 +402,14 @@ pub trait Trait<'a, 'b, A, B, C: Default> { impl<'x, 'y, T, V, U: Default> Trait<'x, 'y, T, V, U> for () {$0}"#, r#" pub trait Trait<'a, 'b, A, B, C: Default> { - fn foo(&self, _one: &'a A, _anoter: &'b B) -> (C, &'a i32) { + fn foo(&self, _one: &'a A, _another: &'b B) -> (C, &'a i32) { let value: &'a i32 = &0; (C::default(), value) } } impl<'x, 'y, T, V, U: Default> Trait<'x, 'y, T, V, U> for () { - $0fn foo(&self, _one: &'x T, _anoter: &'y V) -> (U, &'x i32) { + $0fn foo(&self, _one: &'x T, _another: &'y V) -> (U, &'x i32) { let value: &'x i32 = &0; (::default(), value) } diff --git a/crates/ide-assists/src/handlers/extract_variable.rs b/crates/ide-assists/src/handlers/extract_variable.rs index 0f23b69908d6c..22d16cf6b36e4 100644 --- a/crates/ide-assists/src/handlers/extract_variable.rs +++ b/crates/ide-assists/src/handlers/extract_variable.rs @@ -163,7 +163,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op block } else { // `expr_replace` is a descendant of `to_wrap`, so both steps need to be - // handled seperately, otherwise we wrap the wrong expression + // handled separately, otherwise we wrap the wrong expression let to_wrap = edit.make_mut(to_wrap); // Replace the target expr first so that we don't need to find where diff --git a/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/crates/ide-assists/src/handlers/generate_delegate_trait.rs index 154a1f59c722c..3964b14f4703f 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -491,7 +491,7 @@ fn remove_useless_where_clauses(trait_ty: &ast::Type, self_ty: &ast::Type, wc: a // Generate generic args that should be apply to current impl. // -// For exmaple, say we have implementation `impl Trait for B`, +// For example, say we have implementation `impl Trait for B`, // and `b: B` in struct `S`. Then the `A` should be instantiated to `T`. // While the last two generic args `B` and `C` doesn't change, it remains // ``. So we apply `` as generic arguments to impl. @@ -637,7 +637,7 @@ fn const_assoc_item(item: syntax::ast::Const, qual_path_ty: ast::Path) -> Option let path_expr_segment = make::path_from_text(item.name()?.to_string().as_str()); // We want rhs of the const assignment to be a qualified path - // The general case for const assigment can be found [here](`https://doc.rust-lang.org/reference/items/constant-items.html`) + // The general case for const assignment can be found [here](`https://doc.rust-lang.org/reference/items/constant-items.html`) // The qualified will have the following generic syntax : // >::ConstName; // FIXME : We can't rely on `make::path_qualified` for now but it would be nice to replace the following with it. @@ -779,7 +779,7 @@ impl Trait for Base {} #[test] fn test_self_ty() { - // trait whith `Self` type cannot be delegated + // trait with `Self` type cannot be delegated // // See the function `fn f() -> Self`. // It should be `fn f() -> Base` in `Base`, and `fn f() -> S` in `S` diff --git a/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs b/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs index d90d366ffe4c4..91eaa96b6cb0d 100644 --- a/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs +++ b/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs @@ -6,7 +6,7 @@ use syntax::{ use crate::{AssistContext, AssistId, AssistKind, Assists}; -// FIXME: Generate proper `index_mut` method body refer to `index` method body may impossible due to the unpredicable case [#15581]. +// 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. // Assist: generate_mut_trait_impl diff --git a/crates/ide-assists/src/handlers/generate_trait_from_impl.rs b/crates/ide-assists/src/handlers/generate_trait_from_impl.rs index a8817436ba1fc..8881aa69f29d3 100644 --- a/crates/ide-assists/src/handlers/generate_trait_from_impl.rs +++ b/crates/ide-assists/src/handlers/generate_trait_from_impl.rs @@ -183,7 +183,7 @@ fn remove_items_visibility(item: &ast::AssocItem) { fn strip_body(item: &ast::AssocItem) { if let ast::AssocItem::Fn(f) = item { if let Some(body) = f.body() { - // In constrast to function bodies, we want to see no ws before a semicolon. + // In contrast to function bodies, we want to see no ws before a semicolon. // So let's remove them if we see any. if let Some(prev) = body.syntax().prev_sibling_or_token() { if prev.kind() == SyntaxKind::WHITESPACE { diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs index e5fdac327cdb6..00135a6d202cb 100644 --- a/crates/ide-completion/src/completions/dot.rs +++ b/crates/ide-completion/src/completions/dot.rs @@ -31,7 +31,7 @@ pub(crate) fn complete_dot( } let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. }); - let is_method_acces_with_parens = + let is_method_access_with_parens = matches!(dot_access.kind, DotAccessKind::Method { has_parens: true }); complete_fields( @@ -41,7 +41,7 @@ pub(crate) fn complete_dot( |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty), |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty), is_field_access, - is_method_acces_with_parens, + is_method_access_with_parens, ); complete_methods(ctx, receiver_ty, |func| acc.add_method(ctx, dot_access, func, None, None)); @@ -114,14 +114,14 @@ fn complete_fields( mut named_field: impl FnMut(&mut Completions, hir::Field, hir::Type), mut tuple_index: impl FnMut(&mut Completions, usize, hir::Type), is_field_access: bool, - is_method_acess_with_parens: bool, + is_method_access_with_parens: bool, ) { let mut seen_names = FxHashSet::default(); for receiver in receiver.autoderef(ctx.db) { for (field, ty) in receiver.fields(ctx.db) { if seen_names.insert(field.name(ctx.db)) && (is_field_access - || (is_method_acess_with_parens && (ty.is_fn() || ty.is_closure()))) + || (is_method_access_with_parens && (ty.is_fn() || ty.is_closure()))) { named_field(acc, field, ty); } @@ -131,7 +131,7 @@ fn complete_fields( // already seen without inserting into the hashset. if !seen_names.contains(&hir::Name::new_tuple_field(i)) && (is_field_access - || (is_method_acess_with_parens && (ty.is_fn() || ty.is_closure()))) + || (is_method_access_with_parens && (ty.is_fn() || ty.is_closure()))) { // Tuple fields are always public (tuple struct fields are handled above). tuple_index(acc, i, ty); diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs index b4f936b35aead..758c254a88289 100644 --- a/crates/ide-completion/src/tests/expression.rs +++ b/crates/ide-completion/src/tests/expression.rs @@ -105,7 +105,7 @@ fn func(param0 @ (param1, param2): (i32, i32)) { fn completes_all_the_things_in_fn_body() { check( r#" -use non_existant::Unresolved; +use non_existent::Unresolved; mod qualified { pub enum Enum { Variant } } impl Unit { @@ -170,7 +170,7 @@ impl Unit { ); check( r#" -use non_existant::Unresolved; +use non_existent::Unresolved; mod qualified { pub enum Enum { Variant } } impl Unit { diff --git a/crates/ide-db/src/documentation.rs b/crates/ide-db/src/documentation.rs index cc8e8431708ab..72ca354365e7b 100644 --- a/crates/ide-db/src/documentation.rs +++ b/crates/ide-db/src/documentation.rs @@ -1,4 +1,4 @@ -//! Documentation attribute related utilties. +//! Documentation attribute related utilities. use either::Either; use hir::{ db::{DefDatabase, HirDatabase}, diff --git a/crates/ide-diagnostics/src/tests.rs b/crates/ide-diagnostics/src/tests.rs index 742db32564de3..f394a491b5124 100644 --- a/crates/ide-diagnostics/src/tests.rs +++ b/crates/ide-diagnostics/src/tests.rs @@ -173,7 +173,7 @@ fn minicore_smoke_test() { fn check(minicore: MiniCore) { let source = minicore.source_code(); let mut config = DiagnosticsConfig::test_sample(); - // This should be ignored since we conditionaly remove code which creates single item use with braces + // This should be ignored since we conditionally remove code which creates single item use with braces config.disabled.insert("unused_braces".to_string()); check_diagnostics_with_config(config, &source); } diff --git a/crates/ide/src/inlay_hints/implicit_drop.rs b/crates/ide/src/inlay_hints/implicit_drop.rs index 5a206643acf6a..3104b85768f47 100644 --- a/crates/ide/src/inlay_hints/implicit_drop.rs +++ b/crates/ide/src/inlay_hints/implicit_drop.rs @@ -177,7 +177,7 @@ mod tests { #[test] fn try_operator() { - // We currently show drop inlay hint for every `?` operator that may potentialy drop something. We probably need to + // We currently show drop inlay hint for every `?` operator that may potentially drop something. We probably need to // make it configurable as it doesn't seem very useful. check_with_config( ONLY_DROP_CONFIG, diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs index 5b7a25408a828..800bc994adab2 100644 --- a/crates/mbe/src/expander/transcriber.rs +++ b/crates/mbe/src/expander/transcriber.rs @@ -292,7 +292,7 @@ fn expand_subtree( Err(e) => { // XXX: It *might* make sense to emit a dummy integer value like `0` here. // That would type inference a bit more robust in cases like - // `v[${count(t)}]` where index doesn't matter, but also coult also lead to + // `v[${count(t)}]` where index doesn't matter, but also could lead to // wrong infefrence for cases like `tup.${count(t)}` where index itself // does matter. if err.is_none() { diff --git a/crates/proc-macro-srv/src/server/rust_analyzer_span.rs b/crates/proc-macro-srv/src/server/rust_analyzer_span.rs index bcf3600d27366..b864a5e4fd63e 100644 --- a/crates/proc-macro-srv/src/server/rust_analyzer_span.rs +++ b/crates/proc-macro-srv/src/server/rust_analyzer_span.rs @@ -1,4 +1,4 @@ -//! proc-macro server backend based on rust-analyzer's internal span represention +//! proc-macro server backend based on rust-analyzer's internal span representation //! This backend is used solely by rust-analyzer as it ties into rust-analyzer internals. //! //! It is an unfortunate result of how the proc-macro API works that we need to look into the diff --git a/crates/rust-analyzer/src/cli/flags.rs b/crates/rust-analyzer/src/cli/flags.rs index cc9e2a7ce26f8..252b1e1a48581 100644 --- a/crates/rust-analyzer/src/cli/flags.rs +++ b/crates/rust-analyzer/src/cli/flags.rs @@ -71,7 +71,7 @@ xflags::xflags! { optional --with-deps /// Don't load sysroot crates (`std`, `core` & friends). optional --no-sysroot - /// Run cargo metadata on the sysroot to analyze its third-pary dependencies. + /// Run cargo metadata on the sysroot to analyze its third-party dependencies. /// Requires --no-sysroot to not be set. optional --query-sysroot-metadata diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index 247dfe0b459a5..38420da2ca2d5 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs @@ -960,10 +960,10 @@ impl ast::IdentPat { } pub trait HasVisibilityEdit: ast::HasVisibility { - fn set_visibility(&self, visbility: ast::Visibility) { + fn set_visibility(&self, visibility: ast::Visibility) { match self.visibility() { Some(current_visibility) => { - ted::replace(current_visibility.syntax(), visbility.syntax()) + ted::replace(current_visibility.syntax(), visibility.syntax()) } None => { let vis_before = self @@ -972,7 +972,7 @@ pub trait HasVisibilityEdit: ast::HasVisibility { .find(|it| !matches!(it.kind(), WHITESPACE | COMMENT | ATTR)) .unwrap_or_else(|| self.syntax().first_child_or_token().unwrap()); - ted::insert(ted::Position::before(vis_before), visbility.syntax()); + ted::insert(ted::Position::before(vis_before), visibility.syntax()); } } } diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index ce01ee1c3594b..6e5e4127f4d43 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -384,7 +384,7 @@ impl ast::UseTreeList { // the below remove the innermost {}, got `use crate::{{{A}}}` remove_brace_in_use_tree_list(&self); - // the below remove othe unnecessary {}, got `use crate::A` + // the below remove other unnecessary {}, got `use crate::A` while let Some(parent_use_tree_list) = self.parent_use_tree().parent_use_tree_list() { remove_brace_in_use_tree_list(&parent_use_tree_list); self = parent_use_tree_list; diff --git a/docs/dev/syntax.md b/docs/dev/syntax.md index fd6f220f4fa90..6c4daecc58ff7 100644 --- a/docs/dev/syntax.md +++ b/docs/dev/syntax.md @@ -128,7 +128,7 @@ Interior nodes are shared as well (for example in `(1 + 1) * (1 + 1)`). Note that, the result of the interning is an `Arc`. That is, it's not an index into interning table, so you don't have to have the table around to do anything with the tree. Each tree is fully self-contained (although different trees might share parts). -Currently, the interner is created per-file, but it will be easy to use a per-thread or per-some-contex one. +Currently, the interner is created per-file, but it will be easy to use a per-thread or per-some-context one. We use a `TextSize`, a newtyped `u32`, to store the length of the text. diff --git a/lib/lsp-server/src/error.rs b/lib/lsp-server/src/error.rs index ebdd153b5b317..da55393339028 100644 --- a/lib/lsp-server/src/error.rs +++ b/lib/lsp-server/src/error.rs @@ -14,7 +14,7 @@ impl ProtocolError { ProtocolError("disconnected channel".into(), true) } - /// Whether this error occured due to a disconnected channel. + /// Whether this error occurred due to a disconnected channel. pub fn channel_is_disconnected(&self) -> bool { self.1 } From 75a42f1a09fec0e4f31cbfa31056a3decc4c961e Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 00:08:55 +0100 Subject: [PATCH 119/246] collapsible_if --- crates/proc-macro-srv/proc-macro-test/build.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/proc-macro-srv/proc-macro-test/build.rs b/crates/proc-macro-srv/proc-macro-test/build.rs index c9b605a808765..ff62980e4ffe3 100644 --- a/crates/proc-macro-srv/proc-macro-test/build.rs +++ b/crates/proc-macro-srv/proc-macro-test/build.rs @@ -109,11 +109,11 @@ 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.package_id.repr.starts_with(&repr) || artifact.package_id.repr == pkgid - { - artifact_path = Some(PathBuf::from(&artifact.filenames[0])); - } + if artifact.target.kind.contains(&"proc-macro".to_string()) + && (artifact.package_id.repr.starts_with(&repr) + || artifact.package_id.repr == pkgid) + { + artifact_path = Some(PathBuf::from(&artifact.filenames[0])); } } } From 73c7c729c5bc67d4e4fe713614ce2696665ed02a Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 00:06:52 +0100 Subject: [PATCH 120/246] CI: add clippy --- .github/workflows/ci.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index be830415f9cb7..52cbda5a61315 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -90,7 +90,7 @@ jobs: - name: Switch to stable toolchain run: | rustup update --no-self-update stable - rustup component add --toolchain stable rust-src + rustup component add --toolchain stable rust-src clippy rustup default stable - name: Run analysis-stats on rust-analyzer @@ -103,6 +103,10 @@ jobs: RUSTC_BOOTSTRAP: 1 run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std + - name: clippy + if: matrix.os == 'ubuntu-latest' + run: cargo clippy --all-targets -- -D warnings + # Weird targets to catch non-portable code rust-cross: if: github.repository == 'rust-lang/rust-analyzer' From 628f70156e379dfd4053c08c23290d8e81f77f04 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Tue, 30 Jan 2024 14:15:10 +0100 Subject: [PATCH 121/246] CI: Don't deny clippy warnings We configure that in the lint table in `Cargo.toml`. --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 52cbda5a61315..b5c5ff04738a7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -105,7 +105,7 @@ jobs: - name: clippy if: matrix.os == 'ubuntu-latest' - run: cargo clippy --all-targets -- -D warnings + run: cargo clippy --all-targets # Weird targets to catch non-portable code rust-cross: From 43b1ae04466b4fff30772d0bbb0743a8fb3639a7 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Tue, 30 Jan 2024 14:25:28 +0100 Subject: [PATCH 122/246] `cargo clippy --fix` --- crates/hir-expand/src/attrs.rs | 2 +- crates/hir-expand/src/mod_path.rs | 2 +- crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs | 2 +- crates/hir-ty/src/mir/eval.rs | 2 +- crates/hir/src/attrs.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs index 30d38299d99d4..b0b2501ce9d48 100644 --- a/crates/hir-expand/src/attrs.rs +++ b/crates/hir-expand/src/attrs.rs @@ -235,7 +235,7 @@ impl Attr { let (path, input) = tt.split_at(path_end); let path = Interned::new(ModPath::from_tt(db, path)?); - let input = match input.get(0) { + let input = match input.first() { Some(tt::TokenTree::Subtree(tree)) => { Some(Interned::new(AttrInput::TokenTree(Box::new(tree.clone())))) } diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 0eb1fc1eb5009..dd41bcaee20ef 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -232,7 +232,7 @@ fn convert_path( ast::PathSegmentKind::SuperKw => { let mut deg = 1; let mut next_segment = None; - while let Some(segment) = segments.next() { + for segment in segments.by_ref() { match segment.kind()? { ast::PathSegmentKind::SuperKw => deg += 1, ast::PathSegmentKind::Name(name) => { diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index cd67ca599310c..e2d8c97cd97fc 100644 --- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -237,7 +237,7 @@ impl<'p> MatchCheckCtx<'p> { ctor = Or; // Collect here because `Arena::alloc_extend` panics on reentrancy. let subpats: SmallVec<[_; 2]> = - pats.into_iter().map(|pat| self.lower_pat(pat)).collect(); + pats.iter().map(|pat| self.lower_pat(pat)).collect(); fields = self.pattern_arena.alloc_extend(subpats); } } diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 885360d05fe78..b821942f21226 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -1715,7 +1715,7 @@ impl Evaluator<'_> { let v: Cow<'_, [u8]> = if size != v.len() { // Handle self enum if size == 16 && v.len() < 16 { - Cow::Owned(pad16(&v, false).to_vec()) + Cow::Owned(pad16(v, false).to_vec()) } else if size < 16 && v.len() == 16 { Cow::Borrowed(&v[0..size]) } else { diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index fc0a196df7cbe..f2b9db669e0e9 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -311,7 +311,7 @@ fn modpath_from_str(link: &str) -> Option { "self" => PathKind::Super(0), "super" => { let mut deg = 1; - while let Some(segment) = parts.next() { + for segment in parts.by_ref() { if segment == "super" { deg += 1; } else { From f6b21e90d1ec01081bc2619efb68af6788a63d65 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 30 Jan 2024 15:39:29 +0000 Subject: [PATCH 123/246] Remove the `abi_amdgpu_kernel` feature --- .../rustc_codegen_cranelift/src/abi/mod.rs | 6 +- compiler/rustc_codegen_llvm/src/abi.rs | 1 - compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 - compiler/rustc_feature/src/removed.rs | 2 + compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_middle/src/ty/layout.rs | 1 - .../src/ffi_unwind_calls.rs | 1 - .../rustc_smir/src/rustc_internal/internal.rs | 1 - .../rustc_smir/src/rustc_smir/convert/abi.rs | 1 - .../rustc_smir/src/rustc_smir/convert/ty.rs | 1 - compiler/rustc_target/src/abi/call/mod.rs | 2 - compiler/rustc_target/src/json.rs | 1 - compiler/rustc_target/src/spec/abi/mod.rs | 35 +++--- compiler/rustc_target/src/spec/mod.rs | 1 - compiler/rustc_ty_utils/src/abi.rs | 1 - compiler/stable_mir/src/abi.rs | 1 - compiler/stable_mir/src/ty.rs | 1 - tests/ui/abi/unsupported.aarch64.stderr | 26 ++--- tests/ui/abi/unsupported.arm.stderr | 24 ++-- tests/ui/abi/unsupported.i686.stderr | 20 ++-- tests/ui/abi/unsupported.riscv32.stderr | 24 ++-- tests/ui/abi/unsupported.riscv64.stderr | 24 ++-- tests/ui/abi/unsupported.rs | 3 - tests/ui/abi/unsupported.x64.stderr | 24 ++-- .../feature-gate-abi_amdgpu_kernel.rs | 30 ----- .../feature-gate-abi_amdgpu_kernel.stderr | 104 ------------------ 26 files changed, 70 insertions(+), 268 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs delete mode 100644 tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index abd70dd4458f6..0f0d828c8fc3f 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -56,11 +56,7 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call sess.dcx().fatal("C-cmse-nonsecure-call call conv is not yet implemented"); } - Conv::Msp430Intr - | Conv::PtxKernel - | Conv::AmdGpuKernel - | Conv::AvrInterrupt - | Conv::AvrNonBlockingInterrupt => { + Conv::Msp430Intr | Conv::PtxKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => { unreachable!("tried to use {c:?} call conv which only exists on an unsupported target"); } } diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 0718bebb31bf8..b5b4f894e4d82 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -590,7 +590,6 @@ impl From for llvm::CallConv { Conv::Cold => llvm::ColdCallConv, Conv::PreserveMost => llvm::PreserveMost, Conv::PreserveAll => llvm::PreserveAll, - Conv::AmdGpuKernel => llvm::AmdGpuKernel, Conv::AvrInterrupt => llvm::AvrInterrupt, Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt, Conv::ArmAapcs => llvm::ArmAapcsCallConv, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index ee73c6b4756f0..4ad44a42738b3 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -106,7 +106,6 @@ pub enum CallConv { X86_Intr = 83, AvrNonBlockingInterrupt = 84, AvrInterrupt = 85, - AmdGpuKernel = 91, } /// LLVMRustLinkage diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 67ee53d8ae53f..85fcf6a999412 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -32,6 +32,8 @@ declare_features! ( // feature-group-start: removed features // ------------------------------------------------------------------------- + /// Allows using the `amdgpu-kernel` ABI. + (removed, abi_amdgpu_kernel, "CURRENT_RUSTC_VERSION", Some(51575), None), (removed, advanced_slice_patterns, "1.0.0", Some(62254), Some("merged into `#![feature(slice_patterns)]`")), (removed, allocator, "1.0.0", None, None), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index e66a66e23dc4f..643185ba20a7c 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -321,8 +321,6 @@ declare_features! ( // feature-group-start: actual feature gates // ------------------------------------------------------------------------- - /// Allows using the `amdgpu-kernel` ABI. - (unstable, abi_amdgpu_kernel, "1.29.0", Some(51575)), /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`. (unstable, abi_avr_interrupt, "1.45.0", Some(69664)), /// Allows `extern "C-cmse-nonsecure-call" fn()`. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 25473f52c039e..d00e98b39d095 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1247,7 +1247,6 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option, abi: SpecAbi) -> PtxKernel | Msp430Interrupt | X86Interrupt - | AmdGpuKernel | EfiApi | AvrInterrupt | AvrNonBlockingInterrupt diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index c47abb4fcb478..db7dfc5b43efa 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -26,7 +26,6 @@ fn abi_can_unwind(abi: Abi) -> bool { PtxKernel | Msp430Interrupt | X86Interrupt - | AmdGpuKernel | EfiApi | AvrInterrupt | AvrNonBlockingInterrupt diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index fa52f52d60b99..6bbfcff5e87cc 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -449,7 +449,6 @@ impl RustcInternal for Abi { Abi::PtxKernel => rustc_target::spec::abi::Abi::PtxKernel, Abi::Msp430Interrupt => rustc_target::spec::abi::Abi::Msp430Interrupt, Abi::X86Interrupt => rustc_target::spec::abi::Abi::X86Interrupt, - Abi::AmdGpuKernel => rustc_target::spec::abi::Abi::AmdGpuKernel, Abi::EfiApi => rustc_target::spec::abi::Abi::EfiApi, Abi::AvrInterrupt => rustc_target::spec::abi::Abi::AvrInterrupt, Abi::AvrNonBlockingInterrupt => rustc_target::spec::abi::Abi::AvrNonBlockingInterrupt, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs index 68b564741dc1f..088a836c90182 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs @@ -111,7 +111,6 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::Conv { Conv::X86VectorCall => CallConvention::X86VectorCall, Conv::X86_64SysV => CallConvention::X86_64SysV, Conv::X86_64Win64 => CallConvention::X86_64Win64, - Conv::AmdGpuKernel => CallConvention::AmdGpuKernel, Conv::AvrInterrupt => CallConvention::AvrInterrupt, Conv::AvrNonBlockingInterrupt => CallConvention::AvrNonBlockingInterrupt, Conv::RiscvInterrupt { .. } => CallConvention::RiscvInterrupt, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index cffbdc376f1fa..ba957843bb079 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -223,7 +223,6 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { abi::Abi::PtxKernel => Abi::PtxKernel, abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt, abi::Abi::X86Interrupt => Abi::X86Interrupt, - abi::Abi::AmdGpuKernel => Abi::AmdGpuKernel, abi::Abi::EfiApi => Abi::EfiApi, abi::Abi::AvrInterrupt => Abi::AvrInterrupt, abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt, diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 1c83039047e05..db721212f8e91 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -705,7 +705,6 @@ pub enum Conv { X86_64SysV, X86_64Win64, - AmdGpuKernel, AvrInterrupt, AvrNonBlockingInterrupt, @@ -887,7 +886,6 @@ impl FromStr for Conv { "X86VectorCall" => Ok(Conv::X86VectorCall), "X86_64SysV" => Ok(Conv::X86_64SysV), "X86_64Win64" => Ok(Conv::X86_64Win64), - "AmdGpuKernel" => Ok(Conv::AmdGpuKernel), "AvrInterrupt" => Ok(Conv::AvrInterrupt), "AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt), "RiscvInterrupt(machine)" => { diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs index c613514908141..f3aecaaab984f 100644 --- a/compiler/rustc_target/src/json.rs +++ b/compiler/rustc_target/src/json.rs @@ -110,7 +110,6 @@ impl ToJson for crate::abi::call::Conv { Self::X86VectorCall => "X86VectorCall", Self::X86_64SysV => "X86_64SysV", Self::X86_64Win64 => "X86_64Win64", - Self::AmdGpuKernel => "AmdGpuKernel", Self::AvrInterrupt => "AvrInterrupt", Self::AvrNonBlockingInterrupt => "AvrNonBlockingInterrupt", Self::RiscvInterrupt { kind } => { diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs index 1a0aa6f0c4a2e..6231787bb9fdb 100644 --- a/compiler/rustc_target/src/spec/abi/mod.rs +++ b/compiler/rustc_target/src/spec/abi/mod.rs @@ -44,7 +44,6 @@ pub enum Abi { PtxKernel, Msp430Interrupt, X86Interrupt, - AmdGpuKernel, EfiApi, AvrInterrupt, AvrNonBlockingInterrupt, @@ -121,7 +120,6 @@ const AbiDatas: &[AbiData] = &[ AbiData { abi: Abi::PtxKernel, name: "ptx-kernel" }, AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" }, AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" }, - AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel" }, AbiData { abi: Abi::EfiApi, name: "efiapi" }, AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" }, AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" }, @@ -237,10 +235,6 @@ pub fn is_stable(name: &str) -> Result<(), AbiDisabled> { feature: sym::abi_x86_interrupt, explain: "x86-interrupt ABI is experimental and subject to change", }), - "amdgpu-kernel" => Err(AbiDisabled::Unstable { - feature: sym::abi_amdgpu_kernel, - explain: "amdgpu-kernel ABI is experimental and subject to change", - }), "avr-interrupt" | "avr-non-blocking-interrupt" => Err(AbiDisabled::Unstable { feature: sym::abi_avr_interrupt, explain: "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change", @@ -295,22 +289,21 @@ impl Abi { PtxKernel => 19, Msp430Interrupt => 20, X86Interrupt => 21, - AmdGpuKernel => 22, - EfiApi => 23, - AvrInterrupt => 24, - AvrNonBlockingInterrupt => 25, - CCmseNonSecureCall => 26, - Wasm => 27, + EfiApi => 22, + AvrInterrupt => 23, + AvrNonBlockingInterrupt => 24, + CCmseNonSecureCall => 25, + Wasm => 26, // Cross-platform ABIs - System { unwind: false } => 28, - System { unwind: true } => 29, - RustIntrinsic => 30, - RustCall => 31, - PlatformIntrinsic => 32, - Unadjusted => 33, - RustCold => 34, - RiscvInterruptM => 35, - RiscvInterruptS => 36, + System { unwind: false } => 27, + System { unwind: true } => 28, + RustIntrinsic => 29, + RustCall => 30, + PlatformIntrinsic => 31, + Unadjusted => 32, + RustCold => 33, + RiscvInterruptM => 34, + RiscvInterruptS => 35, }; debug_assert!( AbiDatas diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ead3be7fd529b..3b1e52dfe4d56 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2458,7 +2458,6 @@ impl Target { Win64 { .. } | SysV64 { .. } => self.arch == "x86_64", PtxKernel => self.arch == "nvptx64", Msp430Interrupt => self.arch == "msp430", - AmdGpuKernel => self.arch == "amdgcn", RiscvInterruptM | RiscvInterruptS => ["riscv32", "riscv64"].contains(&&self.arch[..]), AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr", Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]), diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 333aec1d38d7f..af26616831fd0 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -258,7 +258,6 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv { PtxKernel => Conv::PtxKernel, Msp430Interrupt => Conv::Msp430Intr, X86Interrupt => Conv::X86Intr, - AmdGpuKernel => Conv::AmdGpuKernel, AvrInterrupt => Conv::AvrInterrupt, AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt, RiscvInterruptM => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine }, diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index 53dac6abefb30..a15fd3e0999bd 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -275,7 +275,6 @@ pub enum CallConvention { X86_64SysV, X86_64Win64, - AmdGpuKernel, AvrInterrupt, AvrNonBlockingInterrupt, diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index b0a08cd9b792c..bdda929534705 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -864,7 +864,6 @@ pub enum Abi { PtxKernel, Msp430Interrupt, X86Interrupt, - AmdGpuKernel, EfiApi, AvrInterrupt, AvrNonBlockingInterrupt, diff --git a/tests/ui/abi/unsupported.aarch64.stderr b/tests/ui/abi/unsupported.aarch64.stderr index d7b4e6150ff31..72a9519e3e772 100644 --- a/tests/ui/abi/unsupported.aarch64.stderr +++ b/tests/ui/abi/unsupported.aarch64.stderr @@ -1,59 +1,53 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:46:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:51:1 + --> $DIR/unsupported.rs:48:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:53:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:62:1 + --> $DIR/unsupported.rs:59:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,6 +56,6 @@ LL | extern "stdcall" fn stdcall() {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 9 previous errors; 1 warning emitted +error: aborting due to 8 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.arm.stderr b/tests/ui/abi/unsupported.arm.stderr index 3a3ed2dd9c569..473b59a334df3 100644 --- a/tests/ui/abi/unsupported.arm.stderr +++ b/tests/ui/abi/unsupported.arm.stderr @@ -1,53 +1,47 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:46:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:51:1 + --> $DIR/unsupported.rs:48:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:53:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:62:1 + --> $DIR/unsupported.rs:59:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,6 +50,6 @@ LL | extern "stdcall" fn stdcall() {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.i686.stderr b/tests/ui/abi/unsupported.i686.stderr index 31b7d030bd3b4..f0af3d251e245 100644 --- a/tests/ui/abi/unsupported.i686.stderr +++ b/tests/ui/abi/unsupported.i686.stderr @@ -1,45 +1,39 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:46:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.riscv32.stderr b/tests/ui/abi/unsupported.riscv32.stderr index 1966e18f0a06e..b466a2a6ff86b 100644 --- a/tests/ui/abi/unsupported.riscv32.stderr +++ b/tests/ui/abi/unsupported.riscv32.stderr @@ -1,53 +1,47 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:51:1 + --> $DIR/unsupported.rs:48:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:53:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:62:1 + --> $DIR/unsupported.rs:59:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,6 +50,6 @@ LL | extern "stdcall" fn stdcall() {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.riscv64.stderr b/tests/ui/abi/unsupported.riscv64.stderr index 1966e18f0a06e..b466a2a6ff86b 100644 --- a/tests/ui/abi/unsupported.riscv64.stderr +++ b/tests/ui/abi/unsupported.riscv64.stderr @@ -1,53 +1,47 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:51:1 + --> $DIR/unsupported.rs:48:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:53:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:62:1 + --> $DIR/unsupported.rs:59:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,6 +50,6 @@ LL | extern "stdcall" fn stdcall() {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.rs b/tests/ui/abi/unsupported.rs index 57278e664b51e..9b99e51905da2 100644 --- a/tests/ui/abi/unsupported.rs +++ b/tests/ui/abi/unsupported.rs @@ -19,7 +19,6 @@ abi_ptx, abi_msp430_interrupt, abi_avr_interrupt, - abi_amdgpu_kernel, wasm_abi, abi_x86_interrupt, abi_riscv_interrupt @@ -29,8 +28,6 @@ trait Sized {} extern "ptx-kernel" fn ptx() {} //~^ ERROR is not a supported ABI -extern "amdgpu-kernel" fn amdgpu() {} -//~^ ERROR is not a supported ABI extern "wasm" fn wasm() {} //~^ ERROR is not a supported ABI extern "aapcs" fn aapcs() {} diff --git a/tests/ui/abi/unsupported.x64.stderr b/tests/ui/abi/unsupported.x64.stderr index ea62cb1514807..4a2b7e7496920 100644 --- a/tests/ui/abi/unsupported.x64.stderr +++ b/tests/ui/abi/unsupported.x64.stderr @@ -1,53 +1,47 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:46:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:53:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:62:1 + --> $DIR/unsupported.rs:59:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,6 +50,6 @@ LL | extern "stdcall" fn stdcall() {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs b/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs deleted file mode 100644 index 465b81d7fe33c..0000000000000 --- a/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs +++ /dev/null @@ -1,30 +0,0 @@ -// compile-flags: --crate-type=rlib -#![no_core] -#![feature(no_core, lang_items)] -#[lang="sized"] -trait Sized { } - -extern "amdgpu-kernel" fn fu() {} //~ ERROR amdgpu-kernel ABI is experimental -//~^ ERROR is not a supported ABI - -trait T { - extern "amdgpu-kernel" fn mu(); //~ ERROR amdgpu-kernel ABI is experimental - extern "amdgpu-kernel" fn dmu() {} //~ ERROR amdgpu-kernel ABI is experimental - //~^ ERROR is not a supported ABI -} - -struct S; -impl T for S { - extern "amdgpu-kernel" fn mu() {} //~ ERROR amdgpu-kernel ABI is experimental - //~^ ERROR is not a supported ABI -} - -impl S { - extern "amdgpu-kernel" fn imu() {} //~ ERROR amdgpu-kernel ABI is experimental - //~^ ERROR is not a supported ABI -} - -type TAU = extern "amdgpu-kernel" fn(); //~ ERROR amdgpu-kernel ABI is experimental - -extern "amdgpu-kernel" {} //~ ERROR amdgpu-kernel ABI is experimental -//~^ ERROR is not a supported ABI diff --git a/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr b/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr deleted file mode 100644 index c5ae52c789b67..0000000000000 --- a/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr +++ /dev/null @@ -1,104 +0,0 @@ -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:8 - | -LL | extern "amdgpu-kernel" fn fu() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:11:12 - | -LL | extern "amdgpu-kernel" fn mu(); - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:12 - | -LL | extern "amdgpu-kernel" fn dmu() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:12 - | -LL | extern "amdgpu-kernel" fn mu() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:12 - | -LL | extern "amdgpu-kernel" fn imu() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:27:19 - | -LL | type TAU = extern "amdgpu-kernel" fn(); - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:8 - | -LL | extern "amdgpu-kernel" {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` 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[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:1 - | -LL | extern "amdgpu-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:1 - | -LL | extern "amdgpu-kernel" fn fu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:5 - | -LL | extern "amdgpu-kernel" fn dmu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:5 - | -LL | extern "amdgpu-kernel" fn mu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:5 - | -LL | extern "amdgpu-kernel" fn imu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 12 previous errors - -Some errors have detailed explanations: E0570, E0658. -For more information about an error, try `rustc --explain E0570`. From 0b2579a1b617e83da98008bac9b93c36c43a8f4b Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 24 Jan 2024 20:38:21 +0100 Subject: [PATCH 124/246] Make `PatternColumn` generic in `Cx` --- compiler/rustc_pattern_analysis/src/lints.rs | 43 +++++++++----------- compiler/rustc_pattern_analysis/src/rustc.rs | 4 -- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 4bfe7dfb072c4..e3d218d71c301 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -1,12 +1,12 @@ use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::ErrorGuaranteed; +use crate::constructor::{Constructor, SplitConstructorSet}; use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered}; -use crate::pat::PatOrWild; -use crate::rustc::{ - Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, RustcMatchCheckCtxt, - SplitConstructorSet, WitnessPat, -}; +use crate::pat::{DeconstructedPat, PatOrWild}; +use crate::rustc::{MatchCtxt, RevealedTy, RustcMatchCheckCtxt, WitnessPat}; +use crate::usefulness::PlaceCtxt; +use crate::{MatchArm, TypeCx}; /// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that /// inspect the same subvalue/place". @@ -19,12 +19,12 @@ use crate::rustc::{ /// /// This is not used in the usefulness algorithm; only in lints. #[derive(Debug)] -pub(crate) struct PatternColumn<'p, 'tcx> { - patterns: Vec<&'p DeconstructedPat<'p, 'tcx>>, +pub(crate) struct PatternColumn<'p, Cx: TypeCx> { + patterns: Vec<&'p DeconstructedPat<'p, Cx>>, } -impl<'p, 'tcx> PatternColumn<'p, 'tcx> { - pub(crate) fn new(arms: &[MatchArm<'p, 'tcx>]) -> Self { +impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { + pub(crate) fn new(arms: &[MatchArm<'p, Cx>]) -> Self { let patterns = Vec::with_capacity(arms.len()); let mut column = PatternColumn { patterns }; for arm in arms { @@ -34,7 +34,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { } /// Pushes a pattern onto the column, expanding any or-patterns into its subpatterns. /// Internal method, prefer [`PatternColumn::new`]. - fn expand_and_push(&mut self, pat: PatOrWild<'p, RustcMatchCheckCtxt<'p, 'tcx>>) { + fn expand_and_push(&mut self, pat: PatOrWild<'p, Cx>) { // We flatten or-patterns and skip algorithm-generated wildcards. if pat.is_or_pat() { self.patterns.extend( @@ -45,15 +45,12 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { } } - fn head_ty(&self) -> Option> { - self.patterns.first().map(|pat| *pat.ty()) + fn head_ty(&self) -> Option<&Cx::Ty> { + self.patterns.first().map(|pat| pat.ty()) } /// Do constructor splitting on the constructors of the column. - fn analyze_ctors( - &self, - pcx: &PlaceCtxt<'_, 'p, 'tcx>, - ) -> Result, ErrorGuaranteed> { + fn analyze_ctors(&self, pcx: &PlaceCtxt<'_, Cx>) -> Result, Cx::Error> { let column_ctors = self.patterns.iter().map(|p| p.ctor()); let ctors_for_ty = &pcx.ctors_for_ty()?; Ok(ctors_for_ty.split(column_ctors)) @@ -66,9 +63,9 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { /// which may change the lengths. fn specialize( &self, - pcx: &PlaceCtxt<'_, 'p, 'tcx>, - ctor: &Constructor<'p, 'tcx>, - ) -> Vec> { + pcx: &PlaceCtxt<'_, Cx>, + ctor: &Constructor, + ) -> Vec> { let arity = ctor.arity(pcx); if arity == 0 { return Vec::new(); @@ -96,9 +93,9 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { #[instrument(level = "debug", skip(cx), ret)] fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( cx: MatchCtxt<'a, 'p, 'tcx>, - column: &PatternColumn<'p, 'tcx>, + column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, ) -> Result>, ErrorGuaranteed> { - let Some(ty) = column.head_ty() else { + let Some(&ty) = column.head_ty() else { return Ok(Vec::new()); }; let pcx = &PlaceCtxt::new_dummy(cx, &ty); @@ -143,8 +140,8 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>( cx: MatchCtxt<'a, 'p, 'tcx>, - arms: &[MatchArm<'p, 'tcx>], - pat_column: &PatternColumn<'p, 'tcx>, + arms: &[MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>], + pat_column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, scrut_ty: RevealedTy<'tcx>, ) -> Result<(), ErrorGuaranteed> { let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx; diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 223d6cefc83fe..4fb76a891b534 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -31,10 +31,6 @@ pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>; -pub(crate) type PlaceCtxt<'a, 'p, 'tcx> = - crate::usefulness::PlaceCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>; -pub(crate) type SplitConstructorSet<'p, 'tcx> = - crate::constructor::SplitConstructorSet>; pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type UsefulnessReport<'p, 'tcx> = crate::usefulness::UsefulnessReport<'p, RustcMatchCheckCtxt<'p, 'tcx>>; From cb0e8c508c98590346f5943f1ebd0e901acf87f9 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 24 Jan 2024 21:16:57 +0100 Subject: [PATCH 125/246] Limit the use of `PlaceCtxt` --- .../rustc_pattern_analysis/src/constructor.rs | 16 ++++----- compiler/rustc_pattern_analysis/src/lib.rs | 2 +- compiler/rustc_pattern_analysis/src/lints.rs | 34 +++++++++---------- compiler/rustc_pattern_analysis/src/pat.rs | 7 ++-- compiler/rustc_pattern_analysis/src/rustc.rs | 1 - .../rustc_pattern_analysis/src/usefulness.rs | 34 ++++++++----------- 6 files changed, 42 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 4996015f86345..df5bf3111adc4 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -163,7 +163,6 @@ use self::MaybeInfiniteInt::*; use self::SliceKind::*; use crate::index; -use crate::usefulness::PlaceCtxt; use crate::TypeCx; /// Whether we have seen a constructor in the column or not. @@ -818,8 +817,8 @@ impl Constructor { /// The number of fields for this constructor. This must be kept in sync with /// `Fields::wildcards`. - pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, Cx>) -> usize { - pcx.ctor_arity(self) + pub(crate) fn arity(&self, cx: &Cx, ty: &Cx::Ty) -> usize { + cx.ctor_arity(self, ty) } /// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`. @@ -827,12 +826,11 @@ impl Constructor { /// this checks for inclusion. // We inline because this has a single call site in `Matrix::specialize_constructor`. #[inline] - pub(crate) fn is_covered_by(&self, pcx: &PlaceCtxt<'_, Cx>, other: &Self) -> bool { + pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> bool { match (self, other) { - (Wildcard, _) => pcx - .mcx - .tycx - .bug(format_args!("Constructor splitting should not have returned `Wildcard`")), + (Wildcard, _) => { + cx.bug(format_args!("Constructor splitting should not have returned `Wildcard`")) + } // Wildcards cover anything (_, Wildcard) => true, // Only a wildcard pattern can match these special constructors. @@ -873,7 +871,7 @@ impl Constructor { (Opaque(self_id), Opaque(other_id)) => self_id == other_id, (Opaque(..), _) | (_, Opaque(..)) => false, - _ => pcx.mcx.tycx.bug(format_args!( + _ => cx.bug(format_args!( "trying to compare incompatible constructors {self:?} and {other:?}" )), } diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index a53d7a0d8096a..866eb67ea9971 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -183,7 +183,7 @@ pub fn analyze_match<'p, 'tcx>( // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() { let pat_column = PatternColumn::new(arms); - lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)?; + lint_nonexhaustive_missing_variants(tycx, arms, &pat_column, scrut_ty)?; } Ok(report) diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index e3d218d71c301..4cbd5e70189f2 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -4,8 +4,7 @@ use rustc_span::ErrorGuaranteed; use crate::constructor::{Constructor, SplitConstructorSet}; use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered}; use crate::pat::{DeconstructedPat, PatOrWild}; -use crate::rustc::{MatchCtxt, RevealedTy, RustcMatchCheckCtxt, WitnessPat}; -use crate::usefulness::PlaceCtxt; +use crate::rustc::{RevealedTy, RustcMatchCheckCtxt, WitnessPat}; use crate::{MatchArm, TypeCx}; /// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that @@ -50,9 +49,9 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { } /// Do constructor splitting on the constructors of the column. - fn analyze_ctors(&self, pcx: &PlaceCtxt<'_, Cx>) -> Result, Cx::Error> { + fn analyze_ctors(&self, cx: &Cx, ty: &Cx::Ty) -> Result, Cx::Error> { let column_ctors = self.patterns.iter().map(|p| p.ctor()); - let ctors_for_ty = &pcx.ctors_for_ty()?; + let ctors_for_ty = cx.ctors_for_ty(ty)?; Ok(ctors_for_ty.split(column_ctors)) } @@ -63,10 +62,11 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { /// which may change the lengths. fn specialize( &self, - pcx: &PlaceCtxt<'_, Cx>, + cx: &Cx, + ty: &Cx::Ty, ctor: &Constructor, ) -> Vec> { - let arity = ctor.arity(pcx); + let arity = ctor.arity(cx, ty); if arity == 0 { return Vec::new(); } @@ -77,7 +77,7 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { let mut specialized_columns: Vec<_> = (0..arity).map(|_| Self { patterns: Vec::new() }).collect(); let relevant_patterns = - self.patterns.iter().filter(|pat| ctor.is_covered_by(pcx, pat.ctor())); + self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor())); for pat in relevant_patterns { let specialized = pat.specialize(ctor, arity); for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) { @@ -92,15 +92,14 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { /// in a given column. #[instrument(level = "debug", skip(cx), ret)] fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( - cx: MatchCtxt<'a, 'p, 'tcx>, + cx: &RustcMatchCheckCtxt<'p, 'tcx>, column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, ) -> Result>, ErrorGuaranteed> { let Some(&ty) = column.head_ty() else { return Ok(Vec::new()); }; - let pcx = &PlaceCtxt::new_dummy(cx, &ty); - let set = column.analyze_ctors(pcx)?; + let set = column.analyze_ctors(cx, &ty)?; if set.present.is_empty() { // We can't consistently handle the case where no constructors are present (since this would // require digging deep through any type in case there's a non_exhaustive enum somewhere), @@ -109,20 +108,20 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( } let mut witnesses = Vec::new(); - if cx.tycx.is_foreign_non_exhaustive_enum(ty) { + if cx.is_foreign_non_exhaustive_enum(ty) { witnesses.extend( set.missing .into_iter() // This will list missing visible variants. .filter(|c| !matches!(c, Constructor::Hidden | Constructor::NonExhaustive)) - .map(|missing_ctor| WitnessPat::wild_from_ctor(pcx, missing_ctor)), + .map(|missing_ctor| WitnessPat::wild_from_ctor(cx, missing_ctor, ty)), ) } // Recurse into the fields. for ctor in set.present { - let specialized_columns = column.specialize(pcx, &ctor); - let wild_pat = WitnessPat::wild_from_ctor(pcx, ctor); + let specialized_columns = column.specialize(cx, &ty, &ctor); + let wild_pat = WitnessPat::wild_from_ctor(cx, ctor, ty); for (i, col_i) in specialized_columns.iter().enumerate() { // Compute witnesses for each column. let wits_for_col_i = collect_nonexhaustive_missing_variants(cx, col_i)?; @@ -138,18 +137,17 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( Ok(witnesses) } -pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>( - cx: MatchCtxt<'a, 'p, 'tcx>, +pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( + rcx: &RustcMatchCheckCtxt<'p, 'tcx>, arms: &[MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>], pat_column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, scrut_ty: RevealedTy<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx; if !matches!( rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).0, rustc_session::lint::Level::Allow ) { - let witnesses = collect_nonexhaustive_missing_variants(cx, pat_column)?; + let witnesses = collect_nonexhaustive_missing_variants(rcx, pat_column)?; if !witnesses.is_empty() { // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns` // is not exhaustive enough. diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index d476766d466f2..c94d8b9353589 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -6,7 +6,6 @@ use std::fmt; use smallvec::{smallvec, SmallVec}; use crate::constructor::{Constructor, Slice, SliceKind}; -use crate::usefulness::PlaceCtxt; use crate::{Captures, TypeCx}; use self::Constructor::*; @@ -331,9 +330,9 @@ impl WitnessPat { /// Construct a pattern that matches everything that starts with this constructor. /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern /// `Some(_)`. - pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, Cx>, ctor: Constructor) -> Self { - let fields = pcx.ctor_sub_tys(&ctor).map(|ty| Self::wildcard(ty)).collect(); - Self::new(ctor, fields, pcx.ty.clone()) + pub(crate) fn wild_from_ctor(cx: &Cx, ctor: Constructor, ty: Cx::Ty) -> Self { + let fields = cx.ctor_sub_tys(&ctor, &ty).map(|ty| Self::wildcard(ty)).collect(); + Self::new(ctor, fields, ty) } pub fn ctor(&self) -> &Constructor { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 4fb76a891b534..ec37e20211860 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -30,7 +30,6 @@ pub type ConstructorSet<'p, 'tcx> = pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>; -pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>; pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type UsefulnessReport<'p, 'tcx> = crate::usefulness::UsefulnessReport<'p, RustcMatchCheckCtxt<'p, 'tcx>>; diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index b15de1c0ca9d7..62d17ca450982 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -731,20 +731,19 @@ pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { } /// Context that provides information local to a place under investigation. -pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> { - pub(crate) mcx: MatchCtxt<'a, Cx>, +struct PlaceCtxt<'a, Cx: TypeCx> { + mcx: MatchCtxt<'a, Cx>, /// Type of the place under investigation. - pub(crate) ty: &'a Cx::Ty, + ty: &'a Cx::Ty, } +impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {} impl<'a, Cx: TypeCx> Clone for PlaceCtxt<'a, Cx> { fn clone(&self) -> Self { Self { mcx: self.mcx, ty: self.ty } } } -impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {} - impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("PlaceCtxt").field("ty", self.ty).finish() @@ -752,24 +751,21 @@ impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> { } impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { - /// A `PlaceCtxt` when code other than `is_useful` needs one. - #[cfg_attr(not(feature = "rustc"), allow(dead_code))] - pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: &'a Cx::Ty) -> Self { - PlaceCtxt { mcx, ty } - } - - pub(crate) fn ctor_arity(&self, ctor: &Constructor) -> usize { + fn ctor_arity(&self, ctor: &Constructor) -> usize { self.mcx.tycx.ctor_arity(ctor, self.ty) } - pub(crate) fn ctor_sub_tys( + fn ctor_sub_tys( &'a self, ctor: &'a Constructor, ) -> impl Iterator + ExactSizeIterator + Captures<'a> { self.mcx.tycx.ctor_sub_tys(ctor, self.ty) } - pub(crate) fn ctors_for_ty(&self) -> Result, Cx::Error> { + fn ctors_for_ty(&self) -> Result, Cx::Error> { self.mcx.tycx.ctors_for_ty(self.ty) } + fn wild_from_ctor(&self, ctor: Constructor) -> WitnessPat { + WitnessPat::wild_from_ctor(self.mcx.tycx, ctor, self.ty.clone()) + } } /// Serves two purposes: @@ -1089,7 +1085,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant, }; for (i, row) in self.rows().enumerate() { - if ctor.is_covered_by(pcx, row.head().ctor()) { + if ctor.is_covered_by(pcx.mcx.tycx, row.head().ctor()) { let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i); matrix.expand_and_push(new_row); } @@ -1240,7 +1236,7 @@ impl WitnessStack { /// ``` fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor) { let len = self.0.len(); - let arity = ctor.arity(pcx); + let arity = pcx.ctor_arity(ctor); let fields = self.0.drain((len - arity)..).rev().collect(); let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty.clone()); self.0.push(pat); @@ -1315,20 +1311,20 @@ impl WitnessMatrix { *self = Self::empty(); } else if !report_individual_missing_ctors { // Report `_` as missing. - let pat = WitnessPat::wild_from_ctor(pcx, Constructor::Wildcard); + let pat = pcx.wild_from_ctor(Constructor::Wildcard); self.push_pattern(pat); } else if missing_ctors.iter().any(|c| c.is_non_exhaustive()) { // We need to report a `_` anyway, so listing other constructors would be redundant. // `NonExhaustive` is displayed as `_` just like `Wildcard`, but it will be picked // up by diagnostics to add a note about why `_` is required here. - let pat = WitnessPat::wild_from_ctor(pcx, Constructor::NonExhaustive); + let pat = pcx.wild_from_ctor(Constructor::NonExhaustive); self.push_pattern(pat); } else { // For each missing constructor `c`, we add a `c(_, _, _)` witness appropriately // filled with wildcards. let mut ret = Self::empty(); for ctor in missing_ctors { - let pat = WitnessPat::wild_from_ctor(pcx, ctor.clone()); + let pat = pcx.wild_from_ctor(ctor.clone()); // Clone `self` and add `c(_, _, _)` to each of its witnesses. let mut wit_matrix = self.clone(); wit_matrix.push_pattern(pat); From 83e88c6dfcd7aecf1c49d73e2d9e761d15302341 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 24 Jan 2024 20:57:11 +0100 Subject: [PATCH 126/246] Repurpose `MatchCtxt` for usefulness only --- compiler/rustc_pattern_analysis/src/lib.rs | 18 +------------ .../rustc_pattern_analysis/src/usefulness.rs | 26 ++++++++++++++----- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 866eb67ea9971..99c32de74828a 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -135,20 +135,6 @@ pub trait TypeCx: Sized + fmt::Debug { } } -/// Context that provides information global to a match. -pub struct MatchCtxt<'a, Cx: TypeCx> { - /// The context for type information. - pub tycx: &'a Cx, -} - -impl<'a, Cx: TypeCx> Clone for MatchCtxt<'a, Cx> { - fn clone(&self) -> Self { - Self { tycx: self.tycx } - } -} - -impl<'a, Cx: TypeCx> Copy for MatchCtxt<'a, Cx> {} - /// The arm of a match expression. #[derive(Debug)] pub struct MatchArm<'p, Cx: TypeCx> { @@ -175,9 +161,7 @@ pub fn analyze_match<'p, 'tcx>( ) -> Result, ErrorGuaranteed> { let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee); - let cx = MatchCtxt { tycx }; - - let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity)?; + let report = compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity)?; // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 62d17ca450982..d2cf2f72a7d9b 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -719,7 +719,7 @@ use std::fmt; use crate::constructor::{Constructor, ConstructorSet, IntRange}; use crate::pat::{DeconstructedPat, PatOrWild, WitnessPat}; -use crate::{Captures, MatchArm, MatchCtxt, TypeCx}; +use crate::{Captures, MatchArm, TypeCx}; use self::ValidityConstraint::*; @@ -730,9 +730,22 @@ pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { f() } +/// Context that provides information for usefulness checking. +pub struct UsefulnessCtxt<'a, Cx: TypeCx> { + /// The context for type information. + pub tycx: &'a Cx, +} + +impl<'a, Cx: TypeCx> Copy for UsefulnessCtxt<'a, Cx> {} +impl<'a, Cx: TypeCx> Clone for UsefulnessCtxt<'a, Cx> { + fn clone(&self) -> Self { + Self { tycx: self.tycx } + } +} + /// Context that provides information local to a place under investigation. struct PlaceCtxt<'a, Cx: TypeCx> { - mcx: MatchCtxt<'a, Cx>, + mcx: UsefulnessCtxt<'a, Cx>, /// Type of the place under investigation. ty: &'a Cx::Ty, } @@ -1358,7 +1371,7 @@ impl WitnessMatrix { /// We can however get false negatives because exhaustiveness does not explore all cases. See the /// section on relevancy at the top of the file. fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( - mcx: MatchCtxt<'_, Cx>, + mcx: UsefulnessCtxt<'_, Cx>, overlap_range: IntRange, matrix: &Matrix<'p, Cx>, specialized_matrix: &Matrix<'p, Cx>, @@ -1431,7 +1444,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( /// This is all explained at the top of the file. #[instrument(level = "debug", skip(mcx, is_top_level), ret)] fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( - mcx: MatchCtxt<'a, Cx>, + mcx: UsefulnessCtxt<'a, Cx>, matrix: &mut Matrix<'p, Cx>, is_top_level: bool, ) -> Result, Cx::Error> { @@ -1588,13 +1601,14 @@ pub struct UsefulnessReport<'p, Cx: TypeCx> { } /// Computes whether a match is exhaustive and which of its arms are useful. -#[instrument(skip(cx, arms), level = "debug")] +#[instrument(skip(tycx, arms), level = "debug")] pub fn compute_match_usefulness<'p, Cx: TypeCx>( - cx: MatchCtxt<'_, Cx>, + tycx: &Cx, arms: &[MatchArm<'p, Cx>], scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, ) -> Result, Cx::Error> { + let cx = UsefulnessCtxt { tycx }; let mut matrix = Matrix::new(arms, scrut_ty, scrut_validity); let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness(cx, &mut matrix, true)?; From 6ef836246bc48387bfdbe2bde951037c71350c00 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 24 Jan 2024 21:29:58 +0100 Subject: [PATCH 127/246] Make `PatternColumn` part of the public API --- .../rustc_pattern_analysis/src/constructor.rs | 10 +-- compiler/rustc_pattern_analysis/src/lib.rs | 4 +- compiler/rustc_pattern_analysis/src/lints.rs | 87 +----------------- .../rustc_pattern_analysis/src/pat_column.rs | 90 +++++++++++++++++++ 4 files changed, 101 insertions(+), 90 deletions(-) create mode 100644 compiler/rustc_pattern_analysis/src/pat_column.rs diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index df5bf3111adc4..4be564b1d7b1e 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -948,10 +948,10 @@ pub enum ConstructorSet { /// of the `ConstructorSet` for the type, yet if we forgot to include them in `present` we would be /// ignoring any row with `Opaque`s in the algorithm. Hence the importance of point 4. #[derive(Debug)] -pub(crate) struct SplitConstructorSet { - pub(crate) present: SmallVec<[Constructor; 1]>, - pub(crate) missing: Vec>, - pub(crate) missing_empty: Vec>, +pub struct SplitConstructorSet { + pub present: SmallVec<[Constructor; 1]>, + pub missing: Vec>, + pub missing_empty: Vec>, } impl ConstructorSet { @@ -960,7 +960,7 @@ impl ConstructorSet { /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation /// and its invariants. #[instrument(level = "debug", skip(self, ctors), ret)] - pub(crate) fn split<'a>( + pub fn split<'a>( &self, ctors: impl Iterator> + Clone, ) -> SplitConstructorSet diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 99c32de74828a..3d0eb117d174f 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -6,6 +6,7 @@ pub mod errors; #[cfg(feature = "rustc")] pub(crate) mod lints; pub mod pat; +pub mod pat_column; #[cfg(feature = "rustc")] pub mod rustc; pub mod usefulness; @@ -67,8 +68,9 @@ use rustc_span::ErrorGuaranteed; use crate::constructor::{Constructor, ConstructorSet, IntRange}; #[cfg(feature = "rustc")] -use crate::lints::{lint_nonexhaustive_missing_variants, PatternColumn}; +use crate::lints::lint_nonexhaustive_missing_variants; use crate::pat::DeconstructedPat; +use crate::pat_column::PatternColumn; #[cfg(feature = "rustc")] use crate::rustc::RustcMatchCheckCtxt; #[cfg(feature = "rustc")] diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 4cbd5e70189f2..3f1497540d25e 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -1,92 +1,11 @@ use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::ErrorGuaranteed; -use crate::constructor::{Constructor, SplitConstructorSet}; +use crate::constructor::Constructor; use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered}; -use crate::pat::{DeconstructedPat, PatOrWild}; +use crate::pat_column::PatternColumn; use crate::rustc::{RevealedTy, RustcMatchCheckCtxt, WitnessPat}; -use crate::{MatchArm, TypeCx}; - -/// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that -/// inspect the same subvalue/place". -/// This is used to traverse patterns column-by-column for lints. Despite similarities with the -/// algorithm in [`crate::usefulness`], this does a different traversal. Notably this is linear in -/// the depth of patterns, whereas `compute_exhaustiveness_and_usefulness` is worst-case exponential -/// (exhaustiveness is NP-complete). The core difference is that we treat sub-columns separately. -/// -/// This must not contain an or-pattern. `expand_and_push` takes care to expand them. -/// -/// This is not used in the usefulness algorithm; only in lints. -#[derive(Debug)] -pub(crate) struct PatternColumn<'p, Cx: TypeCx> { - patterns: Vec<&'p DeconstructedPat<'p, Cx>>, -} - -impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { - pub(crate) fn new(arms: &[MatchArm<'p, Cx>]) -> Self { - let patterns = Vec::with_capacity(arms.len()); - let mut column = PatternColumn { patterns }; - for arm in arms { - column.expand_and_push(PatOrWild::Pat(arm.pat)); - } - column - } - /// Pushes a pattern onto the column, expanding any or-patterns into its subpatterns. - /// Internal method, prefer [`PatternColumn::new`]. - fn expand_and_push(&mut self, pat: PatOrWild<'p, Cx>) { - // We flatten or-patterns and skip algorithm-generated wildcards. - if pat.is_or_pat() { - self.patterns.extend( - pat.flatten_or_pat().into_iter().filter_map(|pat_or_wild| pat_or_wild.as_pat()), - ) - } else if let Some(pat) = pat.as_pat() { - self.patterns.push(pat) - } - } - - fn head_ty(&self) -> Option<&Cx::Ty> { - self.patterns.first().map(|pat| pat.ty()) - } - - /// Do constructor splitting on the constructors of the column. - fn analyze_ctors(&self, cx: &Cx, ty: &Cx::Ty) -> Result, Cx::Error> { - let column_ctors = self.patterns.iter().map(|p| p.ctor()); - let ctors_for_ty = cx.ctors_for_ty(ty)?; - Ok(ctors_for_ty.split(column_ctors)) - } - - /// Does specialization: given a constructor, this takes the patterns from the column that match - /// the constructor, and outputs their fields. - /// This returns one column per field of the constructor. They usually all have the same length - /// (the number of patterns in `self` that matched `ctor`), except that we expand or-patterns - /// which may change the lengths. - fn specialize( - &self, - cx: &Cx, - ty: &Cx::Ty, - ctor: &Constructor, - ) -> Vec> { - let arity = ctor.arity(cx, ty); - if arity == 0 { - return Vec::new(); - } - - // We specialize the column by `ctor`. This gives us `arity`-many columns of patterns. These - // columns may have different lengths in the presence of or-patterns (this is why we can't - // reuse `Matrix`). - let mut specialized_columns: Vec<_> = - (0..arity).map(|_| Self { patterns: Vec::new() }).collect(); - let relevant_patterns = - self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor())); - for pat in relevant_patterns { - let specialized = pat.specialize(ctor, arity); - for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) { - column.expand_and_push(subpat); - } - } - specialized_columns - } -} +use crate::MatchArm; /// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned /// in a given column. diff --git a/compiler/rustc_pattern_analysis/src/pat_column.rs b/compiler/rustc_pattern_analysis/src/pat_column.rs new file mode 100644 index 0000000000000..3cacfc491b981 --- /dev/null +++ b/compiler/rustc_pattern_analysis/src/pat_column.rs @@ -0,0 +1,90 @@ +use crate::constructor::{Constructor, SplitConstructorSet}; +use crate::pat::{DeconstructedPat, PatOrWild}; +use crate::{Captures, MatchArm, TypeCx}; + +/// A column of patterns in a match, where a column is the intuitive notion of "subpatterns that +/// inspect the same subvalue/place". +/// This is used to traverse patterns column-by-column for lints. Despite similarities with the +/// algorithm in [`crate::usefulness`], this does a different traversal. Notably this is linear in +/// the depth of patterns, whereas `compute_exhaustiveness_and_usefulness` is worst-case exponential +/// (exhaustiveness is NP-complete). The core difference is that we treat sub-columns separately. +/// +/// This is not used in the usefulness algorithm; only in lints. +#[derive(Debug)] +pub struct PatternColumn<'p, Cx: TypeCx> { + /// This must not contain an or-pattern. `expand_and_push` takes care to expand them. + patterns: Vec<&'p DeconstructedPat<'p, Cx>>, +} + +impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { + pub fn new(arms: &[MatchArm<'p, Cx>]) -> Self { + let patterns = Vec::with_capacity(arms.len()); + let mut column = PatternColumn { patterns }; + for arm in arms { + column.expand_and_push(PatOrWild::Pat(arm.pat)); + } + column + } + /// Pushes a pattern onto the column, expanding any or-patterns into its subpatterns. + /// Internal method, prefer [`PatternColumn::new`]. + fn expand_and_push(&mut self, pat: PatOrWild<'p, Cx>) { + // We flatten or-patterns and skip algorithm-generated wildcards. + if pat.is_or_pat() { + self.patterns.extend( + pat.flatten_or_pat().into_iter().filter_map(|pat_or_wild| pat_or_wild.as_pat()), + ) + } else if let Some(pat) = pat.as_pat() { + self.patterns.push(pat) + } + } + + pub fn head_ty(&self) -> Option<&Cx::Ty> { + self.patterns.first().map(|pat| pat.ty()) + } + pub fn iter<'a>(&'a self) -> impl Iterator> + Captures<'a> { + self.patterns.iter().copied() + } + + /// Do constructor splitting on the constructors of the column. + pub fn analyze_ctors( + &self, + cx: &Cx, + ty: &Cx::Ty, + ) -> Result, Cx::Error> { + let column_ctors = self.patterns.iter().map(|p| p.ctor()); + let ctors_for_ty = cx.ctors_for_ty(ty)?; + Ok(ctors_for_ty.split(column_ctors)) + } + + /// Does specialization: given a constructor, this takes the patterns from the column that match + /// the constructor, and outputs their fields. + /// This returns one column per field of the constructor. They usually all have the same length + /// (the number of patterns in `self` that matched `ctor`), except that we expand or-patterns + /// which may change the lengths. + pub fn specialize( + &self, + cx: &Cx, + ty: &Cx::Ty, + ctor: &Constructor, + ) -> Vec> { + let arity = ctor.arity(cx, ty); + if arity == 0 { + return Vec::new(); + } + + // We specialize the column by `ctor`. This gives us `arity`-many columns of patterns. These + // columns may have different lengths in the presence of or-patterns (this is why we can't + // reuse `Matrix`). + let mut specialized_columns: Vec<_> = + (0..arity).map(|_| Self { patterns: Vec::new() }).collect(); + let relevant_patterns = + self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor())); + for pat in relevant_patterns { + let specialized = pat.specialize(ctor, arity); + for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) { + column.expand_and_push(subpat); + } + } + specialized_columns + } +} From 59031429c5ad9f4002e3f860ce2ef31e90368b6c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 24 Jan 2024 21:51:17 +0100 Subject: [PATCH 128/246] Separate `PlaceCtxt` from `UsefulnessCtxt` --- .../rustc_pattern_analysis/src/usefulness.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index d2cf2f72a7d9b..3d45d032a9934 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -745,7 +745,7 @@ impl<'a, Cx: TypeCx> Clone for UsefulnessCtxt<'a, Cx> { /// Context that provides information local to a place under investigation. struct PlaceCtxt<'a, Cx: TypeCx> { - mcx: UsefulnessCtxt<'a, Cx>, + cx: &'a Cx, /// Type of the place under investigation. ty: &'a Cx::Ty, } @@ -753,7 +753,7 @@ struct PlaceCtxt<'a, Cx: TypeCx> { impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {} impl<'a, Cx: TypeCx> Clone for PlaceCtxt<'a, Cx> { fn clone(&self) -> Self { - Self { mcx: self.mcx, ty: self.ty } + Self { cx: self.cx, ty: self.ty } } } @@ -765,19 +765,19 @@ impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> { impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { fn ctor_arity(&self, ctor: &Constructor) -> usize { - self.mcx.tycx.ctor_arity(ctor, self.ty) + self.cx.ctor_arity(ctor, self.ty) } fn ctor_sub_tys( &'a self, ctor: &'a Constructor, ) -> impl Iterator + ExactSizeIterator + Captures<'a> { - self.mcx.tycx.ctor_sub_tys(ctor, self.ty) + self.cx.ctor_sub_tys(ctor, self.ty) } fn ctors_for_ty(&self) -> Result, Cx::Error> { - self.mcx.tycx.ctors_for_ty(self.ty) + self.cx.ctors_for_ty(self.ty) } fn wild_from_ctor(&self, ctor: Constructor) -> WitnessPat { - WitnessPat::wild_from_ctor(self.mcx.tycx, ctor, self.ty.clone()) + WitnessPat::wild_from_ctor(self.cx, ctor, self.ty.clone()) } } @@ -1098,7 +1098,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant, }; for (i, row) in self.rows().enumerate() { - if ctor.is_covered_by(pcx.mcx.tycx, row.head().ctor()) { + if ctor.is_covered_by(pcx.cx, row.head().ctor()) { let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i); matrix.expand_and_push(new_row); } @@ -1478,7 +1478,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( }; debug!("ty: {ty:?}"); - let pcx = &PlaceCtxt { mcx, ty: &ty }; + let pcx = &PlaceCtxt { cx: mcx.tycx, ty: &ty }; let ctors_for_ty = pcx.ctors_for_ty()?; // Whether the place/column we are inspecting is known to contain valid data. From 233b21329c1c9236f7923e0cf574119c200e60b7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jan 2024 15:53:07 +0000 Subject: [PATCH 129/246] Move predicate, region, and const stuff into their own modules in middle --- compiler/rustc_middle/src/ty/consts.rs | 3 +- compiler/rustc_middle/src/ty/mod.rs | 718 +------------- compiler/rustc_middle/src/ty/predicate.rs | 1062 +++++++++++++++++++++ compiler/rustc_middle/src/ty/region.rs | 399 ++++++++ compiler/rustc_middle/src/ty/sty.rs | 765 +-------------- 5 files changed, 1491 insertions(+), 1456 deletions(-) create mode 100644 compiler/rustc_middle/src/ty/predicate.rs create mode 100644 compiler/rustc_middle/src/ty/region.rs diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 6ec1dec97816c..a930c7e8ebf80 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -7,6 +7,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_macros::HashStable; +use rustc_type_ir::ConstKind as IrConstKind; use rustc_type_ir::{ConstTy, IntoKind, TypeFlags, WithCachedTypeInfo}; mod int; @@ -19,7 +20,7 @@ use rustc_span::Span; use rustc_span::DUMMY_SP; pub use valtree::*; -use super::sty::ConstKind; +pub type ConstKind<'tcx> = IrConstKind>; /// Use this rather than `ConstData`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dabd50a32b95c..8e51db82f95ae 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -80,23 +80,34 @@ pub use self::closure::{ CapturedPlace, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL, }; -pub use self::consts::{Const, ConstData, ConstInt, Expr, ScalarInt, UnevaluatedConst, ValTree}; +pub use self::consts::{ + Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree, +}; pub use self::context::{ tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, }; pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; pub use self::list::List; pub use self::parameterized::ParameterizedOverTcx; +pub use self::predicate::{ + Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialProjection, + ExistentialTraitRef, NormalizesTo, OutlivesPredicate, PolyCoercePredicate, + PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef, + PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate, + PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate, + RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitPredicate, + TraitRef, TypeOutlivesPredicate, +}; +pub use self::region::{ + BoundRegion, BoundRegionKind, BoundRegionKind::*, EarlyParamRegion, LateParamRegion, Region, + RegionKind, RegionVid, +}; pub use self::rvalue_scopes::RvalueScopes; -pub use self::sty::BoundRegionKind::*; pub use self::sty::{ - AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, - BoundVariableKind, CanonicalPolyFnSig, ClauseKind, ClosureArgs, ClosureArgsParts, ConstKind, - CoroutineArgs, CoroutineArgsParts, EarlyParamRegion, ExistentialPredicate, - ExistentialProjection, ExistentialTraitRef, FnSig, GenSig, InlineConstArgs, - InlineConstArgsParts, LateParamRegion, ParamConst, ParamTy, PolyExistentialPredicate, - PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyTraitRef, PredicateKind, - Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo, + AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, + ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, FnSig, GenSig, + InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, + UpvarArgs, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -139,6 +150,8 @@ mod instance; mod list; mod opaque_types; mod parameterized; +mod predicate; +mod region; mod rvalue_scopes; mod structural_impls; #[allow(hidden_glob_reexports)] @@ -491,165 +504,6 @@ impl EarlyParamRegion { } } -/// A statement that can be proven by a trait solver. This includes things that may -/// show up in where clauses, such as trait predicates and projection predicates, -/// and also things that are emitted as part of type checking such as `ObjectSafe` -/// predicate which is emitted when a type is coerced to a trait object. -/// -/// Use this rather than `PredicateKind`, whenever possible. -#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] -#[rustc_pass_by_value] -pub struct Predicate<'tcx>( - Interned<'tcx, WithCachedTypeInfo>>>, -); - -impl<'tcx> Predicate<'tcx> { - /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. - #[inline] - pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { - self.0.internee - } - - #[inline(always)] - pub fn flags(self) -> TypeFlags { - self.0.flags - } - - #[inline(always)] - pub fn outer_exclusive_binder(self) -> DebruijnIndex { - self.0.outer_exclusive_binder - } - - /// Flips the polarity of a Predicate. - /// - /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. - pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option> { - let kind = self - .kind() - .map_bound(|kind| match kind { - PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity, - })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity: polarity.flip()?, - }))), - - _ => None, - }) - .transpose()?; - - Some(tcx.mk_predicate(kind)) - } - - #[instrument(level = "debug", skip(tcx), ret)] - pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { - match self.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { - tcx.trait_is_coinductive(data.def_id()) - } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => true, - _ => false, - } - } - - /// Whether this projection can be soundly normalized. - /// - /// Wf predicates must not be normalized, as normalization - /// can remove required bounds which would cause us to - /// unsoundly accept some programs. See #91068. - #[inline] - pub fn allow_normalization(self) -> bool { - match self.kind().skip_binder() { - PredicateKind::Clause(ClauseKind::WellFormed(_)) => false, - // `NormalizesTo` is only used in the new solver, so this shouldn't - // matter. Normalizing `term` would be 'wrong' however, as it changes whether - // `normalizes-to(::Assoc, ::Assoc)` holds. - PredicateKind::NormalizesTo(..) => false, - PredicateKind::Clause(ClauseKind::Trait(_)) - | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) - | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) - | PredicateKind::Clause(ClauseKind::Projection(_)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::AliasRelate(..) - | PredicateKind::ObjectSafe(_) - | PredicateKind::Subtype(_) - | PredicateKind::Coerce(_) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) - | PredicateKind::ConstEquate(_, _) - | PredicateKind::Ambiguous => true, - } - } -} - -impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { - rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) - } -} - -impl rustc_errors::IntoDiagnosticArg for Clause<'_> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { - rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) - } -} - -/// A subset of predicates which can be assumed by the trait solver. They show up in -/// an item's where clauses, hence the name `Clause`, and may either be user-written -/// (such as traits) or may be inserted during lowering. -#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] -#[rustc_pass_by_value] -pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo>>>); - -impl<'tcx> Clause<'tcx> { - pub fn as_predicate(self) -> Predicate<'tcx> { - Predicate(self.0) - } - - pub fn kind(self) -> Binder<'tcx, ClauseKind<'tcx>> { - self.0.internee.map_bound(|kind| match kind { - PredicateKind::Clause(clause) => clause, - _ => unreachable!(), - }) - } - - pub fn as_trait_clause(self) -> Option>> { - let clause = self.kind(); - if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() { - Some(clause.rebind(trait_clause)) - } else { - None - } - } - - pub fn as_projection_clause(self) -> Option>> { - let clause = self.kind(); - if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() { - Some(clause.rebind(projection_clause)) - } else { - None - } - } - - pub fn as_type_outlives_clause(self) -> Option>> { - let clause = self.kind(); - if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() { - Some(clause.rebind(o)) - } else { - None - } - } - - pub fn as_region_outlives_clause(self) -> Option>> { - let clause = self.kind(); - if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() { - Some(clause.rebind(o)) - } else { - None - } - } -} - /// The crate outlives map is computed during typeck and contains the /// outlives of every item in the local crate. You should not use it /// directly, because to do so will make your pass dependent on the @@ -664,189 +518,6 @@ pub struct CratePredicatesMap<'tcx> { pub predicates: DefIdMap<&'tcx [(Clause<'tcx>, Span)]>, } -impl<'tcx> Clause<'tcx> { - /// Performs a substitution suitable for going from a - /// poly-trait-ref to supertraits that must hold if that - /// poly-trait-ref holds. This is slightly different from a normal - /// substitution in terms of what happens with bound regions. See - /// lengthy comment below for details. - pub fn subst_supertrait( - self, - tcx: TyCtxt<'tcx>, - trait_ref: &ty::PolyTraitRef<'tcx>, - ) -> Clause<'tcx> { - // The interaction between HRTB and supertraits is not entirely - // obvious. Let me walk you (and myself) through an example. - // - // Let's start with an easy case. Consider two traits: - // - // trait Foo<'a>: Bar<'a,'a> { } - // trait Bar<'b,'c> { } - // - // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then - // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we - // knew that `Foo<'x>` (for any 'x) then we also know that - // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from - // normal substitution. - // - // In terms of why this is sound, the idea is that whenever there - // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` - // holds. So if there is an impl of `T:Foo<'a>` that applies to - // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all - // `'a`. - // - // Another example to be careful of is this: - // - // trait Foo1<'a>: for<'b> Bar1<'a,'b> { } - // trait Bar1<'b,'c> { } - // - // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know? - // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The - // reason is similar to the previous example: any impl of - // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So - // basically we would want to collapse the bound lifetimes from - // the input (`trait_ref`) and the supertraits. - // - // To achieve this in practice is fairly straightforward. Let's - // consider the more complicated scenario: - // - // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x` - // has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`, - // where both `'x` and `'b` would have a DB index of 1. - // The substitution from the input trait-ref is therefore going to be - // `'a => 'x` (where `'x` has a DB index of 1). - // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an - // early-bound parameter and `'b` is a late-bound parameter with a - // DB index of 1. - // - If we replace `'a` with `'x` from the input, it too will have - // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` - // just as we wanted. - // - // There is only one catch. If we just apply the substitution `'a - // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will - // adjust the DB index because we substituting into a binder (it - // tries to be so smart...) resulting in `for<'x> for<'b> - // Bar1<'x,'b>` (we have no syntax for this, so use your - // imagination). Basically the 'x will have DB index of 2 and 'b - // will have DB index of 1. Not quite what we want. So we apply - // the substitution to the *contents* of the trait reference, - // rather than the trait reference itself (put another way, the - // substitution code expects equal binding levels in the values - // from the substitution and the value being substituted into, and - // this trick achieves that). - - // Working through the second example: - // trait_ref: for<'x> T: Foo1<'^0.0>; args: [T, '^0.0] - // predicate: for<'b> Self: Bar1<'a, '^0.0>; args: [Self, 'a, '^0.0] - // We want to end up with: - // for<'x, 'b> T: Bar1<'^0.0, '^0.1> - // To do this: - // 1) We must shift all bound vars in predicate by the length - // of trait ref's bound vars. So, we would end up with predicate like - // Self: Bar1<'a, '^0.1> - // 2) We can then apply the trait args to this, ending up with - // T: Bar1<'^0.0, '^0.1> - // 3) Finally, to create the final bound vars, we concatenate the bound - // vars of the trait ref with those of the predicate: - // ['x, 'b] - let bound_pred = self.kind(); - let pred_bound_vars = bound_pred.bound_vars(); - let trait_bound_vars = trait_ref.bound_vars(); - // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> - let shifted_pred = - tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); - // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> - let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args); - // 3) ['x] + ['b] -> ['x, 'b] - let bound_vars = - tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); - - // FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here? - tcx.reuse_or_mk_predicate( - self.as_predicate(), - ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars), - ) - .expect_clause() - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct TraitPredicate<'tcx> { - pub trait_ref: TraitRef<'tcx>, - - /// If polarity is Positive: we are proving that the trait is implemented. - /// - /// If polarity is Negative: we are proving that a negative impl of this trait - /// exists. (Note that coherence also checks whether negative impls of supertraits - /// exist via a series of predicates.) - /// - /// If polarity is Reserved: that's a bug. - pub polarity: ImplPolarity, -} - -pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; - -impl<'tcx> TraitPredicate<'tcx> { - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self } - } - - pub fn def_id(self) -> DefId { - self.trait_ref.def_id - } - - pub fn self_ty(self) -> Ty<'tcx> { - self.trait_ref.self_ty() - } -} - -impl<'tcx> PolyTraitPredicate<'tcx> { - pub fn def_id(self) -> DefId { - // Ok to skip binder since trait `DefId` does not care about regions. - self.skip_binder().def_id() - } - - pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { - self.map_bound(|trait_ref| trait_ref.self_ty()) - } - - #[inline] - pub fn polarity(self) -> ImplPolarity { - self.skip_binder().polarity - } -} - -/// `A: B` -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct OutlivesPredicate(pub A, pub B); -pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; -pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; -pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; -pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; - -/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates -/// whether the `a` type is the type that we should label as "expected" when -/// presenting user diagnostics. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct SubtypePredicate<'tcx> { - pub a_is_expected: bool, - pub a: Ty<'tcx>, - pub b: Ty<'tcx>, -} -pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; - -/// Encodes that we have to coerce *from* the `a` type to the `b` type. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct CoercePredicate<'tcx> { - pub a: Ty<'tcx>, - pub b: Ty<'tcx>, -} -pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Term<'tcx> { ptr: NonNull<()>, @@ -1048,351 +719,6 @@ impl From for TermVid { } } -/// This kind of predicate has no *direct* correspondent in the -/// syntax, but it roughly corresponds to the syntactic forms: -/// -/// 1. `T: TraitRef<..., Item = Type>` -/// 2. `>::Item == Type` (NYI) -/// -/// In particular, form #1 is "desugared" to the combination of a -/// normal trait predicate (`T: TraitRef<...>`) and one of these -/// predicates. Form #2 is a broader form in that it also permits -/// equality between arbitrary types. Processing an instance of -/// Form #2 eventually yields one of these `ProjectionPredicate` -/// instances to normalize the LHS. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct ProjectionPredicate<'tcx> { - pub projection_ty: AliasTy<'tcx>, - pub term: Term<'tcx>, -} - -impl<'tcx> ProjectionPredicate<'tcx> { - pub fn self_ty(self) -> Ty<'tcx> { - self.projection_ty.self_ty() - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> { - Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } - } - - pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { - self.projection_ty.trait_def_id(tcx) - } - - pub fn def_id(self) -> DefId { - self.projection_ty.def_id - } -} - -pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; - -impl<'tcx> PolyProjectionPredicate<'tcx> { - /// Returns the `DefId` of the trait of the associated item being projected. - #[inline] - pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - self.skip_binder().projection_ty.trait_def_id(tcx) - } - - /// Get the [PolyTraitRef] required for this projection to be well formed. - /// Note that for generic associated types the predicates of the associated - /// type also need to be checked. - #[inline] - pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> { - // Note: unlike with `TraitRef::to_poly_trait_ref()`, - // `self.0.trait_ref` is permitted to have escaping regions. - // This is because here `self` has a `Binder` and so does our - // return value, so we are preserving the number of binding - // levels. - self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) - } - - pub fn term(&self) -> Binder<'tcx, Term<'tcx>> { - self.map_bound(|predicate| predicate.term) - } - - /// The `DefId` of the `TraitItem` for the associated type. - /// - /// Note that this is not the `DefId` of the `TraitRef` containing this - /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. - pub fn projection_def_id(&self) -> DefId { - // Ok to skip binder since trait `DefId` does not care about regions. - self.skip_binder().projection_ty.def_id - } -} - -/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be -/// proven by actually normalizing `alias`. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct NormalizesTo<'tcx> { - pub alias: AliasTy<'tcx>, - pub term: Term<'tcx>, -} - -impl<'tcx> NormalizesTo<'tcx> { - pub fn self_ty(self) -> Ty<'tcx> { - self.alias.self_ty() - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> { - Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self } - } - - pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { - self.alias.trait_def_id(tcx) - } - - pub fn def_id(self) -> DefId { - self.alias.def_id - } -} - -pub trait ToPolyTraitRef<'tcx> { - fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; -} - -impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { - fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { - self.map_bound_ref(|trait_pred| trait_pred.trait_ref) - } -} - -pub trait ToPredicate<'tcx, P = Predicate<'tcx>> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P; -} - -impl<'tcx, T> ToPredicate<'tcx, T> for T { - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T { - self - } -} - -impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(self).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(self) - } -} - -impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self))) - } -} - -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause)) - } -} - -impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { - #[inline(always)] - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.as_predicate() - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(self).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> { - #[inline(always)] - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> { - TraitPredicate { trait_ref: self, polarity: ImplPolarity::Positive } - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); - pred.to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); - pred.to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { - #[inline(always)] - fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { - self.map_bound(|trait_ref| TraitPredicate { - trait_ref, - polarity: ty::ImplPolarity::Positive, - }) - } -} - -impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for OutlivesPredicate, ty::Region<'tcx>> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(self))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for ProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(self))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - PredicateKind::NormalizesTo(self).to_predicate(tcx) - } -} - -impl<'tcx> Predicate<'tcx> { - pub fn to_opt_poly_trait_pred(self) -> Option> { - let predicate = self.kind(); - match predicate.skip_binder() { - PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)), - PredicateKind::Clause(ClauseKind::Projection(..)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::NormalizesTo(..) - | PredicateKind::AliasRelate(..) - | PredicateKind::Subtype(..) - | PredicateKind::Coerce(..) - | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) - | PredicateKind::Clause(ClauseKind::WellFormed(..)) - | PredicateKind::ObjectSafe(..) - | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) - | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous => None, - } - } - - pub fn to_opt_poly_projection_pred(self) -> Option> { - let predicate = self.kind(); - match predicate.skip_binder() { - PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)), - PredicateKind::Clause(ClauseKind::Trait(..)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::NormalizesTo(..) - | PredicateKind::AliasRelate(..) - | PredicateKind::Subtype(..) - | PredicateKind::Coerce(..) - | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) - | PredicateKind::Clause(ClauseKind::WellFormed(..)) - | PredicateKind::ObjectSafe(..) - | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) - | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous => None, - } - } - - /// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`. - pub fn as_clause(self) -> Option> { - match self.kind().skip_binder() { - PredicateKind::Clause(..) => Some(self.expect_clause()), - _ => None, - } - } - - /// Assert that the predicate is a clause. - pub fn expect_clause(self) -> Clause<'tcx> { - match self.kind().skip_binder() { - PredicateKind::Clause(..) => Clause(self.0), - _ => bug!("{self} is not a clause"), - } - } -} - /// Represents the bounds declared on a particular set of type /// parameters. Should eventually be generalized into a flag list of /// where-clauses. You can obtain an `InstantiatedPredicates` list from a diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs new file mode 100644 index 0000000000000..7c5b49512ae50 --- /dev/null +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -0,0 +1,1062 @@ +use rustc_data_structures::captures::Captures; +use rustc_data_structures::intern::Interned; +use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; +use rustc_hir::def_id::DefId; +use rustc_hir::LangItem; +use rustc_span::Span; +use rustc_type_ir::ClauseKind as IrClauseKind; +use rustc_type_ir::PredicateKind as IrPredicateKind; +use std::cmp::Ordering; + +use crate::ty::visit::TypeVisitableExt; +use crate::ty::{ + self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArg, GenericArgs, + GenericArgsRef, ImplPolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo, +}; + +pub type ClauseKind<'tcx> = IrClauseKind>; +pub type PredicateKind<'tcx> = IrPredicateKind>; + +/// A statement that can be proven by a trait solver. This includes things that may +/// show up in where clauses, such as trait predicates and projection predicates, +/// and also things that are emitted as part of type checking such as `ObjectSafe` +/// predicate which is emitted when a type is coerced to a trait object. +/// +/// Use this rather than `PredicateKind`, whenever possible. +#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] +#[rustc_pass_by_value] +pub struct Predicate<'tcx>( + pub(super) Interned<'tcx, WithCachedTypeInfo>>>, +); + +impl<'tcx> Predicate<'tcx> { + /// Gets the inner `ty::Binder<'tcx, PredicateKind<'tcx>>`. + #[inline] + pub fn kind(self) -> ty::Binder<'tcx, PredicateKind<'tcx>> { + self.0.internee + } + + #[inline(always)] + pub fn flags(self) -> TypeFlags { + self.0.flags + } + + #[inline(always)] + pub fn outer_exclusive_binder(self) -> DebruijnIndex { + self.0.outer_exclusive_binder + } + + /// Flips the polarity of a Predicate. + /// + /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. + pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option> { + let kind = self + .kind() + .map_bound(|kind| match kind { + PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { + trait_ref, + polarity, + })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { + trait_ref, + polarity: polarity.flip()?, + }))), + + _ => None, + }) + .transpose()?; + + Some(tcx.mk_predicate(kind)) + } + + #[instrument(level = "debug", skip(tcx), ret)] + pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { + match self.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { + tcx.trait_is_coinductive(data.def_id()) + } + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => true, + _ => false, + } + } + + /// Whether this projection can be soundly normalized. + /// + /// Wf predicates must not be normalized, as normalization + /// can remove required bounds which would cause us to + /// unsoundly accept some programs. See #91068. + #[inline] + pub fn allow_normalization(self) -> bool { + match self.kind().skip_binder() { + PredicateKind::Clause(ClauseKind::WellFormed(_)) => false, + // `NormalizesTo` is only used in the new solver, so this shouldn't + // matter. Normalizing `term` would be 'wrong' however, as it changes whether + // `normalizes-to(::Assoc, ::Assoc)` holds. + PredicateKind::NormalizesTo(..) => false, + PredicateKind::Clause(ClauseKind::Trait(_)) + | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) + | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) + | PredicateKind::Clause(ClauseKind::Projection(_)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::AliasRelate(..) + | PredicateKind::ObjectSafe(_) + | PredicateKind::Subtype(_) + | PredicateKind::Coerce(_) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) + | PredicateKind::ConstEquate(_, _) + | PredicateKind::Ambiguous => true, + } + } +} + +impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { + rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) + } +} + +impl rustc_errors::IntoDiagnosticArg for Clause<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { + rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) + } +} + +/// A subset of predicates which can be assumed by the trait solver. They show up in +/// an item's where clauses, hence the name `Clause`, and may either be user-written +/// (such as traits) or may be inserted during lowering. +#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] +#[rustc_pass_by_value] +pub struct Clause<'tcx>( + pub(super) Interned<'tcx, WithCachedTypeInfo>>>, +); + +impl<'tcx> Clause<'tcx> { + pub fn as_predicate(self) -> Predicate<'tcx> { + Predicate(self.0) + } + + pub fn kind(self) -> ty::Binder<'tcx, ClauseKind<'tcx>> { + self.0.internee.map_bound(|kind| match kind { + PredicateKind::Clause(clause) => clause, + _ => unreachable!(), + }) + } + + pub fn as_trait_clause(self) -> Option>> { + let clause = self.kind(); + if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() { + Some(clause.rebind(trait_clause)) + } else { + None + } + } + + pub fn as_projection_clause(self) -> Option>> { + let clause = self.kind(); + if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() { + Some(clause.rebind(projection_clause)) + } else { + None + } + } + + pub fn as_type_outlives_clause(self) -> Option>> { + let clause = self.kind(); + if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() { + Some(clause.rebind(o)) + } else { + None + } + } + + pub fn as_region_outlives_clause( + self, + ) -> Option>> { + let clause = self.kind(); + if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() { + Some(clause.rebind(o)) + } else { + None + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub enum ExistentialPredicate<'tcx> { + /// E.g., `Iterator`. + Trait(ExistentialTraitRef<'tcx>), + /// E.g., `Iterator::Item = T`. + Projection(ExistentialProjection<'tcx>), + /// E.g., `Send`. + AutoTrait(DefId), +} + +impl<'tcx> DebugWithInfcx> for ExistentialPredicate<'tcx> { + fn fmt>>( + this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>, + f: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + std::fmt::Debug::fmt(&this.data, f) + } +} + +impl<'tcx> ExistentialPredicate<'tcx> { + /// Compares via an ordering that will not change if modules are reordered or other changes are + /// made to the tree. In particular, this ordering is preserved across incremental compilations. + pub fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering { + use self::ExistentialPredicate::*; + match (*self, *other) { + (Trait(_), Trait(_)) => Ordering::Equal, + (Projection(ref a), Projection(ref b)) => { + tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id)) + } + (AutoTrait(ref a), AutoTrait(ref b)) => { + tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b)) + } + (Trait(_), _) => Ordering::Less, + (Projection(_), Trait(_)) => Ordering::Greater, + (Projection(_), _) => Ordering::Less, + (AutoTrait(_), _) => Ordering::Greater, + } + } +} + +pub type PolyExistentialPredicate<'tcx> = ty::Binder<'tcx, ExistentialPredicate<'tcx>>; + +impl<'tcx> PolyExistentialPredicate<'tcx> { + /// Given an existential predicate like `?Self: PartialEq` (e.g., derived from `dyn PartialEq`), + /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` + /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq`, in our example). + pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> { + match self.skip_binder() { + ExistentialPredicate::Trait(tr) => { + self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx) + } + ExistentialPredicate::Projection(p) => { + self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) + } + ExistentialPredicate::AutoTrait(did) => { + let generics = tcx.generics_of(did); + let trait_ref = if generics.params.len() == 1 { + ty::TraitRef::new(tcx, did, [self_ty]) + } else { + // If this is an ill-formed auto trait, then synthesize + // new error args for the missing generics. + let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]); + ty::TraitRef::new(tcx, did, err_args) + }; + self.rebind(trait_ref).to_predicate(tcx) + } + } + } +} + +impl<'tcx> ty::List> { + /// Returns the "principal `DefId`" of this set of existential predicates. + /// + /// A Rust trait object type consists (in addition to a lifetime bound) + /// of a set of trait bounds, which are separated into any number + /// of auto-trait bounds, and at most one non-auto-trait bound. The + /// non-auto-trait bound is called the "principal" of the trait + /// object. + /// + /// Only the principal can have methods or type parameters (because + /// auto traits can have neither of them). This is important, because + /// it means the auto traits can be treated as an unordered set (methods + /// would force an order for the vtable, while relating traits with + /// type parameters without knowing the order to relate them in is + /// a rather non-trivial task). + /// + /// For example, in the trait object `dyn std::fmt::Debug + Sync`, the + /// principal bound is `Some(std::fmt::Debug)`, while the auto-trait bounds + /// are the set `{Sync}`. + /// + /// It is also possible to have a "trivial" trait object that + /// consists only of auto traits, with no principal - for example, + /// `dyn Send + Sync`. In that case, the set of auto-trait bounds + /// is `{Send, Sync}`, while there is no principal. These trait objects + /// have a "trivial" vtable consisting of just the size, alignment, + /// and destructor. + pub fn principal(&self) -> Option>> { + self[0] + .map_bound(|this| match this { + ExistentialPredicate::Trait(tr) => Some(tr), + _ => None, + }) + .transpose() + } + + pub fn principal_def_id(&self) -> Option { + self.principal().map(|trait_ref| trait_ref.skip_binder().def_id) + } + + #[inline] + pub fn projection_bounds<'a>( + &'a self, + ) -> impl Iterator>> + 'a { + self.iter().filter_map(|predicate| { + predicate + .map_bound(|pred| match pred { + ExistentialPredicate::Projection(projection) => Some(projection), + _ => None, + }) + .transpose() + }) + } + + #[inline] + pub fn auto_traits<'a>(&'a self) -> impl Iterator + Captures<'tcx> + 'a { + self.iter().filter_map(|predicate| match predicate.skip_binder() { + ExistentialPredicate::AutoTrait(did) => Some(did), + _ => None, + }) + } +} + +/// A complete reference to a trait. These take numerous guises in syntax, +/// but perhaps the most recognizable form is in a where-clause: +/// ```ignore (illustrative) +/// T: Foo +/// ``` +/// This would be represented by a trait-reference where the `DefId` is the +/// `DefId` for the trait `Foo` and the args define `T` as parameter 0, +/// and `U` as parameter 1. +/// +/// Trait references also appear in object types like `Foo`, but in +/// that case the `Self` parameter is absent from the substitutions. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct TraitRef<'tcx> { + pub def_id: DefId, + pub args: GenericArgsRef<'tcx>, + /// This field exists to prevent the creation of `TraitRef` without + /// calling [`TraitRef::new`]. + pub(super) _use_trait_ref_new_instead: (), +} + +impl<'tcx> TraitRef<'tcx> { + pub fn new( + tcx: TyCtxt<'tcx>, + trait_def_id: DefId, + args: impl IntoIterator>>, + ) -> Self { + let args = tcx.check_and_mk_args(trait_def_id, args); + Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () } + } + + pub fn from_lang_item( + tcx: TyCtxt<'tcx>, + trait_lang_item: LangItem, + span: Span, + args: impl IntoIterator>>, + ) -> Self { + let trait_def_id = tcx.require_lang_item(trait_lang_item, Some(span)); + Self::new(tcx, trait_def_id, args) + } + + pub fn from_method( + tcx: TyCtxt<'tcx>, + trait_id: DefId, + args: GenericArgsRef<'tcx>, + ) -> ty::TraitRef<'tcx> { + let defs = tcx.generics_of(trait_id); + ty::TraitRef::new(tcx, trait_id, tcx.mk_args(&args[..defs.params.len()])) + } + + /// Returns a `TraitRef` of the form `P0: Foo` where `Pi` + /// are the parameters defined on trait. + pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> { + ty::TraitRef::new(tcx, def_id, GenericArgs::identity_for_item(tcx, def_id)) + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + ty::TraitRef::new( + tcx, + self.def_id, + [self_ty.into()].into_iter().chain(self.args.iter().skip(1)), + ) + } + + #[inline] + pub fn self_ty(&self) -> Ty<'tcx> { + self.args.type_at(0) + } +} + +pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>; + +impl<'tcx> PolyTraitRef<'tcx> { + pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> { + self.map_bound_ref(|tr| tr.self_ty()) + } + + pub fn def_id(&self) -> DefId { + self.skip_binder().def_id + } +} + +impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { + self.to_string().into_diagnostic_arg() + } +} + +/// An existential reference to a trait, where `Self` is erased. +/// For example, the trait object `Trait<'a, 'b, X, Y>` is: +/// ```ignore (illustrative) +/// exists T. T: Trait<'a, 'b, X, Y> +/// ``` +/// The substitutions don't include the erased `Self`, only trait +/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct ExistentialTraitRef<'tcx> { + pub def_id: DefId, + pub args: GenericArgsRef<'tcx>, +} + +impl<'tcx> ExistentialTraitRef<'tcx> { + pub fn erase_self_ty( + tcx: TyCtxt<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + ) -> ty::ExistentialTraitRef<'tcx> { + // Assert there is a Self. + trait_ref.args.type_at(0); + + ty::ExistentialTraitRef { + def_id: trait_ref.def_id, + args: tcx.mk_args(&trait_ref.args[1..]), + } + } + + /// Object types don't have a self type specified. Therefore, when + /// we convert the principal trait-ref into a normal trait-ref, + /// you must give *some* self type. A common choice is `mk_err()` + /// or some placeholder type. + pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { + // otherwise the escaping vars would be captured by the binder + // debug_assert!(!self_ty.has_escaping_bound_vars()); + + ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter())) + } +} + +impl<'tcx> IntoDiagnosticArg for ExistentialTraitRef<'tcx> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { + self.to_string().into_diagnostic_arg() + } +} + +pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>; + +impl<'tcx> PolyExistentialTraitRef<'tcx> { + pub fn def_id(&self) -> DefId { + self.skip_binder().def_id + } + + /// Object types don't have a self type specified. Therefore, when + /// we convert the principal trait-ref into a normal trait-ref, + /// you must give *some* self type. A common choice is `mk_err()` + /// or some placeholder type. + pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::PolyTraitRef<'tcx> { + self.map_bound(|trait_ref| trait_ref.with_self_ty(tcx, self_ty)) + } +} + +/// A `ProjectionPredicate` for an `ExistentialTraitRef`. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct ExistentialProjection<'tcx> { + pub def_id: DefId, + pub args: GenericArgsRef<'tcx>, + pub term: Term<'tcx>, +} + +pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>; + +impl<'tcx> ExistentialProjection<'tcx> { + /// Extracts the underlying existential trait reference from this projection. + /// For example, if this is a projection of `exists T. ::Item == X`, + /// then this function would return an `exists T. T: Iterator` existential trait + /// reference. + pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> { + let def_id = tcx.parent(self.def_id); + let subst_count = tcx.generics_of(def_id).count() - 1; + let args = tcx.mk_args(&self.args[..subst_count]); + ty::ExistentialTraitRef { def_id, args } + } + + pub fn with_self_ty( + &self, + tcx: TyCtxt<'tcx>, + self_ty: Ty<'tcx>, + ) -> ty::ProjectionPredicate<'tcx> { + // otherwise the escaping regions would be captured by the binders + debug_assert!(!self_ty.has_escaping_bound_vars()); + + ty::ProjectionPredicate { + projection_ty: AliasTy::new( + tcx, + self.def_id, + [self_ty.into()].into_iter().chain(self.args), + ), + term: self.term, + } + } + + pub fn erase_self_ty( + tcx: TyCtxt<'tcx>, + projection_predicate: ty::ProjectionPredicate<'tcx>, + ) -> Self { + // Assert there is a Self. + projection_predicate.projection_ty.args.type_at(0); + + Self { + def_id: projection_predicate.projection_ty.def_id, + args: tcx.mk_args(&projection_predicate.projection_ty.args[1..]), + term: projection_predicate.term, + } + } +} + +impl<'tcx> PolyExistentialProjection<'tcx> { + pub fn with_self_ty( + &self, + tcx: TyCtxt<'tcx>, + self_ty: Ty<'tcx>, + ) -> ty::PolyProjectionPredicate<'tcx> { + self.map_bound(|p| p.with_self_ty(tcx, self_ty)) + } + + pub fn item_def_id(&self) -> DefId { + self.skip_binder().def_id + } +} + +impl<'tcx> Clause<'tcx> { + /// Performs a substitution suitable for going from a + /// poly-trait-ref to supertraits that must hold if that + /// poly-trait-ref holds. This is slightly different from a normal + /// substitution in terms of what happens with bound regions. See + /// lengthy comment below for details. + pub fn subst_supertrait( + self, + tcx: TyCtxt<'tcx>, + trait_ref: &ty::PolyTraitRef<'tcx>, + ) -> Clause<'tcx> { + // The interaction between HRTB and supertraits is not entirely + // obvious. Let me walk you (and myself) through an example. + // + // Let's start with an easy case. Consider two traits: + // + // trait Foo<'a>: Bar<'a,'a> { } + // trait Bar<'b,'c> { } + // + // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then + // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we + // knew that `Foo<'x>` (for any 'x) then we also know that + // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from + // normal substitution. + // + // In terms of why this is sound, the idea is that whenever there + // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` + // holds. So if there is an impl of `T:Foo<'a>` that applies to + // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all + // `'a`. + // + // Another example to be careful of is this: + // + // trait Foo1<'a>: for<'b> Bar1<'a,'b> { } + // trait Bar1<'b,'c> { } + // + // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know? + // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The + // reason is similar to the previous example: any impl of + // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So + // basically we would want to collapse the bound lifetimes from + // the input (`trait_ref`) and the supertraits. + // + // To achieve this in practice is fairly straightforward. Let's + // consider the more complicated scenario: + // + // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x` + // has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`, + // where both `'x` and `'b` would have a DB index of 1. + // The substitution from the input trait-ref is therefore going to be + // `'a => 'x` (where `'x` has a DB index of 1). + // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an + // early-bound parameter and `'b` is a late-bound parameter with a + // DB index of 1. + // - If we replace `'a` with `'x` from the input, it too will have + // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` + // just as we wanted. + // + // There is only one catch. If we just apply the substitution `'a + // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will + // adjust the DB index because we substituting into a binder (it + // tries to be so smart...) resulting in `for<'x> for<'b> + // Bar1<'x,'b>` (we have no syntax for this, so use your + // imagination). Basically the 'x will have DB index of 2 and 'b + // will have DB index of 1. Not quite what we want. So we apply + // the substitution to the *contents* of the trait reference, + // rather than the trait reference itself (put another way, the + // substitution code expects equal binding levels in the values + // from the substitution and the value being substituted into, and + // this trick achieves that). + + // Working through the second example: + // trait_ref: for<'x> T: Foo1<'^0.0>; args: [T, '^0.0] + // predicate: for<'b> Self: Bar1<'a, '^0.0>; args: [Self, 'a, '^0.0] + // We want to end up with: + // for<'x, 'b> T: Bar1<'^0.0, '^0.1> + // To do this: + // 1) We must shift all bound vars in predicate by the length + // of trait ref's bound vars. So, we would end up with predicate like + // Self: Bar1<'a, '^0.1> + // 2) We can then apply the trait args to this, ending up with + // T: Bar1<'^0.0, '^0.1> + // 3) Finally, to create the final bound vars, we concatenate the bound + // vars of the trait ref with those of the predicate: + // ['x, 'b] + let bound_pred = self.kind(); + let pred_bound_vars = bound_pred.bound_vars(); + let trait_bound_vars = trait_ref.bound_vars(); + // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> + let shifted_pred = + tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); + // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> + let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args); + // 3) ['x] + ['b] -> ['x, 'b] + let bound_vars = + tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); + + // FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here? + tcx.reuse_or_mk_predicate( + self.as_predicate(), + ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars), + ) + .expect_clause() + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct TraitPredicate<'tcx> { + pub trait_ref: TraitRef<'tcx>, + + /// If polarity is Positive: we are proving that the trait is implemented. + /// + /// If polarity is Negative: we are proving that a negative impl of this trait + /// exists. (Note that coherence also checks whether negative impls of supertraits + /// exist via a series of predicates.) + /// + /// If polarity is Reserved: that's a bug. + pub polarity: ImplPolarity, +} + +pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; + +impl<'tcx> TraitPredicate<'tcx> { + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self } + } + + pub fn def_id(self) -> DefId { + self.trait_ref.def_id + } + + pub fn self_ty(self) -> Ty<'tcx> { + self.trait_ref.self_ty() + } +} + +impl<'tcx> PolyTraitPredicate<'tcx> { + pub fn def_id(self) -> DefId { + // Ok to skip binder since trait `DefId` does not care about regions. + self.skip_binder().def_id() + } + + pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { + self.map_bound(|trait_ref| trait_ref.self_ty()) + } + + #[inline] + pub fn polarity(self) -> ImplPolarity { + self.skip_binder().polarity + } +} + +/// `A: B` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct OutlivesPredicate(pub A, pub B); +pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; +pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; +pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; +pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; + +/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates +/// whether the `a` type is the type that we should label as "expected" when +/// presenting user diagnostics. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct SubtypePredicate<'tcx> { + pub a_is_expected: bool, + pub a: Ty<'tcx>, + pub b: Ty<'tcx>, +} +pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; + +/// Encodes that we have to coerce *from* the `a` type to the `b` type. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct CoercePredicate<'tcx> { + pub a: Ty<'tcx>, + pub b: Ty<'tcx>, +} +pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; + +/// This kind of predicate has no *direct* correspondent in the +/// syntax, but it roughly corresponds to the syntactic forms: +/// +/// 1. `T: TraitRef<..., Item = Type>` +/// 2. `>::Item == Type` (NYI) +/// +/// In particular, form #1 is "desugared" to the combination of a +/// normal trait predicate (`T: TraitRef<...>`) and one of these +/// predicates. Form #2 is a broader form in that it also permits +/// equality between arbitrary types. Processing an instance of +/// Form #2 eventually yields one of these `ProjectionPredicate` +/// instances to normalize the LHS. +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct ProjectionPredicate<'tcx> { + pub projection_ty: AliasTy<'tcx>, + pub term: Term<'tcx>, +} + +impl<'tcx> ProjectionPredicate<'tcx> { + pub fn self_ty(self) -> Ty<'tcx> { + self.projection_ty.self_ty() + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> { + Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } + } + + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + self.projection_ty.trait_def_id(tcx) + } + + pub fn def_id(self) -> DefId { + self.projection_ty.def_id + } +} + +pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; + +impl<'tcx> PolyProjectionPredicate<'tcx> { + /// Returns the `DefId` of the trait of the associated item being projected. + #[inline] + pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { + self.skip_binder().projection_ty.trait_def_id(tcx) + } + + /// Get the [PolyTraitRef] required for this projection to be well formed. + /// Note that for generic associated types the predicates of the associated + /// type also need to be checked. + #[inline] + pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> { + // Note: unlike with `TraitRef::to_poly_trait_ref()`, + // `self.0.trait_ref` is permitted to have escaping regions. + // This is because here `self` has a `Binder` and so does our + // return value, so we are preserving the number of binding + // levels. + self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) + } + + pub fn term(&self) -> Binder<'tcx, Term<'tcx>> { + self.map_bound(|predicate| predicate.term) + } + + /// The `DefId` of the `TraitItem` for the associated type. + /// + /// Note that this is not the `DefId` of the `TraitRef` containing this + /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. + pub fn projection_def_id(&self) -> DefId { + // Ok to skip binder since trait `DefId` does not care about regions. + self.skip_binder().projection_ty.def_id + } +} + +/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be +/// proven by actually normalizing `alias`. +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct NormalizesTo<'tcx> { + pub alias: AliasTy<'tcx>, + pub term: Term<'tcx>, +} + +impl<'tcx> NormalizesTo<'tcx> { + pub fn self_ty(self) -> Ty<'tcx> { + self.alias.self_ty() + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> { + Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self } + } + + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + self.alias.trait_def_id(tcx) + } + + pub fn def_id(self) -> DefId { + self.alias.def_id + } +} + +pub trait ToPolyTraitRef<'tcx> { + fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; +} + +impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { + fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { + self.map_bound_ref(|trait_pred| trait_pred.trait_ref) + } +} + +pub trait ToPredicate<'tcx, P = Predicate<'tcx>> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P; +} + +impl<'tcx, T> ToPredicate<'tcx, T> for T { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T { + self + } +} + +impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(self).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + tcx.mk_predicate(self) + } +} + +impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self))) + } +} + +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause)) + } +} + +impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { + #[inline(always)] + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.as_predicate() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(self).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> { + TraitPredicate { trait_ref: self, polarity: ImplPolarity::Positive } + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); + pred.to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); + pred.to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { + self.map_bound(|trait_ref| TraitPredicate { + trait_ref, + polarity: ty::ImplPolarity::Positive, + }) + } +} + +impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for OutlivesPredicate, ty::Region<'tcx>> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(self))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for ProjectionPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(self))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + PredicateKind::NormalizesTo(self).to_predicate(tcx) + } +} + +impl<'tcx> Predicate<'tcx> { + pub fn to_opt_poly_trait_pred(self) -> Option> { + let predicate = self.kind(); + match predicate.skip_binder() { + PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)), + PredicateKind::Clause(ClauseKind::Projection(..)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::NormalizesTo(..) + | PredicateKind::AliasRelate(..) + | PredicateKind::Subtype(..) + | PredicateKind::Coerce(..) + | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) + | PredicateKind::Clause(ClauseKind::WellFormed(..)) + | PredicateKind::ObjectSafe(..) + | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) + | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous => None, + } + } + + pub fn to_opt_poly_projection_pred(self) -> Option> { + let predicate = self.kind(); + match predicate.skip_binder() { + PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)), + PredicateKind::Clause(ClauseKind::Trait(..)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::NormalizesTo(..) + | PredicateKind::AliasRelate(..) + | PredicateKind::Subtype(..) + | PredicateKind::Coerce(..) + | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) + | PredicateKind::Clause(ClauseKind::WellFormed(..)) + | PredicateKind::ObjectSafe(..) + | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) + | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous => None, + } + } + + /// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`. + pub fn as_clause(self) -> Option> { + match self.kind().skip_binder() { + PredicateKind::Clause(..) => Some(self.expect_clause()), + _ => None, + } + } + + /// Assert that the predicate is a clause. + pub fn expect_clause(self) -> Clause<'tcx> { + match self.kind().skip_binder() { + PredicateKind::Clause(..) => Clause(self.0), + _ => bug!("{self} is not a clause"), + } + } +} diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs new file mode 100644 index 0000000000000..75be380704e1f --- /dev/null +++ b/compiler/rustc_middle/src/ty/region.rs @@ -0,0 +1,399 @@ +use polonius_engine::Atom; +use rustc_data_structures::intern::Interned; +use rustc_errors::MultiSpan; +use rustc_hir::def_id::DefId; +use rustc_index::Idx; +use rustc_span::symbol::sym; +use rustc_span::symbol::{kw, Symbol}; +use rustc_span::{ErrorGuaranteed, DUMMY_SP}; +use rustc_type_ir::RegionKind as IrRegionKind; +use std::ops::Deref; + +use crate::ty::{self, BoundVar, TyCtxt, TypeFlags}; + +pub type RegionKind<'tcx> = IrRegionKind>; + +/// Use this rather than `RegionKind`, whenever possible. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] +#[rustc_pass_by_value] +pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>); + +impl<'tcx> rustc_type_ir::IntoKind for Region<'tcx> { + type Kind = RegionKind<'tcx>; + + fn kind(self) -> RegionKind<'tcx> { + *self + } +} + +impl<'tcx> Region<'tcx> { + #[inline] + pub fn new_early_param( + tcx: TyCtxt<'tcx>, + early_bound_region: ty::EarlyParamRegion, + ) -> Region<'tcx> { + tcx.intern_region(ty::ReEarlyParam(early_bound_region)) + } + + #[inline] + pub fn new_bound( + tcx: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + bound_region: ty::BoundRegion, + ) -> Region<'tcx> { + // Use a pre-interned one when possible. + if let ty::BoundRegion { var, kind: ty::BrAnon } = bound_region + && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize()) + && let Some(re) = inner.get(var.as_usize()).copied() + { + re + } else { + tcx.intern_region(ty::ReBound(debruijn, bound_region)) + } + } + + #[inline] + pub fn new_late_param( + tcx: TyCtxt<'tcx>, + scope: DefId, + bound_region: ty::BoundRegionKind, + ) -> Region<'tcx> { + tcx.intern_region(ty::ReLateParam(ty::LateParamRegion { scope, bound_region })) + } + + #[inline] + pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::RegionVid) -> Region<'tcx> { + // Use a pre-interned one when possible. + tcx.lifetimes + .re_vars + .get(v.as_usize()) + .copied() + .unwrap_or_else(|| tcx.intern_region(ty::ReVar(v))) + } + + #[inline] + pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderRegion) -> Region<'tcx> { + tcx.intern_region(ty::RePlaceholder(placeholder)) + } + + /// Constructs a `RegionKind::ReError` region. + #[track_caller] + pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Region<'tcx> { + tcx.intern_region(ty::ReError(reported)) + } + + /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` to ensure it + /// gets used. + #[track_caller] + pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> { + Region::new_error_with_message( + tcx, + DUMMY_SP, + "RegionKind::ReError constructed but no error reported", + ) + } + + /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` with the given + /// `msg` to ensure it gets used. + #[track_caller] + pub fn new_error_with_message>( + tcx: TyCtxt<'tcx>, + span: S, + msg: &'static str, + ) -> Region<'tcx> { + let reported = tcx.dcx().span_delayed_bug(span, msg); + Region::new_error(tcx, reported) + } + + /// Avoid this in favour of more specific `new_*` methods, where possible, + /// to avoid the cost of the `match`. + pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { + match kind { + ty::ReEarlyParam(region) => Region::new_early_param(tcx, region), + ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region), + ty::ReLateParam(ty::LateParamRegion { scope, bound_region }) => { + Region::new_late_param(tcx, scope, bound_region) + } + ty::ReStatic => tcx.lifetimes.re_static, + ty::ReVar(vid) => Region::new_var(tcx, vid), + ty::RePlaceholder(region) => Region::new_placeholder(tcx, region), + ty::ReErased => tcx.lifetimes.re_erased, + ty::ReError(reported) => Region::new_error(tcx, reported), + } + } +} + +/// Region utilities +impl<'tcx> Region<'tcx> { + pub fn kind(self) -> RegionKind<'tcx> { + *self.0.0 + } + + pub fn get_name(self) -> Option { + if self.has_name() { + match *self { + ty::ReEarlyParam(ebr) => Some(ebr.name), + ty::ReBound(_, br) => br.kind.get_name(), + ty::ReLateParam(fr) => fr.bound_region.get_name(), + ty::ReStatic => Some(kw::StaticLifetime), + ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(), + _ => None, + } + } else { + None + } + } + + pub fn get_name_or_anon(self) -> Symbol { + match self.get_name() { + Some(name) => name, + None => sym::anon, + } + } + + /// Is this region named by the user? + pub fn has_name(self) -> bool { + match *self { + ty::ReEarlyParam(ebr) => ebr.has_name(), + ty::ReBound(_, br) => br.kind.is_named(), + ty::ReLateParam(fr) => fr.bound_region.is_named(), + ty::ReStatic => true, + ty::ReVar(..) => false, + ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(), + ty::ReErased => false, + ty::ReError(_) => false, + } + } + + #[inline] + pub fn is_error(self) -> bool { + matches!(*self, ty::ReError(_)) + } + + #[inline] + pub fn is_static(self) -> bool { + matches!(*self, ty::ReStatic) + } + + #[inline] + pub fn is_erased(self) -> bool { + matches!(*self, ty::ReErased) + } + + #[inline] + pub fn is_bound(self) -> bool { + matches!(*self, ty::ReBound(..)) + } + + #[inline] + pub fn is_placeholder(self) -> bool { + matches!(*self, ty::RePlaceholder(..)) + } + + #[inline] + pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { + match *self { + ty::ReBound(debruijn, _) => debruijn >= index, + _ => false, + } + } + + pub fn type_flags(self) -> TypeFlags { + let mut flags = TypeFlags::empty(); + + match *self { + ty::ReVar(..) => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_RE_INFER; + } + ty::RePlaceholder(..) => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; + } + ty::ReEarlyParam(..) => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_RE_PARAM; + } + ty::ReLateParam { .. } => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + } + ty::ReStatic => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + } + ty::ReBound(..) => { + flags = flags | TypeFlags::HAS_RE_BOUND; + } + ty::ReErased => { + flags = flags | TypeFlags::HAS_RE_ERASED; + } + ty::ReError(_) => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + } + } + + debug!("type_flags({:?}) = {:?}", self, flags); + + flags + } + + /// Given an early-bound or free region, returns the `DefId` where it was bound. + /// For example, consider the regions in this snippet of code: + /// + /// ```ignore (illustrative) + /// impl<'a> Foo { + /// // ^^ -- early bound, declared on an impl + /// + /// fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c + /// // ^^ ^^ ^ anonymous, late-bound + /// // | early-bound, appears in where-clauses + /// // late-bound, appears only in fn args + /// {..} + /// } + /// ``` + /// + /// Here, `free_region_binding_scope('a)` would return the `DefId` + /// of the impl, and for all the other highlighted regions, it + /// would return the `DefId` of the function. In other cases (not shown), this + /// function might return the `DefId` of a closure. + pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId { + match *self { + ty::ReEarlyParam(br) => tcx.parent(br.def_id), + ty::ReLateParam(fr) => fr.scope, + _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), + } + } + + /// True for free regions other than `'static`. + pub fn is_param(self) -> bool { + matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_)) + } + + /// True for free region in the current context. + /// + /// This is the case for `'static` and param regions. + pub fn is_free(self) -> bool { + match *self { + ty::ReStatic | ty::ReEarlyParam(..) | ty::ReLateParam(..) => true, + ty::ReVar(..) + | ty::RePlaceholder(..) + | ty::ReBound(..) + | ty::ReErased + | ty::ReError(..) => false, + } + } + + pub fn is_var(self) -> bool { + matches!(self.kind(), ty::ReVar(_)) + } + + pub fn as_var(self) -> RegionVid { + match self.kind() { + ty::ReVar(vid) => vid, + _ => bug!("expected region {:?} to be of kind ReVar", self), + } + } +} + +impl<'tcx> Deref for Region<'tcx> { + type Target = RegionKind<'tcx>; + + #[inline] + fn deref(&self) -> &RegionKind<'tcx> { + self.0.0 + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)] +#[derive(HashStable)] +pub struct EarlyParamRegion { + pub def_id: DefId, + pub index: u32, + pub name: Symbol, +} + +impl std::fmt::Debug for EarlyParamRegion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name) + } +} + +rustc_index::newtype_index! { + /// A **region** (lifetime) **v**ariable **ID**. + #[derive(HashStable)] + #[encodable] + #[orderable] + #[debug_format = "'?{}"] + pub struct RegionVid {} +} + +impl Atom for RegionVid { + fn index(self) -> usize { + Idx::index(self) + } +} + +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] +#[derive(HashStable)] +/// The parameter representation of late-bound function parameters, "some region +/// at least as big as the scope `fr.scope`". +pub struct LateParamRegion { + pub scope: DefId, + pub bound_region: BoundRegionKind, +} + +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] +#[derive(HashStable)] +pub enum BoundRegionKind { + /// An anonymous region parameter for a given fn (&T) + BrAnon, + + /// Named region parameters for functions (a in &'a T) + /// + /// The `DefId` is needed to distinguish free regions in + /// the event of shadowing. + BrNamed(DefId, Symbol), + + /// Anonymous region for the implicit env pointer parameter + /// to a closure + BrEnv, +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)] +#[derive(HashStable)] +pub struct BoundRegion { + pub var: BoundVar, + pub kind: BoundRegionKind, +} + +impl BoundRegionKind { + pub fn is_named(&self) -> bool { + match *self { + BoundRegionKind::BrNamed(_, name) => { + name != kw::UnderscoreLifetime && name != kw::Empty + } + _ => false, + } + } + + pub fn get_name(&self) -> Option { + if self.is_named() { + match *self { + BoundRegionKind::BrNamed(_, name) => return Some(name), + _ => unreachable!(), + } + } + + None + } + + pub fn get_id(&self) -> Option { + match *self { + BoundRegionKind::BrNamed(id, _) => return Some(id), + _ => None, + } + } +} diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 43a6281481fa4..f5fdf210592e8 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -6,42 +6,32 @@ use crate::infer::canonical::Canonical; use crate::ty::visit::ValidateBoundVars; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, Discr, IntoKind, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, + self, AdtDef, BoundRegionKind, Discr, Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, TypeVisitor, }; use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use crate::ty::{List, ParamEnv}; use hir::def::DefKind; -use polonius_engine::Atom; use rustc_data_structures::captures::Captures; -use rustc_data_structures::intern::Interned; use rustc_errors::{ DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; -use rustc_index::Idx; use rustc_macros::HashStable; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_target::spec::abi::{self, Abi}; use std::assert_matches::debug_assert_matches; use std::borrow::Cow; -use std::cmp::Ordering; -use std::fmt; use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; use rustc_type_ir::BoundVar; -use rustc_type_ir::ClauseKind as IrClauseKind; use rustc_type_ir::CollectAndApply; -use rustc_type_ir::ConstKind as IrConstKind; -use rustc_type_ir::DebugWithInfcx; use rustc_type_ir::DynKind; -use rustc_type_ir::PredicateKind as IrPredicateKind; -use rustc_type_ir::RegionKind as IrRegionKind; use rustc_type_ir::TyKind as IrTyKind; use rustc_type_ir::TyKind::*; use rustc_type_ir::TypeAndMut as IrTypeAndMut; @@ -51,74 +41,8 @@ use super::GenericParamDefKind; // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here #[rustc_diagnostic_item = "TyKind"] pub type TyKind<'tcx> = IrTyKind>; -pub type RegionKind<'tcx> = IrRegionKind>; -pub type ConstKind<'tcx> = IrConstKind>; -pub type PredicateKind<'tcx> = IrPredicateKind>; -pub type ClauseKind<'tcx> = IrClauseKind>; pub type TypeAndMut<'tcx> = IrTypeAndMut>; -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] -#[derive(HashStable)] -/// The parameter representation of late-bound function parameters, "some region -/// at least as big as the scope `fr.scope`". -pub struct LateParamRegion { - pub scope: DefId, - pub bound_region: BoundRegionKind, -} - -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] -#[derive(HashStable)] -pub enum BoundRegionKind { - /// An anonymous region parameter for a given fn (&T) - BrAnon, - - /// Named region parameters for functions (a in &'a T) - /// - /// The `DefId` is needed to distinguish free regions in - /// the event of shadowing. - BrNamed(DefId, Symbol), - - /// Anonymous region for the implicit env pointer parameter - /// to a closure - BrEnv, -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)] -#[derive(HashStable)] -pub struct BoundRegion { - pub var: BoundVar, - pub kind: BoundRegionKind, -} - -impl BoundRegionKind { - pub fn is_named(&self) -> bool { - match *self { - BoundRegionKind::BrNamed(_, name) => { - name != kw::UnderscoreLifetime && name != kw::Empty - } - _ => false, - } - } - - pub fn get_name(&self) -> Option { - if self.is_named() { - match *self { - BoundRegionKind::BrNamed(_, name) => return Some(name), - _ => unreachable!(), - } - } - - None - } - - pub fn get_id(&self) -> Option { - match *self { - BoundRegionKind::BrNamed(id, _) => return Some(id), - _ => None, - } - } -} - pub trait Article { fn article(&self) -> &'static str; } @@ -645,290 +569,6 @@ impl<'tcx> InlineConstArgs<'tcx> { } } -#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub enum ExistentialPredicate<'tcx> { - /// E.g., `Iterator`. - Trait(ExistentialTraitRef<'tcx>), - /// E.g., `Iterator::Item = T`. - Projection(ExistentialProjection<'tcx>), - /// E.g., `Send`. - AutoTrait(DefId), -} - -impl<'tcx> DebugWithInfcx> for ExistentialPredicate<'tcx> { - fn fmt>>( - this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>, - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { - fmt::Debug::fmt(&this.data, f) - } -} - -impl<'tcx> ExistentialPredicate<'tcx> { - /// Compares via an ordering that will not change if modules are reordered or other changes are - /// made to the tree. In particular, this ordering is preserved across incremental compilations. - pub fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering { - use self::ExistentialPredicate::*; - match (*self, *other) { - (Trait(_), Trait(_)) => Ordering::Equal, - (Projection(ref a), Projection(ref b)) => { - tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id)) - } - (AutoTrait(ref a), AutoTrait(ref b)) => { - tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b)) - } - (Trait(_), _) => Ordering::Less, - (Projection(_), Trait(_)) => Ordering::Greater, - (Projection(_), _) => Ordering::Less, - (AutoTrait(_), _) => Ordering::Greater, - } - } -} - -pub type PolyExistentialPredicate<'tcx> = Binder<'tcx, ExistentialPredicate<'tcx>>; - -impl<'tcx> PolyExistentialPredicate<'tcx> { - /// Given an existential predicate like `?Self: PartialEq` (e.g., derived from `dyn PartialEq`), - /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` - /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq`, in our example). - pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> { - use crate::ty::ToPredicate; - match self.skip_binder() { - ExistentialPredicate::Trait(tr) => { - self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx) - } - ExistentialPredicate::Projection(p) => { - self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) - } - ExistentialPredicate::AutoTrait(did) => { - let generics = tcx.generics_of(did); - let trait_ref = if generics.params.len() == 1 { - ty::TraitRef::new(tcx, did, [self_ty]) - } else { - // If this is an ill-formed auto trait, then synthesize - // new error args for the missing generics. - let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]); - ty::TraitRef::new(tcx, did, err_args) - }; - self.rebind(trait_ref).to_predicate(tcx) - } - } - } -} - -impl<'tcx> List> { - /// Returns the "principal `DefId`" of this set of existential predicates. - /// - /// A Rust trait object type consists (in addition to a lifetime bound) - /// of a set of trait bounds, which are separated into any number - /// of auto-trait bounds, and at most one non-auto-trait bound. The - /// non-auto-trait bound is called the "principal" of the trait - /// object. - /// - /// Only the principal can have methods or type parameters (because - /// auto traits can have neither of them). This is important, because - /// it means the auto traits can be treated as an unordered set (methods - /// would force an order for the vtable, while relating traits with - /// type parameters without knowing the order to relate them in is - /// a rather non-trivial task). - /// - /// For example, in the trait object `dyn fmt::Debug + Sync`, the - /// principal bound is `Some(fmt::Debug)`, while the auto-trait bounds - /// are the set `{Sync}`. - /// - /// It is also possible to have a "trivial" trait object that - /// consists only of auto traits, with no principal - for example, - /// `dyn Send + Sync`. In that case, the set of auto-trait bounds - /// is `{Send, Sync}`, while there is no principal. These trait objects - /// have a "trivial" vtable consisting of just the size, alignment, - /// and destructor. - pub fn principal(&self) -> Option>> { - self[0] - .map_bound(|this| match this { - ExistentialPredicate::Trait(tr) => Some(tr), - _ => None, - }) - .transpose() - } - - pub fn principal_def_id(&self) -> Option { - self.principal().map(|trait_ref| trait_ref.skip_binder().def_id) - } - - #[inline] - pub fn projection_bounds<'a>( - &'a self, - ) -> impl Iterator>> + 'a { - self.iter().filter_map(|predicate| { - predicate - .map_bound(|pred| match pred { - ExistentialPredicate::Projection(projection) => Some(projection), - _ => None, - }) - .transpose() - }) - } - - #[inline] - pub fn auto_traits<'a>(&'a self) -> impl Iterator + Captures<'tcx> + 'a { - self.iter().filter_map(|predicate| match predicate.skip_binder() { - ExistentialPredicate::AutoTrait(did) => Some(did), - _ => None, - }) - } -} - -/// A complete reference to a trait. These take numerous guises in syntax, -/// but perhaps the most recognizable form is in a where-clause: -/// ```ignore (illustrative) -/// T: Foo -/// ``` -/// This would be represented by a trait-reference where the `DefId` is the -/// `DefId` for the trait `Foo` and the args define `T` as parameter 0, -/// and `U` as parameter 1. -/// -/// Trait references also appear in object types like `Foo`, but in -/// that case the `Self` parameter is absent from the substitutions. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct TraitRef<'tcx> { - pub def_id: DefId, - pub args: GenericArgsRef<'tcx>, - /// This field exists to prevent the creation of `TraitRef` without - /// calling [`TraitRef::new`]. - pub(super) _use_trait_ref_new_instead: (), -} - -impl<'tcx> TraitRef<'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - args: impl IntoIterator>>, - ) -> Self { - let args = tcx.check_and_mk_args(trait_def_id, args); - Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () } - } - - pub fn from_lang_item( - tcx: TyCtxt<'tcx>, - trait_lang_item: LangItem, - span: Span, - args: impl IntoIterator>>, - ) -> Self { - let trait_def_id = tcx.require_lang_item(trait_lang_item, Some(span)); - Self::new(tcx, trait_def_id, args) - } - - pub fn from_method( - tcx: TyCtxt<'tcx>, - trait_id: DefId, - args: GenericArgsRef<'tcx>, - ) -> ty::TraitRef<'tcx> { - let defs = tcx.generics_of(trait_id); - ty::TraitRef::new(tcx, trait_id, tcx.mk_args(&args[..defs.params.len()])) - } - - /// Returns a `TraitRef` of the form `P0: Foo` where `Pi` - /// are the parameters defined on trait. - pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> { - ty::TraitRef::new(tcx, def_id, GenericArgs::identity_for_item(tcx, def_id)) - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - ty::TraitRef::new( - tcx, - self.def_id, - [self_ty.into()].into_iter().chain(self.args.iter().skip(1)), - ) - } - - #[inline] - pub fn self_ty(&self) -> Ty<'tcx> { - self.args.type_at(0) - } -} - -pub type PolyTraitRef<'tcx> = Binder<'tcx, TraitRef<'tcx>>; - -impl<'tcx> PolyTraitRef<'tcx> { - pub fn self_ty(&self) -> Binder<'tcx, Ty<'tcx>> { - self.map_bound_ref(|tr| tr.self_ty()) - } - - pub fn def_id(&self) -> DefId { - self.skip_binder().def_id - } -} - -impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue { - self.to_string().into_diagnostic_arg() - } -} - -/// An existential reference to a trait, where `Self` is erased. -/// For example, the trait object `Trait<'a, 'b, X, Y>` is: -/// ```ignore (illustrative) -/// exists T. T: Trait<'a, 'b, X, Y> -/// ``` -/// The substitutions don't include the erased `Self`, only trait -/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct ExistentialTraitRef<'tcx> { - pub def_id: DefId, - pub args: GenericArgsRef<'tcx>, -} - -impl<'tcx> ExistentialTraitRef<'tcx> { - pub fn erase_self_ty( - tcx: TyCtxt<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - ) -> ty::ExistentialTraitRef<'tcx> { - // Assert there is a Self. - trait_ref.args.type_at(0); - - ty::ExistentialTraitRef { - def_id: trait_ref.def_id, - args: tcx.mk_args(&trait_ref.args[1..]), - } - } - - /// Object types don't have a self type specified. Therefore, when - /// we convert the principal trait-ref into a normal trait-ref, - /// you must give *some* self type. A common choice is `mk_err()` - /// or some placeholder type. - pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { - // otherwise the escaping vars would be captured by the binder - // debug_assert!(!self_ty.has_escaping_bound_vars()); - - ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter())) - } -} - -impl<'tcx> IntoDiagnosticArg for ExistentialTraitRef<'tcx> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue { - self.to_string().into_diagnostic_arg() - } -} - -pub type PolyExistentialTraitRef<'tcx> = Binder<'tcx, ExistentialTraitRef<'tcx>>; - -impl<'tcx> PolyExistentialTraitRef<'tcx> { - pub fn def_id(&self) -> DefId { - self.skip_binder().def_id - } - - /// Object types don't have a self type specified. Therefore, when - /// we convert the principal trait-ref into a normal trait-ref, - /// you must give *some* self type. A common choice is `mk_err()` - /// or some placeholder type. - pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::PolyTraitRef<'tcx> { - self.map_bound(|trait_ref| trait_ref.with_self_ty(tcx, self_ty)) - } -} - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable)] pub enum BoundVariableKind { @@ -1452,154 +1092,6 @@ impl ParamConst { } } -/// Use this rather than `RegionKind`, whenever possible. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] -#[rustc_pass_by_value] -pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>); - -impl<'tcx> IntoKind for Region<'tcx> { - type Kind = RegionKind<'tcx>; - - fn kind(self) -> RegionKind<'tcx> { - *self - } -} - -impl<'tcx> Region<'tcx> { - #[inline] - pub fn new_early_param( - tcx: TyCtxt<'tcx>, - early_bound_region: ty::EarlyParamRegion, - ) -> Region<'tcx> { - tcx.intern_region(ty::ReEarlyParam(early_bound_region)) - } - - #[inline] - pub fn new_bound( - tcx: TyCtxt<'tcx>, - debruijn: ty::DebruijnIndex, - bound_region: ty::BoundRegion, - ) -> Region<'tcx> { - // Use a pre-interned one when possible. - if let ty::BoundRegion { var, kind: ty::BrAnon } = bound_region - && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize()) - && let Some(re) = inner.get(var.as_usize()).copied() - { - re - } else { - tcx.intern_region(ty::ReBound(debruijn, bound_region)) - } - } - - #[inline] - pub fn new_late_param( - tcx: TyCtxt<'tcx>, - scope: DefId, - bound_region: ty::BoundRegionKind, - ) -> Region<'tcx> { - tcx.intern_region(ty::ReLateParam(ty::LateParamRegion { scope, bound_region })) - } - - #[inline] - pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::RegionVid) -> Region<'tcx> { - // Use a pre-interned one when possible. - tcx.lifetimes - .re_vars - .get(v.as_usize()) - .copied() - .unwrap_or_else(|| tcx.intern_region(ty::ReVar(v))) - } - - #[inline] - pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderRegion) -> Region<'tcx> { - tcx.intern_region(ty::RePlaceholder(placeholder)) - } - - /// Constructs a `RegionKind::ReError` region. - #[track_caller] - pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Region<'tcx> { - tcx.intern_region(ty::ReError(reported)) - } - - /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` to ensure it - /// gets used. - #[track_caller] - pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> { - Region::new_error_with_message( - tcx, - DUMMY_SP, - "RegionKind::ReError constructed but no error reported", - ) - } - - /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` with the given - /// `msg` to ensure it gets used. - #[track_caller] - pub fn new_error_with_message>( - tcx: TyCtxt<'tcx>, - span: S, - msg: &'static str, - ) -> Region<'tcx> { - let reported = tcx.dcx().span_delayed_bug(span, msg); - Region::new_error(tcx, reported) - } - - /// Avoid this in favour of more specific `new_*` methods, where possible, - /// to avoid the cost of the `match`. - pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { - match kind { - ty::ReEarlyParam(region) => Region::new_early_param(tcx, region), - ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region), - ty::ReLateParam(ty::LateParamRegion { scope, bound_region }) => { - Region::new_late_param(tcx, scope, bound_region) - } - ty::ReStatic => tcx.lifetimes.re_static, - ty::ReVar(vid) => Region::new_var(tcx, vid), - ty::RePlaceholder(region) => Region::new_placeholder(tcx, region), - ty::ReErased => tcx.lifetimes.re_erased, - ty::ReError(reported) => Region::new_error(tcx, reported), - } - } -} - -impl<'tcx> Deref for Region<'tcx> { - type Target = RegionKind<'tcx>; - - #[inline] - fn deref(&self) -> &RegionKind<'tcx> { - self.0.0 - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)] -#[derive(HashStable)] -pub struct EarlyParamRegion { - pub def_id: DefId, - pub index: u32, - pub name: Symbol, -} - -impl fmt::Debug for EarlyParamRegion { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name) - } -} - -rustc_index::newtype_index! { - /// A **region** (lifetime) **v**ariable **ID**. - #[derive(HashStable)] - #[encodable] - #[orderable] - #[debug_format = "'?{}"] - pub struct RegionVid {} -} - -impl Atom for RegionVid { - fn index(self) -> usize { - Idx::index(self) - } -} - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] pub struct BoundTy { @@ -1620,251 +1112,6 @@ impl From for BoundTy { } } -/// A `ProjectionPredicate` for an `ExistentialTraitRef`. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct ExistentialProjection<'tcx> { - pub def_id: DefId, - pub args: GenericArgsRef<'tcx>, - pub term: Term<'tcx>, -} - -pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>; - -impl<'tcx> ExistentialProjection<'tcx> { - /// Extracts the underlying existential trait reference from this projection. - /// For example, if this is a projection of `exists T. ::Item == X`, - /// then this function would return an `exists T. T: Iterator` existential trait - /// reference. - pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> { - let def_id = tcx.parent(self.def_id); - let subst_count = tcx.generics_of(def_id).count() - 1; - let args = tcx.mk_args(&self.args[..subst_count]); - ty::ExistentialTraitRef { def_id, args } - } - - pub fn with_self_ty( - &self, - tcx: TyCtxt<'tcx>, - self_ty: Ty<'tcx>, - ) -> ty::ProjectionPredicate<'tcx> { - // otherwise the escaping regions would be captured by the binders - debug_assert!(!self_ty.has_escaping_bound_vars()); - - ty::ProjectionPredicate { - projection_ty: AliasTy::new( - tcx, - self.def_id, - [self_ty.into()].into_iter().chain(self.args), - ), - term: self.term, - } - } - - pub fn erase_self_ty( - tcx: TyCtxt<'tcx>, - projection_predicate: ty::ProjectionPredicate<'tcx>, - ) -> Self { - // Assert there is a Self. - projection_predicate.projection_ty.args.type_at(0); - - Self { - def_id: projection_predicate.projection_ty.def_id, - args: tcx.mk_args(&projection_predicate.projection_ty.args[1..]), - term: projection_predicate.term, - } - } -} - -impl<'tcx> PolyExistentialProjection<'tcx> { - pub fn with_self_ty( - &self, - tcx: TyCtxt<'tcx>, - self_ty: Ty<'tcx>, - ) -> ty::PolyProjectionPredicate<'tcx> { - self.map_bound(|p| p.with_self_ty(tcx, self_ty)) - } - - pub fn item_def_id(&self) -> DefId { - self.skip_binder().def_id - } -} - -/// Region utilities -impl<'tcx> Region<'tcx> { - pub fn kind(self) -> RegionKind<'tcx> { - *self.0.0 - } - - pub fn get_name(self) -> Option { - if self.has_name() { - match *self { - ty::ReEarlyParam(ebr) => Some(ebr.name), - ty::ReBound(_, br) => br.kind.get_name(), - ty::ReLateParam(fr) => fr.bound_region.get_name(), - ty::ReStatic => Some(kw::StaticLifetime), - ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(), - _ => None, - } - } else { - None - } - } - - pub fn get_name_or_anon(self) -> Symbol { - match self.get_name() { - Some(name) => name, - None => sym::anon, - } - } - - /// Is this region named by the user? - pub fn has_name(self) -> bool { - match *self { - ty::ReEarlyParam(ebr) => ebr.has_name(), - ty::ReBound(_, br) => br.kind.is_named(), - ty::ReLateParam(fr) => fr.bound_region.is_named(), - ty::ReStatic => true, - ty::ReVar(..) => false, - ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(), - ty::ReErased => false, - ty::ReError(_) => false, - } - } - - #[inline] - pub fn is_error(self) -> bool { - matches!(*self, ty::ReError(_)) - } - - #[inline] - pub fn is_static(self) -> bool { - matches!(*self, ty::ReStatic) - } - - #[inline] - pub fn is_erased(self) -> bool { - matches!(*self, ty::ReErased) - } - - #[inline] - pub fn is_bound(self) -> bool { - matches!(*self, ty::ReBound(..)) - } - - #[inline] - pub fn is_placeholder(self) -> bool { - matches!(*self, ty::RePlaceholder(..)) - } - - #[inline] - pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { - match *self { - ty::ReBound(debruijn, _) => debruijn >= index, - _ => false, - } - } - - pub fn type_flags(self) -> TypeFlags { - let mut flags = TypeFlags::empty(); - - match *self { - ty::ReVar(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; - flags = flags | TypeFlags::HAS_RE_INFER; - } - ty::RePlaceholder(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; - flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; - } - ty::ReEarlyParam(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; - flags = flags | TypeFlags::HAS_RE_PARAM; - } - ty::ReLateParam { .. } => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; - } - ty::ReStatic => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - } - ty::ReBound(..) => { - flags = flags | TypeFlags::HAS_RE_BOUND; - } - ty::ReErased => { - flags = flags | TypeFlags::HAS_RE_ERASED; - } - ty::ReError(_) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - } - } - - debug!("type_flags({:?}) = {:?}", self, flags); - - flags - } - - /// Given an early-bound or free region, returns the `DefId` where it was bound. - /// For example, consider the regions in this snippet of code: - /// - /// ```ignore (illustrative) - /// impl<'a> Foo { - /// // ^^ -- early bound, declared on an impl - /// - /// fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c - /// // ^^ ^^ ^ anonymous, late-bound - /// // | early-bound, appears in where-clauses - /// // late-bound, appears only in fn args - /// {..} - /// } - /// ``` - /// - /// Here, `free_region_binding_scope('a)` would return the `DefId` - /// of the impl, and for all the other highlighted regions, it - /// would return the `DefId` of the function. In other cases (not shown), this - /// function might return the `DefId` of a closure. - pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId { - match *self { - ty::ReEarlyParam(br) => tcx.parent(br.def_id), - ty::ReLateParam(fr) => fr.scope, - _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), - } - } - - /// True for free regions other than `'static`. - pub fn is_param(self) -> bool { - matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_)) - } - - /// True for free region in the current context. - /// - /// This is the case for `'static` and param regions. - pub fn is_free(self) -> bool { - match *self { - ty::ReStatic | ty::ReEarlyParam(..) | ty::ReLateParam(..) => true, - ty::ReVar(..) - | ty::RePlaceholder(..) - | ty::ReBound(..) - | ty::ReErased - | ty::ReError(..) => false, - } - } - - pub fn is_var(self) -> bool { - matches!(self.kind(), ty::ReVar(_)) - } - - pub fn as_var(self) -> RegionVid { - match self.kind() { - ty::ReVar(vid) => vid, - _ => bug!("expected region {:?} to be of kind ReVar", self), - } - } -} - /// Constructors for `Ty` impl<'tcx> Ty<'tcx> { // Avoid this in favour of more specific `new_*` methods, where possible. @@ -2116,7 +1363,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_dynamic( tcx: TyCtxt<'tcx>, - obj: &'tcx List>, + obj: &'tcx List>, reg: ty::Region<'tcx>, repr: DynKind, ) -> Ty<'tcx> { @@ -3017,7 +2264,7 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(RegionKind<'_>, 24); - static_assert_size!(TyKind<'_>, 32); + static_assert_size!(ty::RegionKind<'_>, 24); + static_assert_size!(ty::TyKind<'_>, 32); // tidy-alphabetical-end } From dfbbdda56e4ccc0d660dbb5594fa21a6f799cb21 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 21 Jan 2024 21:21:57 +0300 Subject: [PATCH 130/246] check `RUST_BOOTSTRAP_CONFIG` in `profile_user_dist` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/tests.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 201d11571c48a..0ae466eca7d7c 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -174,12 +174,14 @@ fn override_toml_duplicate() { #[test] fn profile_user_dist() { fn get_toml(file: &Path) -> TomlConfig { - let contents = if file.ends_with("config.toml") { - "profile = \"user\"".to_owned() - } else { - assert!(file.ends_with("config.dist.toml")); - std::fs::read_to_string(file).unwrap() - }; + let contents = + if file.ends_with("config.toml") || env::var_os("RUST_BOOTSTRAP_CONFIG").is_some() { + "profile = \"user\"".to_owned() + } else { + assert!(file.ends_with("config.dist.toml")); + std::fs::read_to_string(file).unwrap() + }; + toml::from_str(&contents) .and_then(|table: toml::Value| TomlConfig::deserialize(table)) .unwrap() From 75f670d57d2e38dd7483b79bdfab3a5bc530b2bd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 30 Jan 2024 18:13:17 +0100 Subject: [PATCH 131/246] rustdoc: Correctly handle attribute merge if this is a glob reexport --- src/librustdoc/clean/mod.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8706abda97963..22df5ef81b7e7 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -147,6 +147,17 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< ) } +fn is_glob_import(tcx: TyCtxt<'_>, import_id: LocalDefId) -> bool { + if let Some(node) = tcx.opt_hir_node_by_def_id(import_id) + && let hir::Node::Item(item) = node + && let hir::ItemKind::Use(_, use_kind) = item.kind + { + use_kind == hir::UseKind::Glob + } else { + false + } +} + fn generate_item_with_correct_attrs( cx: &mut DocContext<'_>, kind: ItemKind, @@ -157,10 +168,17 @@ fn generate_item_with_correct_attrs( ) -> Item { let target_attrs = inline::load_attrs(cx, def_id); let attrs = if let Some(import_id) = import_id { + // glob reexports are treated the same as `#[doc(inline)]` items. + // + // For glob re-exports the item may or may not exist to be re-exported (potentially the cfgs + // on the path up until the glob can be removed, and only cfgs on the globbed item itself + // matter), for non-inlined re-exports see #85043. let is_inline = inline::load_attrs(cx, import_id.to_def_id()) .lists(sym::doc) .get_word_attr(sym::inline) - .is_some(); + .is_some() + || (is_glob_import(cx.tcx, import_id) + && (cx.render_options.document_hidden || !cx.tcx.is_doc_hidden(def_id))); let mut attrs = get_all_import_attributes(cx, import_id, def_id, is_inline); add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None); attrs From 024364ac6021246ad1ccbee4d0d611c7b872f7f1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 30 Jan 2024 18:14:09 +0100 Subject: [PATCH 132/246] Add regression test for #120487 --- .../glob-reexport-attribute-merge-120487.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/rustdoc/glob-reexport-attribute-merge-120487.rs diff --git a/tests/rustdoc/glob-reexport-attribute-merge-120487.rs b/tests/rustdoc/glob-reexport-attribute-merge-120487.rs new file mode 100644 index 0000000000000..98cdec107ae08 --- /dev/null +++ b/tests/rustdoc/glob-reexport-attribute-merge-120487.rs @@ -0,0 +1,32 @@ +// This test ensures that non-glob reexports don't get their attributes merge with +// the reexported item whereas glob reexports do. +// Regression test for . + +#![crate_name = "foo"] +#![feature(doc_cfg)] + +// @has 'foo/index.html' +// There are two items. +// @count - '//*[@class="item-table"]//div[@class="item-name"]' 2 +// Only one of them should have an attribute. +// @count - '//*[@class="item-table"]//div[@class="item-name"]/*[@class="stab portability"]' 1 + +mod a { + #[doc(cfg(not(feature = "a")))] + #[cfg(not(feature = "a"))] + pub struct Test1; +} + +mod b { + #[doc(cfg(not(feature = "a")))] + #[cfg(not(feature = "a"))] + pub struct Test2; +} + +// @has 'foo/struct.Test1.html' +// @count - '//*[@id="main-content"]/*[@class="item-info"]' 1 +// @has - '//*[@id="main-content"]/*[@class="item-info"]' 'Available on non-crate feature a only.' +pub use a::*; +// @has 'foo/struct.Test2.html' +// @count - '//*[@id="main-content"]/*[@class="item-info"]' 0 +pub use b::Test2; From e1ea7c8844af31ec55e81acaa9a71508085a5aae Mon Sep 17 00:00:00 2001 From: David Barsky Date: Wed, 17 Jan 2024 18:27:38 -0800 Subject: [PATCH 133/246] internal: switch to `tracing` from `log` This commit also adds `tracing` to NotificationDispatcher/RequestDispatcher, bumps `rust-analyzer-salsa` to 0.17.0-pre.6, `always-assert` to 0.2, and removes the homegrown `hprof` implementation in favor of a vendored tracing-span-tree. --- Cargo.lock | 25 +- Cargo.toml | 8 +- crates/base-db/Cargo.toml | 3 +- crates/base-db/src/change.rs | 2 +- crates/base-db/src/input.rs | 2 +- crates/base-db/src/lib.rs | 4 +- crates/hir-def/src/attr.rs | 4 +- crates/hir-def/src/body.rs | 2 +- crates/hir-def/src/data.rs | 2 +- crates/hir-def/src/db.rs | 2 +- crates/hir-def/src/find_path.rs | 6 +- crates/hir-def/src/generics.rs | 2 +- crates/hir-def/src/import_map.rs | 8 +- crates/hir-def/src/item_tree.rs | 3 +- crates/hir-def/src/lang_item.rs | 10 +- crates/hir-def/src/nameres.rs | 7 +- crates/hir-def/src/nameres/collector.rs | 16 +- crates/hir-def/src/per_ns.rs | 4 +- crates/hir-expand/src/db.rs | 4 +- crates/hir-ty/src/autoderef.rs | 2 +- crates/hir-ty/src/chalk_db.rs | 2 +- crates/hir-ty/src/db.rs | 7 +- crates/hir-ty/src/diagnostics/decl_check.rs | 2 +- crates/hir-ty/src/diagnostics/expr.rs | 3 +- crates/hir-ty/src/infer.rs | 2 +- crates/hir-ty/src/infer/unify.rs | 3 +- crates/hir-ty/src/method_resolution.rs | 15 +- crates/hir-ty/src/mir/borrowck.rs | 2 +- crates/hir-ty/src/mir/lower.rs | 5 +- crates/hir-ty/src/traits.rs | 5 +- crates/hir/Cargo.toml | 1 + crates/hir/src/lib.rs | 19 +- crates/hir/src/semantics.rs | 6 +- crates/hir/src/semantics/source_to_def.rs | 6 +- crates/ide-assists/Cargo.toml | 3 +- .../src/handlers/add_missing_impl_members.rs | 2 +- crates/ide-completion/Cargo.toml | 3 +- crates/ide-completion/src/completions/expr.rs | 2 +- .../src/completions/flyimport.rs | 10 +- .../src/completions/item_list.rs | 2 +- crates/ide-completion/src/completions/mod_.rs | 2 +- crates/ide-completion/src/completions/type.rs | 2 +- crates/ide-completion/src/context.rs | 8 +- crates/ide-completion/src/context/analysis.rs | 4 +- crates/ide-completion/src/item.rs | 2 +- crates/ide-completion/src/lib.rs | 2 +- crates/ide-completion/src/render.rs | 6 +- crates/ide-completion/src/render/const_.rs | 2 +- crates/ide-completion/src/render/function.rs | 4 +- crates/ide-completion/src/render/literal.rs | 4 +- crates/ide-completion/src/render/macro_.rs | 4 +- crates/ide-completion/src/render/pattern.rs | 4 +- .../ide-completion/src/render/type_alias.rs | 4 +- crates/ide-db/src/apply_change.rs | 5 +- crates/ide-db/src/defs.rs | 8 +- crates/ide-db/src/helpers.rs | 2 +- crates/ide-db/src/imports/import_assets.rs | 18 +- crates/ide-db/src/imports/insert_use.rs | 2 +- crates/ide-db/src/items_locator.rs | 13 +- crates/ide-db/src/search.rs | 4 +- crates/ide-db/src/symbol_index.rs | 10 +- crates/ide-diagnostics/Cargo.toml | 3 +- crates/ide-diagnostics/src/lib.rs | 2 +- crates/ide/src/highlight_related.rs | 2 +- crates/ide/src/inlay_hints.rs | 2 +- crates/ide/src/prime_caches.rs | 2 +- crates/ide/src/references.rs | 2 +- crates/ide/src/syntax_highlighting.rs | 2 +- crates/proc-macro-api/src/lib.rs | 2 +- crates/profile/Cargo.toml | 3 +- crates/profile/src/hprof.rs | 326 ------------------ crates/profile/src/lib.rs | 3 - crates/profile/src/tree.rs | 84 ----- crates/project-model/src/rustc_cfg.rs | 2 +- crates/project-model/src/workspace.rs | 8 +- crates/rust-analyzer/Cargo.toml | 3 +- crates/rust-analyzer/src/bin/logger.rs | 137 -------- crates/rust-analyzer/src/bin/main.rs | 25 +- crates/rust-analyzer/src/cli/parse.rs | 2 +- crates/rust-analyzer/src/diagnostics.rs | 2 +- crates/rust-analyzer/src/dispatch.rs | 20 +- crates/rust-analyzer/src/global_state.rs | 2 +- .../src/handlers/notification.rs | 14 +- crates/rust-analyzer/src/handlers/request.rs | 102 +++--- .../src/integrated_benchmarks.rs | 9 +- crates/rust-analyzer/src/lib.rs | 1 + crates/rust-analyzer/src/main_loop.rs | 11 +- crates/rust-analyzer/src/reload.rs | 9 +- crates/rust-analyzer/src/tracing/hprof.rs | 238 +++++++++++++ crates/rust-analyzer/src/tracing/mod.rs | 108 ++++++ crates/rust-analyzer/tests/slow-tests/main.rs | 3 - .../rust-analyzer/tests/slow-tests/support.rs | 18 +- crates/stdx/Cargo.toml | 2 +- crates/syntax/Cargo.toml | 1 + crates/syntax/src/algo.rs | 4 +- crates/test-utils/Cargo.toml | 3 +- 96 files changed, 658 insertions(+), 825 deletions(-) delete mode 100644 crates/profile/src/hprof.rs delete mode 100644 crates/profile/src/tree.rs delete mode 100644 crates/rust-analyzer/src/bin/logger.rs create mode 100644 crates/rust-analyzer/src/tracing/hprof.rs create mode 100644 crates/rust-analyzer/src/tracing/mod.rs diff --git a/Cargo.lock b/Cargo.lock index ca1fc63570731..dfaf5c23f18c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,11 +19,11 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "always-assert" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4436e0292ab1bb631b42973c61205e704475fe8126af845c8d923c0996328127" +checksum = "a1078fa1ce1e34b1872d8611ad921196d76bdd7027e949fbe31231abde201892" dependencies = [ - "log", + "tracing", ] [[package]] @@ -78,6 +78,7 @@ dependencies = [ "span", "stdx", "syntax", + "tracing", "triomphe", "vfs", ] @@ -497,6 +498,7 @@ dependencies = [ "span", "stdx", "syntax", + "tracing", "triomphe", "tt", ] @@ -671,6 +673,7 @@ dependencies = [ "test-fixture", "test-utils", "text-edit", + "tracing", ] [[package]] @@ -691,6 +694,7 @@ dependencies = [ "test-fixture", "test-utils", "text-edit", + "tracing", ] [[package]] @@ -748,6 +752,7 @@ dependencies = [ "test-fixture", "test-utils", "text-edit", + "tracing", ] [[package]] @@ -1343,6 +1348,7 @@ dependencies = [ "once_cell", "perf-event", "tikv-jemalloc-ctl", + "tracing", "winapi", ] @@ -1582,7 +1588,6 @@ dependencies = [ "tikv-jemallocator", "toolchain", "tracing", - "tracing-log", "tracing-subscriber", "tracing-tree", "triomphe", @@ -1596,26 +1601,26 @@ dependencies = [ [[package]] name = "rust-analyzer-salsa" -version = "0.17.0-pre.5" +version = "0.17.0-pre.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca9d387a9801f4fb9b366789ad1bfc08448cafc49cf148d907cfcd88ab665d7f" +checksum = "719825638c59fd26a55412a24561c7c5bcf54364c88b9a7a04ba08a6eafaba8d" dependencies = [ "indexmap", "lock_api", - "log", "oorandom", "parking_lot", "rust-analyzer-salsa-macros", "rustc-hash", "smallvec", + "tracing", "triomphe", ] [[package]] name = "rust-analyzer-salsa-macros" -version = "0.17.0-pre.5" +version = "0.17.0-pre.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2035f385d7fae31e9b086f40b272ee1d79c484472f31c9a10348a406e841eaf" +checksum = "4d96498e9684848c6676c399032ebc37c52da95ecbefa83d71ccc53b9f8a4a8e" dependencies = [ "heck", "proc-macro2", @@ -1864,6 +1869,7 @@ dependencies = [ "stdx", "test-utils", "text-edit", + "tracing", "triomphe", "ungrammar", ] @@ -1891,6 +1897,7 @@ dependencies = [ "rustc-hash", "stdx", "text-size", + "tracing", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 56db5a28c08a3..d5f9740c6deaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,7 +113,7 @@ itertools = "0.12.0" libc = "0.2.150" nohash-hasher = "0.2.0" rayon = "1.8.0" -rust-analyzer-salsa = "0.17.0-pre.5" +rust-analyzer-salsa = "0.17.0-pre.6" rustc-hash = "1.1.0" semver = "1.0.14" serde = { version = "1.0.192", features = ["derive"] } @@ -128,9 +128,9 @@ text-size = "1.1.1" tracing = "0.1.40" tracing-tree = "0.3.0" tracing-subscriber = { version = "0.3.18", default-features = false, features = [ - "registry", - "fmt", - "tracing-log", + "registry", + "fmt", + "tracing-log", ] } triomphe = { version = "0.1.10", default-features = false, features = ["std"] } xshell = "0.2.5" diff --git a/crates/base-db/Cargo.toml b/crates/base-db/Cargo.toml index 1aa43175f90b2..485ba78846a85 100644 --- a/crates/base-db/Cargo.toml +++ b/crates/base-db/Cargo.toml @@ -17,6 +17,7 @@ rust-analyzer-salsa.workspace = true rustc-hash.workspace = true triomphe.workspace = true semver.workspace = true +tracing.workspace = true # local deps cfg.workspace = true @@ -27,4 +28,4 @@ vfs.workspace = true span.workspace = true [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/base-db/src/change.rs b/crates/base-db/src/change.rs index 4332e572e2092..003ffb24d9d0d 100644 --- a/crates/base-db/src/change.rs +++ b/crates/base-db/src/change.rs @@ -51,7 +51,7 @@ impl FileChange { } pub fn apply(self, db: &mut dyn SourceDatabaseExt) { - let _p = profile::span("RootDatabase::apply_change"); + let _p = tracing::span!(tracing::Level::INFO, "RootDatabase::apply_change").entered(); if let Some(roots) = self.roots { for (idx, root) in roots.into_iter().enumerate() { let root_id = SourceRootId(idx as u32); diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index 852f36ea712a6..51e6fdb9510a8 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -494,7 +494,7 @@ impl CrateGraph { from: CrateId, dep: Dependency, ) -> Result<(), CyclicDependenciesError> { - let _p = profile::span("add_dep"); + let _p = tracing::span!(tracing::Level::INFO, "add_dep").entered(); self.check_cycle_after_dependency(from, dep.crate_id)?; diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index 90da7efd4a8b2..d7fc9d4c95cd6 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -65,7 +65,7 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug { } fn parse(db: &dyn SourceDatabase, file_id: FileId) -> Parse { - let _p = profile::span("parse_query").detail(|| format!("{file_id:?}")); + let _p = tracing::span!(tracing::Level::INFO, "parse_query", ?file_id).entered(); let text = db.file_text(file_id); SourceFile::parse(&text) } @@ -116,7 +116,7 @@ impl FileLoader for FileLoaderDelegate<&'_ T> { } fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { - let _p = profile::span("relevant_crates"); + let _p = tracing::span!(tracing::Level::INFO, "relevant_crates").entered(); let source_root = self.0.file_source_root(file_id); self.0.source_root_crates(source_root) } diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index a8e081705e324..bee6f0083b1e4 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -75,7 +75,7 @@ impl Attrs { db: &dyn DefDatabase, v: VariantId, ) -> Arc> { - let _p = profile::span("fields_attrs_query"); + let _p = tracing::span!(tracing::Level::INFO, "fields_attrs_query").entered(); // FIXME: There should be some proper form of mapping between item tree field ids and hir field ids let mut res = ArenaMap::default(); @@ -322,7 +322,7 @@ impl AttrsWithOwner { } pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { - let _p = profile::span("attrs_query"); + let _p = tracing::span!(tracing::Level::INFO, "attrs_query").entered(); // FIXME: this should use `Trace` to avoid duplication in `source_map` below let raw_attrs = match def { AttrDefId::ModuleId(module) => { diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index e4308c6b7f1f2..ce8a9eab14a9d 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -122,7 +122,7 @@ impl Body { db: &dyn DefDatabase, def: DefWithBodyId, ) -> (Arc, Arc) { - let _p = profile::span("body_with_source_map_query"); + let _p = tracing::span!(tracing::Level::INFO, "body_with_source_map_query").entered(); let mut params = None; let mut is_async_fn = false; diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index ca02b5d68e2e2..73fbad5e67508 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -340,7 +340,7 @@ impl ImplData { db: &dyn DefDatabase, id: ImplId, ) -> (Arc, DefDiagnostics) { - let _p = profile::span("impl_data_with_diagnostics_query"); + let _p = tracing::span!(tracing::Level::INFO, "impl_data_with_diagnostics_query").entered(); let ItemLoc { container: module_id, id: tree_id } = id.lookup(db); let item_tree = tree_id.item_tree(db); diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 97845f0f2b7fd..68f57600ec450 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -254,7 +254,7 @@ fn include_macro_invoc(db: &dyn DefDatabase, krate: CrateId) -> Vec<(MacroCallId } fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc { - let _p = profile::span("crate_def_map:wait"); + let _p = tracing::span!(tracing::Level::INFO, "crate_def_map:wait").entered(); db.crate_def_map_query(krate) } diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index efda8abf4b8bb..515a2cc8243ea 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -26,7 +26,7 @@ pub fn find_path( prefer_no_std: bool, prefer_prelude: bool, ) -> Option { - let _p = profile::span("find_path"); + let _p = tracing::span!(tracing::Level::INFO, "find_path").entered(); find_path_inner(FindPathCtx { db, prefixed: None, prefer_no_std, prefer_prelude }, item, from) } @@ -38,7 +38,7 @@ pub fn find_path_prefixed( prefer_no_std: bool, prefer_prelude: bool, ) -> Option { - let _p = profile::span("find_path_prefixed"); + let _p = tracing::span!(tracing::Level::INFO, "find_path_prefixed").entered(); find_path_inner( FindPathCtx { db, prefixed: Some(prefix_kind), prefer_no_std, prefer_prelude }, item, @@ -497,7 +497,7 @@ fn find_local_import_locations( item: ItemInNs, from: ModuleId, ) -> Vec<(ModuleId, Name)> { - let _p = profile::span("find_local_import_locations"); + let _p = tracing::span!(tracing::Level::INFO, "find_local_import_locations").entered(); // `from` can import anything below `from` with visibility of at least `from`, and anything // above `from` with any visibility. That means we do not need to descend into private siblings diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 7daae821f88d5..349d327aaae92 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -373,7 +373,7 @@ impl GenericParams { db: &dyn DefDatabase, def: GenericDefId, ) -> Interned { - let _p = profile::span("generic_params_query"); + let _p = tracing::span!(tracing::Level::INFO, "generic_params_query").entered(); let krate = def.module(db).krate; let cfg_options = db.crate_graph(); diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index 15c127f15628c..66d9cf54daa76 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -75,7 +75,7 @@ impl ImportMap { } pub(crate) fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc { - let _p = profile::span("import_map_query"); + let _p = tracing::span!(tracing::Level::INFO, "import_map_query").entered(); let map = Self::collect_import_map(db, krate); @@ -126,7 +126,7 @@ impl ImportMap { } fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex { - let _p = profile::span("collect_import_map"); + let _p = tracing::span!(tracing::Level::INFO, "collect_import_map").entered(); let def_map = db.crate_def_map(krate); let mut map = FxIndexMap::default(); @@ -216,7 +216,7 @@ impl ImportMap { is_type_in_ns: bool, trait_import_info: &ImportInfo, ) { - let _p = profile::span("collect_trait_assoc_items"); + let _p = tracing::span!(tracing::Level::INFO, "collect_trait_assoc_items").entered(); for &(ref assoc_item_name, item) in &db.trait_data(tr).items { let module_def_id = match item { AssocItemId::FunctionId(f) => ModuleDefId::from(f), @@ -398,7 +398,7 @@ pub fn search_dependencies( krate: CrateId, ref query: Query, ) -> FxHashSet { - let _p = profile::span("search_dependencies").detail(|| format!("{query:?}")); + let _p = tracing::span!(tracing::Level::INFO, "search_dependencies", ?query).entered(); let graph = db.crate_graph(); diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index c37cf52155102..299ad33c34934 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -109,7 +109,8 @@ pub struct ItemTree { impl ItemTree { pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc { - let _p = profile::span("file_item_tree_query").detail(|| format!("{file_id:?}")); + let _p = tracing::span!(tracing::Level::INFO, "file_item_tree_query", ?file_id).entered(); + let syntax = db.parse_or_expand(file_id); let ctx = lower::Ctx::new(db, file_id); diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index 60c8baf424dbb..7d98f6cfe88c1 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -91,7 +91,7 @@ impl LangItems { db: &dyn DefDatabase, krate: CrateId, ) -> Option> { - let _p = profile::span("crate_lang_items_query"); + let _p = tracing::span!(tracing::Level::INFO, "crate_lang_items_query").entered(); let mut lang_items = LangItems::default(); @@ -163,7 +163,7 @@ impl LangItems { start_crate: CrateId, item: LangItem, ) -> Option { - let _p = profile::span("lang_item_query"); + let _p = tracing::span!(tracing::Level::INFO, "lang_item_query").entered(); if let Some(target) = db.crate_lang_items(start_crate).and_then(|it| it.items.get(&item).copied()) { @@ -183,7 +183,7 @@ impl LangItems { ) where T: Into + Copy, { - let _p = profile::span("collect_lang_item"); + let _p = tracing::span!(tracing::Level::INFO, "collect_lang_item").entered(); if let Some(lang_item) = lang_attr(db, item.into()) { self.items.entry(lang_item).or_insert_with(|| constructor(item)); } @@ -199,7 +199,7 @@ pub(crate) fn notable_traits_in_deps( db: &dyn DefDatabase, krate: CrateId, ) -> Arc<[Arc<[TraitId]>]> { - let _p = profile::span("notable_traits_in_deps").detail(|| format!("{krate:?}")); + let _p = tracing::span!(tracing::Level::INFO, "notable_traits_in_deps", ?krate).entered(); let crate_graph = db.crate_graph(); Arc::from_iter( @@ -208,7 +208,7 @@ pub(crate) fn notable_traits_in_deps( } pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: CrateId) -> Option> { - let _p = profile::span("crate_notable_traits").detail(|| format!("{krate:?}")); + let _p = tracing::span!(tracing::Level::INFO, "crate_notable_traits", ?krate).entered(); let mut traits = Vec::new(); diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 2295df16fdcc4..1fa975789e772 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -306,9 +306,10 @@ impl DefMap { pub const ROOT: LocalModuleId = LocalModuleId::from_raw(la_arena::RawIdx::from_u32(0)); pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc { - let _p = profile::span("crate_def_map_query").detail(|| { - db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string() - }); + let crate_graph = db.crate_graph(); + let krate_name = crate_graph[krate].display_name.as_deref().unwrap_or_default(); + + let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?krate_name).entered(); let crate_graph = db.crate_graph(); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 248d3213d5d75..bdef9c8a93192 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -273,7 +273,7 @@ struct DefCollector<'a> { impl DefCollector<'_> { fn seed_with_top_level(&mut self) { - let _p = profile::span("seed_with_top_level"); + let _p = tracing::span!(tracing::Level::INFO, "seed_with_top_level").entered(); let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; let item_tree = self.db.file_item_tree(file_id.into()); @@ -401,7 +401,7 @@ impl DefCollector<'_> { } fn resolution_loop(&mut self) { - let _p = profile::span("DefCollector::resolution_loop"); + let _p = tracing::span!(tracing::Level::INFO, "DefCollector::resolution_loop").entered(); // main name resolution fixed-point loop. let mut i = 0; @@ -410,7 +410,7 @@ impl DefCollector<'_> { self.db.unwind_if_cancelled(); { - let _p = profile::span("resolve_imports loop"); + let _p = tracing::span!(tracing::Level::INFO, "resolve_imports loop").entered(); 'resolve_imports: loop { if self.resolve_imports() == ReachedFixedPoint::Yes { @@ -436,7 +436,7 @@ impl DefCollector<'_> { } fn collect(&mut self) { - let _p = profile::span("DefCollector::collect"); + let _p = tracing::span!(tracing::Level::INFO, "DefCollector::collect").entered(); self.resolution_loop(); @@ -792,8 +792,8 @@ impl DefCollector<'_> { } fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport { - let _p = profile::span("resolve_import") - .detail(|| format!("{}", import.path.display(self.db.upcast()))); + let _p = tracing::span!(tracing::Level::INFO, "resolve_import", import_path = %import.path.display(self.db.upcast())) + .entered(); tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition); match import.source { ImportSource::ExternCrate { .. } => { @@ -856,7 +856,7 @@ impl DefCollector<'_> { } fn record_resolved_import(&mut self, directive: &ImportDirective) { - let _p = profile::span("record_resolved_import"); + let _p = tracing::span!(tracing::Level::INFO, "record_resolved_import").entered(); let module_id = directive.module_id; let import = &directive.import; @@ -1430,7 +1430,7 @@ impl DefCollector<'_> { fn finish(mut self) -> DefMap { // Emit diagnostics for all remaining unexpanded macros. - let _p = profile::span("DefCollector::finish"); + let _p = tracing::span!(tracing::Level::INFO, "DefCollector::finish").entered(); for directive in &self.unresolved_macros { match &directive.kind { diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs index 14890364d0bd1..6a62ef697017c 100644 --- a/crates/hir-def/src/per_ns.rs +++ b/crates/hir-def/src/per_ns.rs @@ -92,7 +92,7 @@ impl PerNs { } pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { - let _p = profile::span("PerNs::filter_visibility"); + let _p = tracing::span!(tracing::Level::INFO, "PerNs::filter_visibility").entered(); PerNs { types: self.types.filter(|&(_, v, _)| f(v)), values: self.values.filter(|&(_, v, _)| f(v)), @@ -125,7 +125,7 @@ impl PerNs { } pub fn iter_items(self) -> impl Iterator)> { - let _p = profile::span("PerNs::iter_items"); + let _p = tracing::span!(tracing::Level::INFO, "PerNs::iter_items").entered(); self.types .map(|it| (ItemInNs::Types(it.0), it.2)) .into_iter() diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 8c43017971fb0..19dda651d7a30 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -280,7 +280,7 @@ fn parse_macro_expansion( db: &dyn ExpandDatabase, macro_file: MacroFileId, ) -> ExpandResult<(Parse, Arc)> { - let _p = profile::span("parse_macro_expansion"); + let _p = tracing::span!(tracing::Level::INFO, "parse_macro_expansion").entered(); let loc = db.lookup_intern_macro_call(macro_file.macro_call_id); let expand_to = loc.expand_to(); let mbe::ValueResult { value: tt, err } = macro_expand(db, macro_file.macro_call_id, loc); @@ -501,7 +501,7 @@ fn macro_expand( macro_call_id: MacroCallId, loc: MacroCallLoc, ) -> ExpandResult> { - let _p = profile::span("macro_expand"); + let _p = tracing::span!(tracing::Level::INFO, "macro_expand").entered(); let ExpandResult { value: tt, mut err } = match loc.def.kind { MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id).map(CowArc::Arc), diff --git a/crates/hir-ty/src/autoderef.rs b/crates/hir-ty/src/autoderef.rs index 4625a3b01a36c..991fd2f91df85 100644 --- a/crates/hir-ty/src/autoderef.rs +++ b/crates/hir-ty/src/autoderef.rs @@ -142,7 +142,7 @@ pub(crate) fn deref_by_trait( table @ &mut InferenceTable { db, .. }: &mut InferenceTable<'_>, ty: Ty, ) -> Option { - let _p = profile::span("deref_by_trait"); + let _p = tracing::span!(tracing::Level::INFO, "deref_by_trait").entered(); if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() { // don't try to deref unknown variables return None; diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index 4d509f20d01ca..7e460f9f867ae 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -689,7 +689,7 @@ pub(crate) fn impl_datum_query( krate: CrateId, impl_id: ImplId, ) -> Arc { - let _p = profile::span("impl_datum"); + let _p = tracing::span!(tracing::Level::INFO, "impl_datum").entered(); debug!("impl_datum {:?}", impl_id); let impl_: hir_def::ImplId = from_chalk(db, impl_id); impl_def_datum(db, krate, impl_id, impl_) diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs index 89fe8c2b824a1..21679150b3428 100644 --- a/crates/hir-ty/src/db.rs +++ b/crates/hir-ty/src/db.rs @@ -281,7 +281,7 @@ pub trait HirDatabase: DefDatabase + Upcast { } fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc { - let _p = profile::span("infer:wait").detail(|| match def { + let detail = match def { DefWithBodyId::FunctionId(it) => db.function_data(it).name.display(db.upcast()).to_string(), DefWithBodyId::StaticId(it) => { db.static_data(it).name.clone().display(db.upcast()).to_string() @@ -297,7 +297,8 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc db.enum_variant_data(it).name.display(db.upcast()).to_string() } DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"), - }); + }; + let _p = tracing::span!(tracing::Level::INFO, "infer:wait", ?detail).entered(); db.infer_query(def) } @@ -307,7 +308,7 @@ fn trait_solve_wait( block: Option, goal: crate::Canonical>, ) -> Option { - let _p = profile::span("trait_solve::wait"); + let _p = tracing::span!(tracing::Level::INFO, "trait_solve::wait").entered(); db.trait_solve_query(krate, block, goal) } diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs index a37dba480564e..78f2005e676c7 100644 --- a/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/crates/hir-ty/src/diagnostics/decl_check.rs @@ -45,7 +45,7 @@ mod allow { } pub fn incorrect_case(db: &dyn HirDatabase, owner: ModuleDefId) -> Vec { - let _p = profile::span("validate_module_item"); + let _p = tracing::span!(tracing::Level::INFO, "validate_module_item").entered(); let mut validator = DeclValidator::new(db); validator.validate_item(owner); validator.sink diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index 530608292e6fd..eda8f2371c9cd 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -48,7 +48,8 @@ pub enum BodyValidationDiagnostic { impl BodyValidationDiagnostic { pub fn collect(db: &dyn HirDatabase, owner: DefWithBodyId) -> Vec { - let _p = profile::span("BodyValidationDiagnostic::collect"); + let _p = + tracing::span!(tracing::Level::INFO, "BodyValidationDiagnostic::collect").entered(); let infer = db.infer(owner); let mut validator = ExprValidator::new(owner, infer); validator.validate_body(db); diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 0d89269b32509..71c3f89716d82 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -75,7 +75,7 @@ pub(crate) use closure::{CaptureKind, CapturedItem, CapturedItemWithoutTy}; /// The entry point of type inference. pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc { - let _p = profile::span("infer_query"); + let _p = tracing::span!(tracing::Level::INFO, "infer_query").entered(); let resolver = def.resolver(db.upcast()); let body = db.body(def); let mut ctx = InferenceContext::new(db, def, &body, resolver); diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index 9c415400775a2..61c82339508de 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -509,7 +509,8 @@ impl<'a> InferenceTable<'a> { } pub(crate) fn resolve_obligations_as_possible(&mut self) { - let _span = profile::span("resolve_obligations_as_possible"); + let _span = + tracing::span!(tracing::Level::INFO, "resolve_obligations_as_possible").entered(); let mut changed = true; let mut obligations = mem::take(&mut self.resolve_obligations_buffer); while mem::take(&mut changed) { diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index f8ce3008f1a96..1c068bf684ae0 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -143,7 +143,8 @@ pub struct TraitImpls { impl TraitImpls { pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc { - let _p = profile::span("trait_impls_in_crate_query").detail(|| format!("{krate:?}")); + let _p = + tracing::span!(tracing::Level::INFO, "trait_impls_in_crate_query", ?krate).entered(); let mut impls = FxHashMap::default(); Self::collect_def_map(db, &mut impls, &db.crate_def_map(krate)); @@ -155,7 +156,7 @@ impl TraitImpls { db: &dyn HirDatabase, block: BlockId, ) -> Option> { - let _p = profile::span("trait_impls_in_block_query"); + let _p = tracing::span!(tracing::Level::INFO, "trait_impls_in_block_query").entered(); let mut impls = FxHashMap::default(); Self::collect_def_map(db, &mut impls, &db.block_def_map(block)); @@ -171,7 +172,8 @@ impl TraitImpls { db: &dyn HirDatabase, krate: CrateId, ) -> Arc<[Arc]> { - let _p = profile::span("trait_impls_in_deps_query").detail(|| format!("{krate:?}")); + let _p = + tracing::span!(tracing::Level::INFO, "trait_impls_in_deps_query", ?krate).entered(); let crate_graph = db.crate_graph(); Arc::from_iter( @@ -272,7 +274,8 @@ pub struct InherentImpls { impl InherentImpls { pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc { - let _p = profile::span("inherent_impls_in_crate_query").detail(|| format!("{krate:?}")); + let _p = + tracing::span!(tracing::Level::INFO, "inherent_impls_in_crate_query", ?krate).entered(); let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() }; let crate_def_map = db.crate_def_map(krate); @@ -286,7 +289,7 @@ impl InherentImpls { db: &dyn HirDatabase, block: BlockId, ) -> Option> { - let _p = profile::span("inherent_impls_in_block_query"); + let _p = tracing::span!(tracing::Level::INFO, "inherent_impls_in_block_query").entered(); let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() }; let block_def_map = db.block_def_map(block); @@ -359,7 +362,7 @@ pub(crate) fn incoherent_inherent_impl_crates( krate: CrateId, fp: TyFingerprint, ) -> SmallVec<[CrateId; 2]> { - let _p = profile::span("inherent_impl_crates_query"); + let _p = tracing::span!(tracing::Level::INFO, "inherent_impl_crates_query").entered(); let mut res = SmallVec::new(); let crate_graph = db.crate_graph(); diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs index 2dd5fa78d0754..ea4e60cad3006 100644 --- a/crates/hir-ty/src/mir/borrowck.rs +++ b/crates/hir-ty/src/mir/borrowck.rs @@ -71,7 +71,7 @@ pub fn borrowck_query( db: &dyn HirDatabase, def: DefWithBodyId, ) -> Result, MirLowerError> { - let _p = profile::span("borrowck_query"); + let _p = tracing::span!(tracing::Level::INFO, "borrowck_query").entered(); let mut res = vec![]; all_mir_bodies(db, def, |body| { res.push(BorrowckResult { diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index f51853107fe92..74bac8cbf1249 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -2068,7 +2068,7 @@ pub fn mir_body_for_closure_query( } pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result> { - let _p = profile::span("mir_body_query").detail(|| match def { + let detail = match def { DefWithBodyId::FunctionId(it) => db.function_data(it).name.display(db.upcast()).to_string(), DefWithBodyId::StaticId(it) => db.static_data(it).name.display(db.upcast()).to_string(), DefWithBodyId::ConstId(it) => db @@ -2082,7 +2082,8 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result format!("in type const {it:?}"), - }); + }; + let _p = tracing::span!(tracing::Level::INFO, "mir_body_query", ?detail).entered(); let body = db.body(def); let infer = db.infer(def); let mut result = lower_to_mir(db, def, &body, &infer, body.body_expr)?; diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs index b6bc76bc98d53..3a1a4e63ea121 100644 --- a/crates/hir-ty/src/traits.rs +++ b/crates/hir-ty/src/traits.rs @@ -100,13 +100,14 @@ pub(crate) fn trait_solve_query( block: Option, goal: Canonical>, ) -> Option { - let _p = profile::span("trait_solve_query").detail(|| match &goal.value.goal.data(Interner) { + let detail = match &goal.value.goal.data(Interner) { GoalData::DomainGoal(DomainGoal::Holds(WhereClause::Implemented(it))) => { db.trait_data(it.hir_trait_id()).name.display(db.upcast()).to_string() } GoalData::DomainGoal(DomainGoal::Holds(WhereClause::AliasEq(_))) => "alias_eq".to_string(), _ => "??".to_string(), - }); + }; + let _p = tracing::span!(tracing::Level::INFO, "trait_solve_query", ?detail).entered(); tracing::info!("trait_solve_query({:?})", goal.value.goal); if let GoalData::DomainGoal(DomainGoal::Holds(WhereClause::AliasEq(AliasEq { diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml index 668a14cd55e49..7fea8372876ee 100644 --- a/crates/hir/Cargo.toml +++ b/crates/hir/Cargo.toml @@ -17,6 +17,7 @@ either.workspace = true arrayvec.workspace = true itertools.workspace = true smallvec.workspace = true +tracing.workspace = true triomphe.workspace = true once_cell = "1.17.1" diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index eafba8a88b89d..28decd4ce710a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -235,7 +235,7 @@ impl Crate { db: &dyn DefDatabase, query: import_map::Query, ) -> impl Iterator> { - let _p = profile::span("query_external_importables"); + let _p = tracing::span!(tracing::Level::INFO, "query_external_importables"); 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), @@ -539,13 +539,8 @@ impl Module { /// Fills `acc` with the module's diagnostics. pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec) { - let _p = profile::span("Module::diagnostics").detail(|| { - format!( - "{:?}", - self.name(db) - .map_or("".into(), |name| name.display(db.upcast()).to_string()) - ) - }); + let name = self.name(db); + let _p = tracing::span!(tracing::Level::INFO, "Module::diagnostics", ?name); let def_map = self.id.def_map(db.upcast()); for diag in def_map.diagnostics() { if diag.in_module != self.id.local_id { @@ -4057,7 +4052,7 @@ impl Type { name: Option<&Name>, mut callback: impl FnMut(Function) -> Option, ) -> Option { - let _p = profile::span("iterate_method_candidates"); + let _p = tracing::span!(tracing::Level::INFO, "iterate_method_candidates"); let mut slot = None; self.iterate_method_candidates_dyn( @@ -4136,7 +4131,7 @@ impl Type { name: Option<&Name>, mut callback: impl FnMut(AssocItem) -> Option, ) -> Option { - let _p = profile::span("iterate_path_candidates"); + let _p = tracing::span!(tracing::Level::INFO, "iterate_path_candidates"); let mut slot = None; self.iterate_path_candidates_dyn( db, @@ -4202,7 +4197,7 @@ impl Type { &'a self, db: &'a dyn HirDatabase, ) -> impl Iterator + 'a { - let _p = profile::span("applicable_inherent_traits"); + let _p = tracing::span!(tracing::Level::INFO, "applicable_inherent_traits"); self.autoderef_(db) .filter_map(|ty| ty.dyn_trait()) .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id)) @@ -4210,7 +4205,7 @@ impl Type { } pub fn env_traits<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator + 'a { - let _p = profile::span("env_traits"); + let _p = tracing::span!(tracing::Level::INFO, "env_traits"); self.autoderef_(db) .filter(|ty| matches!(ty.kind(Interner), TyKind::Placeholder(_))) .flat_map(|ty| { diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 46f3997620abf..7dc84a0353025 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -671,10 +671,8 @@ impl<'db> SemanticsImpl<'db> { mut token: SyntaxToken, f: &mut dyn FnMut(InFile) -> ControlFlow<()>, ) { - let _p = profile::span("descend_into_macros"); - + let _p = tracing::span!(tracing::Level::INFO, "descend_into_macros"); let mut include_macro_file_id_and_span = None; - let sa = match token.parent().and_then(|parent| self.analyze_no_infer(&parent)) { Some(it) => it, None => { @@ -1303,7 +1301,7 @@ impl<'db> SemanticsImpl<'db> { offset: Option, infer_body: bool, ) -> Option { - let _p = profile::span("Semantics::analyze_impl"); + let _p = tracing::span!(tracing::Level::INFO, "Semantics::analyze_impl"); let node = self.find_file(node); let container = self.with_ctx(|ctx| ctx.find_container(node))?; diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index f60b3749b0805..14dbe6924032f 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -117,7 +117,7 @@ pub(super) struct SourceToDefCtx<'a, 'b> { impl SourceToDefCtx<'_, '_> { pub(super) fn file_to_def(&self, file: FileId) -> SmallVec<[ModuleId; 1]> { - let _p = profile::span("SourceBinder::to_module_def"); + let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::to_module_def"); let mut mods = SmallVec::new(); for &crate_id in self.db.relevant_crates(file).iter() { // FIXME: inner items @@ -132,7 +132,7 @@ impl SourceToDefCtx<'_, '_> { } pub(super) fn module_to_def(&self, src: InFile) -> Option { - let _p = profile::span("module_to_def"); + let _p = tracing::span!(tracing::Level::INFO, "module_to_def"); let parent_declaration = src .syntax() .ancestors_with_macros_skip_attr_item(self.db.upcast()) @@ -153,7 +153,7 @@ impl SourceToDefCtx<'_, '_> { } pub(super) fn source_file_to_def(&self, src: InFile) -> Option { - let _p = profile::span("source_file_to_def"); + let _p = tracing::span!(tracing::Level::INFO, "source_file_to_def"); let file_id = src.file_id.original_file(self.db.upcast()); self.file_to_def(file_id).first().copied() } diff --git a/crates/ide-assists/Cargo.toml b/crates/ide-assists/Cargo.toml index 4d4bac5fb9664..98961a18de257 100644 --- a/crates/ide-assists/Cargo.toml +++ b/crates/ide-assists/Cargo.toml @@ -17,6 +17,7 @@ cov-mark = "2.0.0-pre.1" itertools.workspace = true either.workspace = true smallvec.workspace = true +tracing.workspace = true # local deps stdx.workspace = true @@ -38,4 +39,4 @@ sourcegen.workspace = true in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 410c623109ea0..a0f4f8eb846bc 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -105,7 +105,7 @@ fn add_missing_impl_members_inner( assist_id: &'static str, label: &'static str, ) -> Option<()> { - let _p = profile::span("add_missing_impl_members_inner"); + let _p = tracing::span!(tracing::Level::INFO, "add_missing_impl_members_inner"); let impl_def = ctx.find_node_at_offset::()?; let impl_ = ctx.sema.to_def(&impl_def)?; diff --git a/crates/ide-completion/Cargo.toml b/crates/ide-completion/Cargo.toml index 7fbcf3d19e0f1..f2a11276ba2b8 100644 --- a/crates/ide-completion/Cargo.toml +++ b/crates/ide-completion/Cargo.toml @@ -14,6 +14,7 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" itertools.workspace = true +tracing.workspace = true once_cell = "1.17.0" smallvec.workspace = true @@ -38,4 +39,4 @@ test-utils.workspace = true test-fixture.workspace = true [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs index d3c817d4b43ad..1433216d6111d 100644 --- a/crates/ide-completion/src/completions/expr.rs +++ b/crates/ide-completion/src/completions/expr.rs @@ -15,7 +15,7 @@ pub(crate) fn complete_expr_path( path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, expr_ctx: &ExprCtx, ) { - let _p = profile::span("complete_expr_path"); + let _p = tracing::span!(tracing::Level::INFO, "complete_expr_path").entered(); if !ctx.qualifier_ctx.none() { return; } diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs index e330430d6b90b..0e04ad35d33d1 100644 --- a/crates/ide-completion/src/completions/flyimport.rs +++ b/crates/ide-completion/src/completions/flyimport.rs @@ -207,7 +207,8 @@ fn import_on_the_fly( position: SyntaxNode, potential_import_name: String, ) -> Option<()> { - let _p = profile::span("import_on_the_fly").detail(|| potential_import_name.clone()); + let _p = + tracing::span!(tracing::Level::INFO, "import_on_the_fly", ?potential_import_name).entered(); ImportScope::find_insert_use_container(&position, &ctx.sema)?; @@ -293,7 +294,8 @@ fn import_on_the_fly_pat_( position: SyntaxNode, potential_import_name: String, ) -> Option<()> { - let _p = profile::span("import_on_the_fly_pat").detail(|| potential_import_name.clone()); + let _p = tracing::span!(tracing::Level::INFO, "import_on_the_fly_pat", ?potential_import_name) + .entered(); ImportScope::find_insert_use_container(&position, &ctx.sema)?; @@ -343,7 +345,9 @@ fn import_on_the_fly_method( position: SyntaxNode, potential_import_name: String, ) -> Option<()> { - let _p = profile::span("import_on_the_fly_method").detail(|| potential_import_name.clone()); + let _p = + tracing::span!(tracing::Level::INFO, "import_on_the_fly_method", ?potential_import_name) + .entered(); ImportScope::find_insert_use_container(&position, &ctx.sema)?; diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs index 4de15ab759629..addd9dac1a766 100644 --- a/crates/ide-completion/src/completions/item_list.rs +++ b/crates/ide-completion/src/completions/item_list.rs @@ -28,7 +28,7 @@ pub(crate) fn complete_item_list( path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, kind: &ItemListKind, ) { - let _p = profile::span("complete_item_list"); + let _p = tracing::span!(tracing::Level::INFO, "complete_item_list").entered(); if path_ctx.is_trivial_path() { add_keywords(acc, ctx, Some(kind)); } diff --git a/crates/ide-completion/src/completions/mod_.rs b/crates/ide-completion/src/completions/mod_.rs index 5d138eea46f4b..ecf5b29e2c0c3 100644 --- a/crates/ide-completion/src/completions/mod_.rs +++ b/crates/ide-completion/src/completions/mod_.rs @@ -21,7 +21,7 @@ pub(crate) fn complete_mod( return None; } - let _p = profile::span("completion::complete_mod"); + let _p = tracing::span!(tracing::Level::INFO, "completion::complete_mod").entered(); let mut current_module = ctx.module; // For `mod $0`, `ctx.module` is its parent, but for `mod f$0`, it's `mod f` itself, but we're diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs index a30fd13b1d5f3..e6a4335c3fec8 100644 --- a/crates/ide-completion/src/completions/type.rs +++ b/crates/ide-completion/src/completions/type.rs @@ -15,7 +15,7 @@ pub(crate) fn complete_type_path( path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, location: &TypeLocation, ) { - let _p = profile::span("complete_type_path"); + let _p = tracing::span!(tracing::Level::INFO, "complete_type_path").entered(); let scope_def_applicable = |def| { use hir::{GenericParam::*, ModuleDef::*}; diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index 575f524209c70..2c0370c58f70a 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -568,7 +568,8 @@ impl CompletionContext<'_> { /// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items and /// passes all doc-aliases along, to funnel it into [`Completions::add_path_resolution`]. pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef, Vec)) { - let _p = profile::span("CompletionContext::process_all_names"); + let _p = + tracing::span!(tracing::Level::INFO, "CompletionContext::process_all_names").entered(); self.scope.process_all_names(&mut |name, def| { if self.is_scope_def_hidden(def) { return; @@ -579,7 +580,8 @@ impl CompletionContext<'_> { } pub(crate) fn process_all_names_raw(&self, f: &mut dyn FnMut(Name, ScopeDef)) { - let _p = profile::span("CompletionContext::process_all_names_raw"); + let _p = tracing::span!(tracing::Level::INFO, "CompletionContext::process_all_names_raw") + .entered(); self.scope.process_all_names(f); } @@ -637,7 +639,7 @@ impl<'a> CompletionContext<'a> { position @ FilePosition { file_id, offset }: FilePosition, config: &'a CompletionConfig, ) -> Option<(CompletionContext<'a>, CompletionAnalysis)> { - let _p = profile::span("CompletionContext::new"); + let _p = tracing::span!(tracing::Level::INFO, "CompletionContext::new").entered(); let sema = Semantics::new(db); let original_file = sema.parse(file_id); diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 8a4ac00de9105..65ecaf6bac531 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -72,7 +72,7 @@ fn expand( mut fake_ident_token: SyntaxToken, relative_offset: TextSize, ) -> ExpansionResult { - let _p = profile::span("CompletionContext::expand"); + let _p = tracing::span!(tracing::Level::INFO, "CompletionContext::expand").entered(); let mut derive_ctx = None; 'expansion: loop { @@ -211,7 +211,7 @@ fn analyze( original_token: &SyntaxToken, self_token: &SyntaxToken, ) -> Option<(CompletionAnalysis, (Option, Option), QualifierCtx)> { - let _p = profile::span("CompletionContext::analyze"); + let _p = tracing::span!(tracing::Level::INFO, "CompletionContext::analyze").entered(); let ExpansionResult { original_file, speculative_file, offset, fake_ident_token, derive_ctx } = expansion_result; diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs index 864b993f7136e..bcf169f46530d 100644 --- a/crates/ide-completion/src/item.rs +++ b/crates/ide-completion/src/item.rs @@ -433,7 +433,7 @@ impl Builder { } pub(crate) fn build(self, db: &RootDatabase) -> CompletionItem { - let _p = profile::span("item::Builder::build"); + let _p = tracing::span!(tracing::Level::INFO, "item::Builder::build").entered(); let label = self.label; let mut label_detail = None; diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs index d26b6f431b5b4..733523d369424 100644 --- a/crates/ide-completion/src/lib.rs +++ b/crates/ide-completion/src/lib.rs @@ -236,7 +236,7 @@ pub fn resolve_completion_edits( FilePosition { file_id, offset }: FilePosition, imports: impl IntoIterator, ) -> Option> { - let _p = profile::span("resolve_completion_edits"); + let _p = tracing::span!(tracing::Level::INFO, "resolve_completion_edits").entered(); let sema = hir::Semantics::new(db); let original_file = sema.parse(file_id); diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index ad26280ae748f..4d49d2f4987f1 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -292,7 +292,7 @@ fn render_resolution_pat( import_to_add: Option, resolution: ScopeDef, ) -> Builder { - let _p = profile::span("render_resolution"); + let _p = tracing::span!(tracing::Level::INFO, "render_resolution").entered(); use hir::ModuleDef::*; if let ScopeDef::ModuleDef(Macro(mac)) = resolution { @@ -310,7 +310,7 @@ fn render_resolution_path( import_to_add: Option, resolution: ScopeDef, ) -> Builder { - let _p = profile::span("render_resolution"); + let _p = tracing::span!(tracing::Level::INFO, "render_resolution").entered(); use hir::ModuleDef::*; match resolution { @@ -418,7 +418,7 @@ fn render_resolution_simple_( import_to_add: Option, resolution: ScopeDef, ) -> Builder { - let _p = profile::span("render_resolution"); + let _p = tracing::span!(tracing::Level::INFO, "render_resolution").entered(); let db = ctx.db(); let ctx = ctx.import_to_add(import_to_add); diff --git a/crates/ide-completion/src/render/const_.rs b/crates/ide-completion/src/render/const_.rs index 3c73983c39a2b..a2bfac994ff0b 100644 --- a/crates/ide-completion/src/render/const_.rs +++ b/crates/ide-completion/src/render/const_.rs @@ -6,7 +6,7 @@ use ide_db::SymbolKind; use crate::{item::CompletionItem, render::RenderContext}; pub(crate) fn render_const(ctx: RenderContext<'_>, const_: hir::Const) -> Option { - let _p = profile::span("render_const"); + let _p = tracing::span!(tracing::Level::INFO, "render_const").entered(); render(ctx, const_) } diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index 0f2608d1325a9..4ae7ea861c75b 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -25,7 +25,7 @@ pub(crate) fn render_fn( local_name: Option, func: hir::Function, ) -> Builder { - let _p = profile::span("render_fn"); + let _p = tracing::span!(tracing::Level::INFO, "render_fn").entered(); render(ctx, local_name, func, FuncKind::Function(path_ctx)) } @@ -36,7 +36,7 @@ pub(crate) fn render_method( local_name: Option, func: hir::Function, ) -> Builder { - let _p = profile::span("render_method"); + let _p = tracing::span!(tracing::Level::INFO, "render_method").entered(); render(ctx, local_name, func, FuncKind::Method(dot_access, receiver)) } diff --git a/crates/ide-completion/src/render/literal.rs b/crates/ide-completion/src/render/literal.rs index f2d67df01d31b..f52a5f7625557 100644 --- a/crates/ide-completion/src/render/literal.rs +++ b/crates/ide-completion/src/render/literal.rs @@ -27,7 +27,7 @@ pub(crate) fn render_variant_lit( variant: hir::Variant, path: Option, ) -> Option { - let _p = profile::span("render_enum_variant"); + let _p = tracing::span!(tracing::Level::INFO, "render_enum_variant").entered(); let db = ctx.db(); let name = local_name.unwrap_or_else(|| variant.name(db)); @@ -41,7 +41,7 @@ pub(crate) fn render_struct_literal( path: Option, local_name: Option, ) -> Option { - let _p = profile::span("render_struct_literal"); + let _p = tracing::span!(tracing::Level::INFO, "render_struct_literal").entered(); let db = ctx.db(); let name = local_name.unwrap_or_else(|| strukt.name(db)); diff --git a/crates/ide-completion/src/render/macro_.rs b/crates/ide-completion/src/render/macro_.rs index 915a245ab6b4c..540cfd03d6061 100644 --- a/crates/ide-completion/src/render/macro_.rs +++ b/crates/ide-completion/src/render/macro_.rs @@ -17,7 +17,7 @@ pub(crate) fn render_macro( name: hir::Name, macro_: hir::Macro, ) -> Builder { - let _p = profile::span("render_macro"); + let _p = tracing::span!(tracing::Level::INFO, "render_macro").entered(); render(ctx, *kind == PathKind::Use, *has_macro_bang, *has_call_parens, name, macro_) } @@ -27,7 +27,7 @@ pub(crate) fn render_macro_pat( name: hir::Name, macro_: hir::Macro, ) -> Builder { - let _p = profile::span("render_macro"); + let _p = tracing::span!(tracing::Level::INFO, "render_macro").entered(); render(ctx, false, false, false, name, macro_) } diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs index 6f998119b7cac..a5f851566cb08 100644 --- a/crates/ide-completion/src/render/pattern.rs +++ b/crates/ide-completion/src/render/pattern.rs @@ -20,7 +20,7 @@ pub(crate) fn render_struct_pat( strukt: hir::Struct, local_name: Option, ) -> Option { - let _p = profile::span("render_struct_pat"); + let _p = tracing::span!(tracing::Level::INFO, "render_struct_pat").entered(); let fields = strukt.fields(ctx.db()); let (visible_fields, fields_omitted) = visible_fields(ctx.completion, &fields, strukt)?; @@ -50,7 +50,7 @@ pub(crate) fn render_variant_pat( local_name: Option, path: Option<&hir::ModPath>, ) -> Option { - let _p = profile::span("render_variant_pat"); + let _p = tracing::span!(tracing::Level::INFO, "render_variant_pat").entered(); let fields = variant.fields(ctx.db()); let (visible_fields, fields_omitted) = visible_fields(ctx.completion, &fields, variant)?; diff --git a/crates/ide-completion/src/render/type_alias.rs b/crates/ide-completion/src/render/type_alias.rs index 343ba7e28d8e0..b192309e93f34 100644 --- a/crates/ide-completion/src/render/type_alias.rs +++ b/crates/ide-completion/src/render/type_alias.rs @@ -10,7 +10,7 @@ pub(crate) fn render_type_alias( ctx: RenderContext<'_>, type_alias: hir::TypeAlias, ) -> Option { - let _p = profile::span("render_type_alias"); + let _p = tracing::span!(tracing::Level::INFO, "render_type_alias").entered(); render(ctx, type_alias, false) } @@ -18,7 +18,7 @@ pub(crate) fn render_type_alias_with_eq( ctx: RenderContext<'_>, type_alias: hir::TypeAlias, ) -> Option { - let _p = profile::span("render_type_alias_with_eq"); + let _p = tracing::span!(tracing::Level::INFO, "render_type_alias_with_eq").entered(); render(ctx, type_alias, true) } diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs index 766d1c1e43dba..296253aa1ee19 100644 --- a/crates/ide-db/src/apply_change.rs +++ b/crates/ide-db/src/apply_change.rs @@ -15,12 +15,13 @@ use crate::{symbol_index::SymbolsDatabase, Change, RootDatabase}; impl RootDatabase { pub fn request_cancellation(&mut self) { - let _p = profile::span("RootDatabase::request_cancellation"); + let _p = + tracing::span!(tracing::Level::INFO, "RootDatabase::request_cancellation").entered(); self.salsa_runtime_mut().synthetic_write(Durability::LOW); } pub fn apply_change(&mut self, change: Change) { - let _p = profile::span("RootDatabase::apply_change"); + let _p = tracing::span!(tracing::Level::INFO, "RootDatabase::apply_change").entered(); self.request_cancellation(); tracing::trace!("apply_change {:?}", change); if let Some(roots) = &change.source_change.roots { diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 5995b318e8eff..81f2f87d96236 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -404,7 +404,7 @@ impl NameClass { } pub fn classify(sema: &Semantics<'_, RootDatabase>, name: &ast::Name) -> Option { - let _p = profile::span("classify_name"); + let _p = tracing::span!(tracing::Level::INFO, "classify_name").entered(); let parent = name.syntax().parent()?; @@ -496,7 +496,7 @@ impl NameClass { sema: &Semantics<'_, RootDatabase>, lifetime: &ast::Lifetime, ) -> Option { - let _p = profile::span("classify_lifetime").detail(|| lifetime.to_string()); + let _p = tracing::span!(tracing::Level::INFO, "classify_lifetime", ?lifetime).entered(); let parent = lifetime.syntax().parent()?; if let Some(it) = ast::LifetimeParam::cast(parent.clone()) { @@ -587,7 +587,7 @@ impl NameRefClass { sema: &Semantics<'_, RootDatabase>, name_ref: &ast::NameRef, ) -> Option { - let _p = profile::span("classify_name_ref").detail(|| name_ref.to_string()); + let _p = tracing::span!(tracing::Level::INFO, "classify_name_ref", ?name_ref).entered(); let parent = name_ref.syntax().parent()?; @@ -686,7 +686,7 @@ impl NameRefClass { sema: &Semantics<'_, RootDatabase>, lifetime: &ast::Lifetime, ) -> Option { - let _p = profile::span("classify_lifetime_ref").detail(|| lifetime.to_string()); + let _p = tracing::span!(tracing::Level::INFO, "classify_lifetime_ref", ?lifetime).entered(); let parent = lifetime.syntax().parent()?; match parent.kind() { SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => { diff --git a/crates/ide-db/src/helpers.rs b/crates/ide-db/src/helpers.rs index 9363bdfa14b2a..0b5ad7060e043 100644 --- a/crates/ide-db/src/helpers.rs +++ b/crates/ide-db/src/helpers.rs @@ -35,7 +35,7 @@ pub fn pick_token(mut tokens: TokenAtOffset) -> Option /// Converts the mod path struct into its ast representation. pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path { - let _p = profile::span("mod_path_to_ast"); + let _p = tracing::span!(tracing::Level::INFO, "mod_path_to_ast").entered(); let mut segments = Vec::new(); let mut is_abs = false; diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs index 089bd44c2a5da..cb3f01f345825 100644 --- a/crates/ide-db/src/imports/import_assets.rs +++ b/crates/ide-db/src/imports/import_assets.rs @@ -208,7 +208,8 @@ impl ImportAssets { prefer_no_std: bool, prefer_prelude: bool, ) -> impl Iterator { - let _p = profile::span("import_assets::search_for_imports"); + let _p = + tracing::span!(tracing::Level::INFO, "import_assets::search_for_imports").entered(); self.search_for(sema, Some(prefix_kind), prefer_no_std, prefer_prelude) } @@ -219,7 +220,8 @@ impl ImportAssets { prefer_no_std: bool, prefer_prelude: bool, ) -> impl Iterator { - let _p = profile::span("import_assets::search_for_relative_paths"); + let _p = tracing::span!(tracing::Level::INFO, "import_assets::search_for_relative_paths") + .entered(); self.search_for(sema, None, prefer_no_std, prefer_prelude) } @@ -260,7 +262,7 @@ impl ImportAssets { prefer_no_std: bool, prefer_prelude: bool, ) -> impl Iterator { - let _p = profile::span("import_assets::search_for"); + let _p = tracing::span!(tracing::Level::INFO, "import_assets::search_for").entered(); let scope = match sema.scope(&self.candidate_node) { Some(it) => it, @@ -305,7 +307,7 @@ impl ImportAssets { } fn scope_definitions(&self, sema: &Semantics<'_, RootDatabase>) -> FxHashSet { - let _p = profile::span("import_assets::scope_definitions"); + let _p = tracing::span!(tracing::Level::INFO, "import_assets::scope_definitions").entered(); let mut scope_definitions = FxHashSet::default(); if let Some(scope) = sema.scope(&self.candidate_node) { scope.process_all_names(&mut |_, scope_def| { @@ -323,7 +325,8 @@ fn path_applicable_imports( mod_path: impl Fn(ItemInNs) -> Option + Copy, scope_filter: impl Fn(ItemInNs) -> bool + Copy, ) -> FxHashSet { - let _p = profile::span("import_assets::path_applicable_imports"); + let _p = + tracing::span!(tracing::Level::INFO, "import_assets::path_applicable_imports").entered(); match &path_candidate.qualifier { None => { @@ -370,7 +373,7 @@ fn import_for_item( original_item: ItemInNs, scope_filter: impl Fn(ItemInNs) -> bool, ) -> Option { - let _p = profile::span("import_assets::import_for_item"); + let _p = tracing::span!(tracing::Level::INFO, "import_assets::import_for_item").entered(); let [first_segment, ..] = unresolved_qualifier else { return None }; let item_as_assoc = item_as_assoc(db, original_item); @@ -504,7 +507,8 @@ fn trait_applicable_items( mod_path: impl Fn(ItemInNs) -> Option, scope_filter: impl Fn(hir::Trait) -> bool, ) -> FxHashSet { - let _p = profile::span("import_assets::trait_applicable_items"); + let _p = + tracing::span!(tracing::Level::INFO, "import_assets::trait_applicable_items").entered(); let db = sema.db; diff --git a/crates/ide-db/src/imports/insert_use.rs b/crates/ide-db/src/imports/insert_use.rs index 5f5ec44687096..f29f91eea84f5 100644 --- a/crates/ide-db/src/imports/insert_use.rs +++ b/crates/ide-db/src/imports/insert_use.rs @@ -194,7 +194,7 @@ fn insert_use_with_alias_option( cfg: &InsertUseConfig, alias: Option, ) { - let _p = profile::span("insert_use"); + let _p = tracing::span!(tracing::Level::INFO, "insert_use").entered(); let mut mb = match cfg.granularity { ImportGranularity::Crate => Some(MergeBehavior::Crate), ImportGranularity::Module => Some(MergeBehavior::Module), diff --git a/crates/ide-db/src/items_locator.rs b/crates/ide-db/src/items_locator.rs index 432f1d745d205..1b6f650768b9e 100644 --- a/crates/ide-db/src/items_locator.rs +++ b/crates/ide-db/src/items_locator.rs @@ -20,14 +20,9 @@ pub fn items_with_name<'a>( name: NameToImport, assoc_item_search: AssocSearchMode, ) -> impl Iterator + 'a { - let _p = profile::span("items_with_name").detail(|| { - format!( - "Name: {}, crate: {:?}, assoc items: {:?}", - name.text(), - assoc_item_search, - krate.display_name(sema.db).map(|name| name.to_string()), - ) - }); + let krate_name = krate.display_name(sema.db).map(|name| name.to_string()); + let _p = tracing::span!(tracing::Level::INFO, "items_with_name", name = name.text(), assoc_item_search = ?assoc_item_search, crate = ?krate_name) + .entered(); let prefix = matches!(name, NameToImport::Prefix(..)); let (local_query, external_query) = match name { @@ -77,7 +72,7 @@ fn find_items<'a>( local_query: symbol_index::Query, external_query: import_map::Query, ) -> impl Iterator + 'a { - let _p = profile::span("find_items"); + let _p = tracing::span!(tracing::Level::INFO, "find_items").entered(); let db = sema.db; // NOTE: `external_query` includes `assoc_item_search`, so we don't need to diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index 7769d8fba100c..a596134178a75 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -273,7 +273,7 @@ impl IntoIterator for SearchScope { impl Definition { fn search_scope(&self, db: &RootDatabase) -> SearchScope { - let _p = profile::span("search_scope"); + let _p = tracing::span!(tracing::Level::INFO, "search_scope").entered(); if let Definition::BuiltinType(_) = self { return SearchScope::crate_graph(db); @@ -435,7 +435,7 @@ impl<'a> FindUsages<'a> { } pub fn search(&self, sink: &mut dyn FnMut(FileId, FileReference) -> bool) { - let _p = profile::span("FindUsages:search"); + let _p = tracing::span!(tracing::Level::INFO, "FindUsages:search").entered(); let sema = self.sema; let search_scope = { diff --git a/crates/ide-db/src/symbol_index.rs b/crates/ide-db/src/symbol_index.rs index 7774b0834dca5..92c09089e1f13 100644 --- a/crates/ide-db/src/symbol_index.rs +++ b/crates/ide-db/src/symbol_index.rs @@ -124,7 +124,7 @@ pub trait SymbolsDatabase: HirDatabase + SourceDatabaseExt + Upcast Arc { - let _p = profile::span("library_symbols"); + let _p = tracing::span!(tracing::Level::INFO, "library_symbols").entered(); let mut symbol_collector = SymbolCollector::new(db.upcast()); @@ -142,14 +142,14 @@ fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Ar } fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc { - let _p = profile::span("module_symbols"); + let _p = tracing::span!(tracing::Level::INFO, "module_symbols").entered(); let symbols = SymbolCollector::collect_module(db.upcast(), module); Arc::new(SymbolIndex::new(symbols)) } pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc]> { - let _p = profile::span("crate_symbols"); + let _p = tracing::span!(tracing::Level::INFO, "crate_symbols").entered(); krate.modules(db.upcast()).into_iter().map(|module| db.module_symbols(module)).collect() } @@ -200,7 +200,7 @@ impl std::ops::Deref for Snap { // | VS Code | kbd:[Ctrl+T] // |=== pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec { - let _p = profile::span("world_symbols").detail(|| query.query.clone()); + let _p = tracing::span!(tracing::Level::INFO, "world_symbols", query = ?query.query).entered(); let indices: Vec<_> = if query.libs { db.library_roots() @@ -320,7 +320,7 @@ impl Query { indices: &'sym [Arc], cb: impl FnMut(&'sym FileSymbol), ) { - let _p = profile::span("symbol_index::Query::search"); + let _p = tracing::span!(tracing::Level::INFO, "symbol_index::Query::search").entered(); let mut op = fst::map::OpBuilder::new(); match self.mode { SearchMode::Exact => { diff --git a/crates/ide-diagnostics/Cargo.toml b/crates/ide-diagnostics/Cargo.toml index 3ed48457a2842..69768041389ac 100644 --- a/crates/ide-diagnostics/Cargo.toml +++ b/crates/ide-diagnostics/Cargo.toml @@ -16,6 +16,7 @@ cov-mark = "2.0.0-pre.1" either.workspace = true itertools.workspace = true serde_json.workspace = true +tracing.workspace = true once_cell = "1.17.0" # local deps @@ -39,4 +40,4 @@ sourcegen.workspace = true in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index f35fc5b533a66..535fb45cd68c0 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -293,7 +293,7 @@ pub fn diagnostics( resolve: &AssistResolveStrategy, file_id: FileId, ) -> Vec { - let _p = profile::span("diagnostics"); + let _p = tracing::span!(tracing::Level::INFO, "diagnostics").entered(); let sema = Semantics::new(db); let parse = db.parse(file_id); let mut res = Vec::new(); diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs index c3a403b10704b..c1c62e3cdaa97 100644 --- a/crates/ide/src/highlight_related.rs +++ b/crates/ide/src/highlight_related.rs @@ -55,7 +55,7 @@ pub(crate) fn highlight_related( config: HighlightRelatedConfig, pos @ FilePosition { offset, file_id }: FilePosition, ) -> Option> { - let _p = profile::span("highlight_related"); + let _p = tracing::span!(tracing::Level::INFO, "highlight_related").entered(); let syntax = sema.parse(file_id).syntax().clone(); let token = pick_best_token(syntax.token_at_offset(offset), |kind| match kind { diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 46e5901852ae5..8311e770b4b41 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -454,7 +454,7 @@ pub(crate) fn inlay_hints( range_limit: Option, config: &InlayHintsConfig, ) -> Vec { - let _p = profile::span("inlay_hints"); + let _p = tracing::span!(tracing::Level::INFO, "inlay_hints").entered(); let sema = Semantics::new(db); let file = sema.parse(file_id); let file = file.syntax(); diff --git a/crates/ide/src/prime_caches.rs b/crates/ide/src/prime_caches.rs index d704d12a05b23..a95d1771ce0b3 100644 --- a/crates/ide/src/prime_caches.rs +++ b/crates/ide/src/prime_caches.rs @@ -33,7 +33,7 @@ pub(crate) fn parallel_prime_caches( num_worker_threads: u8, cb: &(dyn Fn(ParallelPrimeCachesProgress) + Sync), ) { - let _p = profile::span("prime_caches"); + let _p = tracing::span!(tracing::Level::INFO, "prime_caches").entered(); let graph = db.crate_graph(); let mut crates_to_prime = { diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 78fe84f70d3a6..df7a4a3332a8d 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -57,7 +57,7 @@ pub(crate) fn find_all_refs( position: FilePosition, search_scope: Option, ) -> Option> { - let _p = profile::span("find_all_refs"); + let _p = tracing::span!(tracing::Level::INFO, "find_all_refs").entered(); let syntax = sema.parse(position.file_id).syntax().clone(); let make_searcher = |literal_search: bool| { move |def: Definition| { diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 8c6f5e2e9cb50..dfcbaf54d4f92 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -186,7 +186,7 @@ pub(crate) fn highlight( file_id: FileId, range_to_highlight: Option, ) -> Vec { - let _p = profile::span("highlight"); + let _p = tracing::span!(tracing::Level::INFO, "highlight").entered(); let sema = Semantics::new(db); // Determine the root based on the given range. diff --git a/crates/proc-macro-api/src/lib.rs b/crates/proc-macro-api/src/lib.rs index 208051113a7d2..345608d3d0c68 100644 --- a/crates/proc-macro-api/src/lib.rs +++ b/crates/proc-macro-api/src/lib.rs @@ -113,7 +113,7 @@ impl ProcMacroServer { } pub fn load_dylib(&self, dylib: MacroDylib) -> Result, ServerError> { - let _p = profile::span("ProcMacroClient::load_dylib"); + let _p = tracing::span!(tracing::Level::INFO, "ProcMacroClient::load_dylib").entered(); let macros = self.process.lock().unwrap_or_else(|e| e.into_inner()).find_proc_macros(&dylib.path)?; diff --git a/crates/profile/Cargo.toml b/crates/profile/Cargo.toml index 5350023c88fac..a87b67f5c69f3 100644 --- a/crates/profile/Cargo.toml +++ b/crates/profile/Cargo.toml @@ -13,6 +13,7 @@ doctest = false [dependencies] once_cell = "1.17.0" +tracing.workspace = true cfg-if = "1.0.0" la-arena.workspace = true libc.workspace = true @@ -33,4 +34,4 @@ jemalloc = ["jemalloc-ctl"] # default = [ "cpu_profiler" ] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/profile/src/hprof.rs b/crates/profile/src/hprof.rs deleted file mode 100644 index ea89a89c5c5ca..0000000000000 --- a/crates/profile/src/hprof.rs +++ /dev/null @@ -1,326 +0,0 @@ -//! Simple hierarchical profiler -use std::{ - cell::RefCell, - collections::{BTreeMap, HashSet}, - env, fmt, - io::{stderr, Write}, - sync::{ - atomic::{AtomicBool, Ordering}, - RwLock, - }, - time::{Duration, Instant}, -}; - -use once_cell::sync::Lazy; - -use crate::tree::{Idx, Tree}; - -/// Filtering syntax -/// env RA_PROFILE=* // dump everything -/// env RA_PROFILE=foo|bar|baz // enabled only selected entries -/// env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms -pub fn init() { - countme::enable(env::var("RA_COUNT").is_ok()); - let spec = env::var("RA_PROFILE").unwrap_or_default(); - init_from(&spec); -} - -pub fn init_from(spec: &str) { - let filter = if spec.is_empty() { Filter::disabled() } else { Filter::from_spec(spec) }; - filter.install(); -} - -type Label = &'static str; - -/// This function starts a profiling scope in the current execution stack with a given description. -/// It returns a `Profile` struct that measures elapsed time between this method invocation and `Profile` struct drop. -/// It supports nested profiling scopes in case when this function is invoked multiple times at the execution stack. -/// In this case the profiling information will be nested at the output. -/// Profiling information is being printed in the stderr. -/// -/// # Example -/// ``` -/// profile::init_from("profile1|profile2@2"); -/// profiling_function1(); -/// -/// fn profiling_function1() { -/// let _p = profile::span("profile1"); -/// profiling_function2(); -/// } -/// -/// fn profiling_function2() { -/// let _p = profile::span("profile2"); -/// } -/// ``` -/// This will print in the stderr the following: -/// ```text -/// 0ms - profile -/// 0ms - profile2 -/// ``` -#[inline] -pub fn span(label: Label) -> ProfileSpan { - debug_assert!(!label.is_empty()); - - let enabled = PROFILING_ENABLED.load(Ordering::Relaxed); - if enabled && with_profile_stack(|stack| stack.push(label)) { - ProfileSpan(Some(ProfilerImpl { label, detail: None })) - } else { - ProfileSpan(None) - } -} - -#[inline] -pub fn heartbeat_span() -> HeartbeatSpan { - let enabled = PROFILING_ENABLED.load(Ordering::Relaxed); - HeartbeatSpan::new(enabled) -} - -#[inline] -pub fn heartbeat() { - let enabled = PROFILING_ENABLED.load(Ordering::Relaxed); - if enabled { - with_profile_stack(|it| it.heartbeat(1)); - } -} - -pub struct ProfileSpan(Option); - -struct ProfilerImpl { - label: Label, - detail: Option, -} - -impl ProfileSpan { - pub fn detail(mut self, detail: impl FnOnce() -> String) -> ProfileSpan { - if let Some(profiler) = &mut self.0 { - profiler.detail = Some(detail()); - } - self - } -} - -impl Drop for ProfilerImpl { - #[inline] - fn drop(&mut self) { - with_profile_stack(|it| it.pop(self.label, self.detail.take())); - } -} - -pub struct HeartbeatSpan { - enabled: bool, -} - -impl HeartbeatSpan { - #[inline] - pub fn new(enabled: bool) -> Self { - if enabled { - with_profile_stack(|it| it.heartbeats(true)); - } - Self { enabled } - } -} - -impl Drop for HeartbeatSpan { - fn drop(&mut self) { - if self.enabled { - with_profile_stack(|it| it.heartbeats(false)); - } - } -} - -static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false); -static FILTER: Lazy> = Lazy::new(Default::default); - -fn with_profile_stack(f: impl FnOnce(&mut ProfileStack) -> T) -> T { - thread_local!(static STACK: RefCell = RefCell::new(ProfileStack::new())); - STACK.with(|it| f(&mut it.borrow_mut())) -} - -#[derive(Default, Clone, Debug)] -struct Filter { - depth: usize, - allowed: HashSet, - longer_than: Duration, - heartbeat_longer_than: Duration, - version: usize, -} - -impl Filter { - fn disabled() -> Filter { - Filter::default() - } - - fn from_spec(mut spec: &str) -> Filter { - let longer_than = if let Some(idx) = spec.rfind('>') { - let longer_than = spec[idx + 1..].parse().expect("invalid profile longer_than"); - spec = &spec[..idx]; - Duration::from_millis(longer_than) - } else { - Duration::new(0, 0) - }; - let heartbeat_longer_than = longer_than; - - let depth = if let Some(idx) = spec.rfind('@') { - let depth: usize = spec[idx + 1..].parse().expect("invalid profile depth"); - spec = &spec[..idx]; - depth - } else { - 999 - }; - let allowed = - if spec == "*" { HashSet::new() } else { spec.split('|').map(String::from).collect() }; - Filter { depth, allowed, longer_than, heartbeat_longer_than, version: 0 } - } - - fn install(mut self) { - PROFILING_ENABLED.store(self.depth > 0, Ordering::SeqCst); - let mut old = FILTER.write().unwrap(); - self.version = old.version + 1; - *old = self; - } -} - -struct ProfileStack { - frames: Vec, - filter: Filter, - messages: Tree, - heartbeats: bool, -} - -struct Frame { - t: Instant, - heartbeats: u32, -} - -#[derive(Default)] -struct Message { - duration: Duration, - label: Label, - detail: Option, -} - -impl ProfileStack { - fn new() -> ProfileStack { - ProfileStack { - frames: Vec::new(), - messages: Tree::default(), - filter: Default::default(), - heartbeats: false, - } - } - - fn push(&mut self, label: Label) -> bool { - if self.frames.is_empty() { - if let Ok(f) = FILTER.try_read() { - if f.version > self.filter.version { - self.filter = f.clone(); - } - }; - } - if self.frames.len() > self.filter.depth { - return false; - } - let allowed = &self.filter.allowed; - if self.frames.is_empty() && !allowed.is_empty() && !allowed.contains(label) { - return false; - } - - self.frames.push(Frame { t: Instant::now(), heartbeats: 0 }); - self.messages.start(); - true - } - - fn pop(&mut self, label: Label, detail: Option) { - let frame = self.frames.pop().unwrap(); - let duration = frame.t.elapsed(); - - if self.heartbeats { - self.heartbeat(frame.heartbeats); - let avg_span = duration / (frame.heartbeats + 1); - if avg_span > self.filter.heartbeat_longer_than { - eprintln!("Too few heartbeats {label} ({}/{duration:?})?", frame.heartbeats); - } - } - - self.messages.finish(Message { duration, label, detail }); - if self.frames.is_empty() { - let longer_than = self.filter.longer_than; - // Convert to millis for comparison to avoid problems with rounding - // (otherwise we could print `0ms` despite user's `>0` filter when - // `duration` is just a few nanos). - if duration.as_millis() > longer_than.as_millis() { - if let Some(root) = self.messages.root() { - print(&self.messages, root, 0, longer_than, &mut stderr().lock()); - } - } - self.messages.clear(); - } - } - - fn heartbeats(&mut self, yes: bool) { - self.heartbeats = yes; - } - fn heartbeat(&mut self, n: u32) { - if let Some(frame) = self.frames.last_mut() { - frame.heartbeats += n; - } - } -} - -fn print( - tree: &Tree, - curr: Idx, - level: u32, - longer_than: Duration, - out: &mut impl Write, -) { - let current_indent = " ".repeat(level as usize); - let detail = tree[curr].detail.as_ref().map(|it| format!(" @ {it}")).unwrap_or_default(); - writeln!( - out, - "{}{} - {}{}", - current_indent, - ms(tree[curr].duration), - tree[curr].label, - detail, - ) - .expect("printing profiling info"); - - let mut accounted_for = Duration::default(); - let mut short_children = BTreeMap::new(); // Use `BTreeMap` to get deterministic output. - for child in tree.children(curr) { - accounted_for += tree[child].duration; - - if tree[child].duration.as_millis() > longer_than.as_millis() { - print(tree, child, level + 1, longer_than, out); - } else { - let (total_duration, cnt) = - short_children.entry(tree[child].label).or_insert((Duration::default(), 0)); - *total_duration += tree[child].duration; - *cnt += 1; - } - } - - for (child_msg, (duration, count)) in &short_children { - writeln!(out, " {current_indent}{} - {child_msg} ({count} calls)", ms(*duration)) - .expect("printing profiling info"); - } - - let unaccounted = tree[curr].duration - accounted_for; - if tree.children(curr).next().is_some() && unaccounted > longer_than { - writeln!(out, " {current_indent}{} - ???", ms(unaccounted)) - .expect("printing profiling info"); - } -} - -#[allow(non_camel_case_types)] -struct ms(Duration); - -impl fmt::Display for ms { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0.as_millis() { - 0 => f.write_str(" 0 "), - n => write!(f, "{n:5}ms"), - } - } -} diff --git a/crates/profile/src/lib.rs b/crates/profile/src/lib.rs index d86aa0c414406..38c5b3fc9c725 100644 --- a/crates/profile/src/lib.rs +++ b/crates/profile/src/lib.rs @@ -4,15 +4,12 @@ #[cfg(feature = "cpu_profiler")] mod google_cpu_profiler; -mod hprof; mod memory_usage; mod stop_watch; -mod tree; use std::cell::RefCell; pub use crate::{ - hprof::{heartbeat, heartbeat_span, init, init_from, span}, memory_usage::{Bytes, MemoryUsage}, stop_watch::{StopWatch, StopWatchSpan}, }; diff --git a/crates/profile/src/tree.rs b/crates/profile/src/tree.rs deleted file mode 100644 index 1290fba36fab3..0000000000000 --- a/crates/profile/src/tree.rs +++ /dev/null @@ -1,84 +0,0 @@ -//! A simple tree implementation which tries to not allocate all over the place. -use std::ops; - -use la_arena::Arena; - -#[derive(Default)] -pub(crate) struct Tree { - nodes: Arena>, - current_path: Vec<(Idx, Option>)>, -} - -pub(crate) type Idx = la_arena::Idx>; - -impl Tree { - pub(crate) fn start(&mut self) - where - T: Default, - { - let me = self.nodes.alloc(Node::new(T::default())); - if let Some((parent, last_child)) = self.current_path.last_mut() { - let slot = match *last_child { - Some(last_child) => &mut self.nodes[last_child].next_sibling, - None => &mut self.nodes[*parent].first_child, - }; - let prev = slot.replace(me); - assert!(prev.is_none()); - *last_child = Some(me); - } - - self.current_path.push((me, None)); - } - - pub(crate) fn finish(&mut self, data: T) { - let (me, _last_child) = self.current_path.pop().unwrap(); - self.nodes[me].data = data; - } - - pub(crate) fn root(&self) -> Option> { - self.nodes.iter().next().map(|(idx, _)| idx) - } - - pub(crate) fn children(&self, idx: Idx) -> impl Iterator> + '_ { - NodeIter { nodes: &self.nodes, next: self.nodes[idx].first_child } - } - pub(crate) fn clear(&mut self) { - self.nodes.clear(); - self.current_path.clear(); - } -} - -impl ops::Index> for Tree { - type Output = T; - fn index(&self, index: Idx) -> &T { - &self.nodes[index].data - } -} - -pub(crate) struct Node { - data: T, - first_child: Option>, - next_sibling: Option>, -} - -impl Node { - fn new(data: T) -> Node { - Node { data, first_child: None, next_sibling: None } - } -} - -struct NodeIter<'a, T> { - nodes: &'a Arena>, - next: Option>, -} - -impl Iterator for NodeIter<'_, T> { - type Item = Idx; - - fn next(&mut self) -> Option> { - self.next.map(|next| { - self.next = self.nodes[next].next_sibling; - next - }) - } -} diff --git a/crates/project-model/src/rustc_cfg.rs b/crates/project-model/src/rustc_cfg.rs index c5d55f7d2171f..cf12d5b71df56 100644 --- a/crates/project-model/src/rustc_cfg.rs +++ b/crates/project-model/src/rustc_cfg.rs @@ -26,7 +26,7 @@ pub(crate) fn get( extra_env: &FxHashMap, config: RustcCfgConfig<'_>, ) -> Vec { - let _p = profile::span("rustc_cfg::get"); + let _p = tracing::span!(tracing::Level::INFO, "rustc_cfg::get").entered(); let mut res = Vec::with_capacity(6 * 2 + 1); // Some nightly-only cfgs, which are required for stdlib diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 88974e889e8bc..e6e2fa7a97800 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -647,7 +647,7 @@ impl ProjectWorkspace { load: &mut dyn FnMut(&AbsPath) -> Option, extra_env: &FxHashMap, ) -> (CrateGraph, ProcMacroPaths) { - let _p = profile::span("ProjectWorkspace::to_crate_graph"); + let _p = tracing::span!(tracing::Level::INFO, "ProjectWorkspace::to_crate_graph").entered(); let (mut crate_graph, proc_macros) = match self { ProjectWorkspace::Json { project, sysroot, rustc_cfg, toolchain } => { @@ -891,7 +891,7 @@ fn cargo_to_crate_graph( target_layout: TargetLayoutLoadResult, toolchain: Option<&Version>, ) -> (CrateGraph, ProcMacroPaths) { - let _p = profile::span("cargo_to_crate_graph"); + let _p = tracing::span!(tracing::Level::INFO, "cargo_to_crate_graph").entered(); let mut res = (CrateGraph::default(), ProcMacroPaths::default()); let crate_graph = &mut res.0; let proc_macros = &mut res.1; @@ -1088,7 +1088,7 @@ fn detached_files_to_crate_graph( sysroot: Option<&Sysroot>, target_layout: TargetLayoutLoadResult, ) -> (CrateGraph, ProcMacroPaths) { - let _p = profile::span("detached_files_to_crate_graph"); + let _p = tracing::span!(tracing::Level::INFO, "detached_files_to_crate_graph").entered(); let mut crate_graph = CrateGraph::default(); let (public_deps, _libproc_macro) = match sysroot { Some(sysroot) => sysroot_to_crate_graph( @@ -1384,7 +1384,7 @@ fn sysroot_to_crate_graph( load: &mut dyn FnMut(&AbsPath) -> Option, toolchain: Option<&Version>, ) -> (SysrootPublicDeps, Option) { - let _p = profile::span("sysroot_to_crate_graph"); + let _p = tracing::span!(tracing::Level::INFO, "sysroot_to_crate_graph").entered(); match sysroot.mode() { SysrootMode::Workspace(cargo) => { let (mut cg, mut pm) = cargo_to_crate_graph( diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index db5cabaf76941..da421e7aaa49f 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -37,11 +37,10 @@ mimalloc = { version = "0.1.30", default-features = false, optional = true } lsp-server.workspace = true tracing.workspace = true tracing-subscriber.workspace = true -tracing-log = "0.2.0" tracing-tree.workspace = true triomphe.workspace = true nohash-hasher.workspace = true -always-assert = "0.1.2" +always-assert = "0.2.0" walkdir = "2.3.2" cfg.workspace = true diff --git a/crates/rust-analyzer/src/bin/logger.rs b/crates/rust-analyzer/src/bin/logger.rs deleted file mode 100644 index 1f923f6cf8dda..0000000000000 --- a/crates/rust-analyzer/src/bin/logger.rs +++ /dev/null @@ -1,137 +0,0 @@ -//! Simple logger that logs either to stderr or to a file, using `tracing_subscriber` -//! filter syntax and `tracing_appender` for non blocking output. - -use std::{ - fmt, - fs::File, - io::{self, Stderr}, - sync::Arc, -}; - -use anyhow::Context; -use tracing::{level_filters::LevelFilter, Event, Subscriber}; -use tracing_log::NormalizeEvent; -use tracing_subscriber::{ - filter::Targets, - fmt::{ - format::Writer, writer::BoxMakeWriter, FmtContext, FormatEvent, FormatFields, - FormattedFields, MakeWriter, - }, - layer::SubscriberExt, - registry::LookupSpan, - util::SubscriberInitExt, - Registry, -}; -use tracing_tree::HierarchicalLayer; - -pub(crate) struct LoggerConfig { - pub(crate) log_file: Option, - pub(crate) filter: String, - pub(crate) chalk_filter: Option, -} - -struct MakeWriterStderr; - -impl MakeWriter<'_> for MakeWriterStderr { - type Writer = Stderr; - - fn make_writer(&self) -> Self::Writer { - io::stderr() - } -} - -impl LoggerConfig { - pub(crate) fn init(self) -> anyhow::Result<()> { - let mut filter: Targets = self - .filter - .parse() - .with_context(|| format!("invalid log filter: `{}`", self.filter))?; - - let mut chalk_layer = None; - if let Some(chalk_filter) = self.chalk_filter { - let level: LevelFilter = - chalk_filter.parse().with_context(|| "invalid chalk log filter")?; - chalk_layer = Some( - HierarchicalLayer::default() - .with_indent_lines(true) - .with_ansi(false) - .with_indent_amount(2) - .with_writer(io::stderr), - ); - filter = filter - .with_target("chalk_solve", level) - .with_target("chalk_ir", level) - .with_target("chalk_recursive", level); - }; - - let writer = match self.log_file { - Some(file) => BoxMakeWriter::new(Arc::new(file)), - None => BoxMakeWriter::new(io::stderr), - }; - let ra_fmt_layer = - tracing_subscriber::fmt::layer().event_format(LoggerFormatter).with_writer(writer); - - let registry = Registry::default().with(filter).with(ra_fmt_layer); - match chalk_layer { - Some(chalk_layer) => registry.with(chalk_layer).init(), - None => registry.init(), - } - Ok(()) - } -} - -#[derive(Debug)] -struct LoggerFormatter; - -impl FormatEvent for LoggerFormatter -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'a> FormatFields<'a> + 'static, -{ - fn format_event( - &self, - ctx: &FmtContext<'_, S, N>, - mut writer: Writer<'_>, - event: &Event<'_>, - ) -> fmt::Result { - // Write level and target - let level = *event.metadata().level(); - - // If this event is issued from `log` crate, then the value of target is - // always "log". `tracing-log` has hard coded it for some reason, so we - // need to extract it using `normalized_metadata` method which is part of - // `tracing_log::NormalizeEvent`. - let target = match event.normalized_metadata() { - // This event is issued from `log` crate - Some(log) => log.target(), - None => event.metadata().target(), - }; - write!(writer, "[{level} {target}] ")?; - - // Write spans and fields of each span - ctx.visit_spans(|span| { - write!(writer, "{}", span.name())?; - - let ext = span.extensions(); - - // `FormattedFields` is a formatted representation of the span's - // fields, which is stored in its extensions by the `fmt` layer's - // `new_span` method. The fields will have been formatted - // by the same field formatter that's provided to the event - // formatter in the `FmtContext`. - let fields = &ext.get::>().expect("will never be `None`"); - - if !fields.is_empty() { - write!(writer, "{{{fields}}}")?; - } - write!(writer, ": ")?; - - Ok(()) - })?; - - // Write fields on the event - ctx.field_format().format_fields(writer.by_ref(), event)?; - - writeln!(writer) - } -} diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 04387291907b7..66b680571a97d 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -7,14 +7,14 @@ #[cfg(feature = "in-rust-tree")] extern crate rustc_driver as _; -mod logger; mod rustc_wrapper; -use std::{env, fs, path::PathBuf, process}; +use std::{env, fs, path::PathBuf, process, sync::Arc}; use anyhow::Context; use lsp_server::Connection; use rust_analyzer::{cli::flags, config::Config, from_json}; +use tracing_subscriber::fmt::writer::BoxMakeWriter; use vfs::AbsPathBuf; #[cfg(feature = "mimalloc")] @@ -123,26 +123,21 @@ fn setup_logging(log_file_flag: Option) -> anyhow::Result<()> { None => None, }; - logger::LoggerConfig { - log_file, + let writer = match log_file { + Some(file) => BoxMakeWriter::new(Arc::new(file)), + None => BoxMakeWriter::new(std::io::stderr), + }; + + rust_analyzer::tracing::Config { + writer, // Deliberately enable all `error` logs if the user has not set RA_LOG, as there is usually // useful information in there for debugging. filter: env::var("RA_LOG").ok().unwrap_or_else(|| "error".to_string()), - // The meaning of CHALK_DEBUG I suspected is to tell chalk crates - // (i.e. chalk-solve, chalk-ir, chalk-recursive) how to filter tracing - // logs. But now we can only have just one filter, which means we have to - // merge chalk filter to our main filter (from RA_LOG env). - // - // The acceptable syntax of CHALK_DEBUG is `target[span{field=value}]=level`. - // As the value should only affect chalk crates, we'd better manually - // specify the target. And for simplicity, CHALK_DEBUG only accept the value - // that specify level. chalk_filter: env::var("CHALK_DEBUG").ok(), + profile_filter: env::var("RA_PROFILE").ok(), } .init()?; - profile::init(); - Ok(()) } diff --git a/crates/rust-analyzer/src/cli/parse.rs b/crates/rust-analyzer/src/cli/parse.rs index 5ef8cdff4cf25..757f2dd70cad9 100644 --- a/crates/rust-analyzer/src/cli/parse.rs +++ b/crates/rust-analyzer/src/cli/parse.rs @@ -5,7 +5,7 @@ use crate::cli::{flags, read_stdin}; impl flags::Parse { pub fn run(self) -> anyhow::Result<()> { - let _p = profile::span("parsing"); + let _p = tracing::span!(tracing::Level::INFO, "parsing").entered(); let text = read_stdin()?; let file = SourceFile::parse(&text).tree(); if !self.no_dump { diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs index ab3881f438b2a..c91b22999dede 100644 --- a/crates/rust-analyzer/src/diagnostics.rs +++ b/crates/rust-analyzer/src/diagnostics.rs @@ -128,7 +128,7 @@ pub(crate) fn fetch_native_diagnostics( snapshot: GlobalStateSnapshot, subscriptions: Vec, ) -> Vec<(FileId, Vec)> { - let _p = profile::span("fetch_native_diagnostics"); + let _p = tracing::span!(tracing::Level::INFO, "fetch_native_diagnostics").entered(); let _ctx = stdx::panic_context::enter("fetch_native_diagnostics".to_owned()); let convert_diagnostic = diff --git a/crates/rust-analyzer/src/dispatch.rs b/crates/rust-analyzer/src/dispatch.rs index 7da4311888181..fa856a796a8ef 100644 --- a/crates/rust-analyzer/src/dispatch.rs +++ b/crates/rust-analyzer/src/dispatch.rs @@ -1,5 +1,8 @@ //! See [RequestDispatcher]. -use std::{fmt, panic, thread}; +use std::{ + fmt::{self, Debug}, + panic, thread, +}; use ide::Cancelled; use lsp_server::ExtractError; @@ -49,6 +52,8 @@ impl RequestDispatcher<'_> { Some(it) => it, None => return self, }; + let _guard = tracing::span!(tracing::Level::INFO, "request", method = ?req.method, "request_id" = ?req.id).entered(); + tracing::debug!(?params); let result = { let _pctx = stdx::panic_context::enter(panic_context); f(self.global_state, params) @@ -74,6 +79,8 @@ impl RequestDispatcher<'_> { Some(it) => it, None => return self, }; + let _guard = tracing::span!(tracing::Level::INFO, "request", method = ?req.method, "request_id" = ?req.id).entered(); + tracing::debug!(?params); let global_state_snapshot = self.global_state.snapshot(); let result = panic::catch_unwind(move || { @@ -192,6 +199,8 @@ impl RequestDispatcher<'_> { Some(it) => it, None => return self, }; + let _guard = tracing::span!(tracing::Level::INFO, "request", method = ?req.method, "request_id" = ?req.id).entered(); + tracing::debug!(?params); let world = self.global_state.snapshot(); if MAIN_POOL { @@ -313,12 +322,16 @@ impl NotificationDispatcher<'_> { ) -> anyhow::Result<&mut Self> where N: lsp_types::notification::Notification, - N::Params: DeserializeOwned + Send, + N::Params: DeserializeOwned + Send + Debug, { let not = match self.not.take() { Some(it) => it, None => return Ok(self), }; + + let _guard = + tracing::span!(tracing::Level::INFO, "notification", method = ?not.method).entered(); + let params = match not.extract::(N::METHOD) { Ok(it) => it, Err(ExtractError::JsonError { method, error }) => { @@ -329,6 +342,9 @@ impl NotificationDispatcher<'_> { return Ok(self); } }; + + tracing::debug!(?params); + let _pctx = stdx::panic_context::enter(format!( "\nversion: {}\nnotification: {}", version(), diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 232c03ae6c4fe..2f226d01155bd 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -215,7 +215,7 @@ impl GlobalState { } pub(crate) fn process_changes(&mut self) -> bool { - let _p = profile::span("GlobalState::process_changes"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::process_changes").entered(); let mut file_changes = FxHashMap::<_, (bool, ChangedFile)>::default(); let (change, modified_rust_files, workspace_structure_change) = { diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs index c556fdee504b8..1f24e95010571 100644 --- a/crates/rust-analyzer/src/handlers/notification.rs +++ b/crates/rust-analyzer/src/handlers/notification.rs @@ -54,7 +54,7 @@ pub(crate) fn handle_did_open_text_document( state: &mut GlobalState, params: DidOpenTextDocumentParams, ) -> anyhow::Result<()> { - let _p = profile::span("handle_did_open_text_document"); + let _p = tracing::span!(tracing::Level::INFO, "handle_did_open_text_document").entered(); if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { let already_exists = state @@ -79,7 +79,7 @@ pub(crate) fn handle_did_change_text_document( state: &mut GlobalState, params: DidChangeTextDocumentParams, ) -> anyhow::Result<()> { - let _p = profile::span("handle_did_change_text_document"); + let _p = tracing::span!(tracing::Level::INFO, "handle_did_change_text_document").entered(); if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { let data = match state.mem_docs.get_mut(&path) { @@ -113,7 +113,7 @@ pub(crate) fn handle_did_close_text_document( state: &mut GlobalState, params: DidCloseTextDocumentParams, ) -> anyhow::Result<()> { - let _p = profile::span("handle_did_close_text_document"); + let _p = tracing::span!(tracing::Level::INFO, "handle_did_close_text_document").entered(); if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { if state.mem_docs.remove(&path).is_err() { @@ -247,7 +247,7 @@ pub(crate) fn handle_did_change_watched_files( } fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool { - let _p = profile::span("run_flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "run_flycheck").entered(); let file_id = state.vfs.read().0.file_id(&vfs_path); if let Some(file_id) = file_id { @@ -326,13 +326,13 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool { } pub(crate) fn handle_cancel_flycheck(state: &mut GlobalState, _: ()) -> anyhow::Result<()> { - let _p = profile::span("handle_stop_flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "handle_stop_flycheck").entered(); state.flycheck.iter().for_each(|flycheck| flycheck.cancel()); Ok(()) } pub(crate) fn handle_clear_flycheck(state: &mut GlobalState, _: ()) -> anyhow::Result<()> { - let _p = profile::span("handle_clear_flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "handle_clear_flycheck").entered(); state.diagnostics.clear_check_all(); Ok(()) } @@ -341,7 +341,7 @@ pub(crate) fn handle_run_flycheck( state: &mut GlobalState, params: RunFlycheckParams, ) -> anyhow::Result<()> { - let _p = profile::span("handle_run_flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "handle_run_flycheck").entered(); if let Some(text_document) = params.text_document { if let Ok(vfs_path) = from_proto::vfs_path(&text_document.uri) { if run_flycheck(state, vfs_path) { diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 1a55dcebc1350..90c3a88cb8674 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -70,7 +70,7 @@ pub(crate) fn handle_analyzer_status( snap: GlobalStateSnapshot, params: lsp_ext::AnalyzerStatusParams, ) -> anyhow::Result { - let _p = profile::span("handle_analyzer_status"); + let _p = tracing::span!(tracing::Level::INFO, "handle_analyzer_status").entered(); let mut buf = String::new(); @@ -114,7 +114,7 @@ pub(crate) fn handle_analyzer_status( } pub(crate) fn handle_memory_usage(state: &mut GlobalState, _: ()) -> anyhow::Result { - let _p = profile::span("handle_memory_usage"); + let _p = tracing::span!(tracing::Level::INFO, "handle_memory_usage").entered(); let mem = state.analysis_host.per_query_memory_usage(); let mut out = String::new(); @@ -135,7 +135,7 @@ pub(crate) fn handle_syntax_tree( snap: GlobalStateSnapshot, params: lsp_ext::SyntaxTreeParams, ) -> anyhow::Result { - let _p = profile::span("handle_syntax_tree"); + let _p = tracing::span!(tracing::Level::INFO, "handle_syntax_tree").entered(); let id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(id)?; let text_range = params.range.and_then(|r| from_proto::text_range(&line_index, r).ok()); @@ -147,7 +147,7 @@ pub(crate) fn handle_view_hir( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { - let _p = profile::span("handle_view_hir"); + let _p = tracing::span!(tracing::Level::INFO, "handle_view_hir").entered(); let position = from_proto::file_position(&snap, params)?; let res = snap.analysis.view_hir(position)?; Ok(res) @@ -157,7 +157,7 @@ pub(crate) fn handle_view_mir( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { - let _p = profile::span("handle_view_mir"); + let _p = tracing::span!(tracing::Level::INFO, "handle_view_mir").entered(); let position = from_proto::file_position(&snap, params)?; let res = snap.analysis.view_mir(position)?; Ok(res) @@ -167,7 +167,7 @@ pub(crate) fn handle_interpret_function( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { - let _p = profile::span("handle_interpret_function"); + let _p = tracing::span!(tracing::Level::INFO, "handle_interpret_function").entered(); let position = from_proto::file_position(&snap, params)?; let res = snap.analysis.interpret_function(position)?; Ok(res) @@ -185,7 +185,7 @@ pub(crate) fn handle_view_item_tree( snap: GlobalStateSnapshot, params: lsp_ext::ViewItemTreeParams, ) -> anyhow::Result { - let _p = profile::span("handle_view_item_tree"); + let _p = tracing::span!(tracing::Level::INFO, "handle_view_item_tree").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let res = snap.analysis.view_item_tree(file_id)?; Ok(res) @@ -195,7 +195,7 @@ pub(crate) fn handle_view_crate_graph( snap: GlobalStateSnapshot, params: ViewCrateGraphParams, ) -> anyhow::Result { - let _p = profile::span("handle_view_crate_graph"); + let _p = tracing::span!(tracing::Level::INFO, "handle_view_crate_graph").entered(); let dot = snap.analysis.view_crate_graph(params.full)?.map_err(anyhow::Error::msg)?; Ok(dot) } @@ -204,7 +204,7 @@ pub(crate) fn handle_expand_macro( snap: GlobalStateSnapshot, params: lsp_ext::ExpandMacroParams, ) -> anyhow::Result> { - let _p = profile::span("handle_expand_macro"); + let _p = tracing::span!(tracing::Level::INFO, "handle_expand_macro").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; let offset = from_proto::offset(&line_index, params.position)?; @@ -217,7 +217,7 @@ pub(crate) fn handle_selection_range( snap: GlobalStateSnapshot, params: lsp_types::SelectionRangeParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_selection_range"); + let _p = tracing::span!(tracing::Level::INFO, "handle_selection_range").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; let res: anyhow::Result> = params @@ -260,7 +260,7 @@ pub(crate) fn handle_matching_brace( snap: GlobalStateSnapshot, params: lsp_ext::MatchingBraceParams, ) -> anyhow::Result> { - let _p = profile::span("handle_matching_brace"); + let _p = tracing::span!(tracing::Level::INFO, "handle_matching_brace").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; params @@ -283,7 +283,7 @@ pub(crate) fn handle_join_lines( snap: GlobalStateSnapshot, params: lsp_ext::JoinLinesParams, ) -> anyhow::Result> { - let _p = profile::span("handle_join_lines"); + let _p = tracing::span!(tracing::Level::INFO, "handle_join_lines").entered(); let config = snap.config.join_lines(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; @@ -308,7 +308,7 @@ pub(crate) fn handle_on_enter( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_on_enter"); + let _p = tracing::span!(tracing::Level::INFO, "handle_on_enter").entered(); let position = from_proto::file_position(&snap, params)?; let edit = match snap.analysis.on_enter(position)? { None => return Ok(None), @@ -323,7 +323,7 @@ pub(crate) fn handle_on_type_formatting( snap: GlobalStateSnapshot, params: lsp_types::DocumentOnTypeFormattingParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_on_type_formatting"); + let _p = tracing::span!(tracing::Level::INFO, "handle_on_type_formatting").entered(); let mut position = from_proto::file_position(&snap, params.text_document_position)?; let line_index = snap.file_line_index(position.file_id)?; @@ -364,7 +364,7 @@ pub(crate) fn handle_document_symbol( snap: GlobalStateSnapshot, params: lsp_types::DocumentSymbolParams, ) -> anyhow::Result> { - let _p = profile::span("handle_document_symbol"); + let _p = tracing::span!(tracing::Level::INFO, "handle_document_symbol").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; @@ -453,7 +453,7 @@ pub(crate) fn handle_workspace_symbol( snap: GlobalStateSnapshot, params: WorkspaceSymbolParams, ) -> anyhow::Result> { - let _p = profile::span("handle_workspace_symbol"); + let _p = tracing::span!(tracing::Level::INFO, "handle_workspace_symbol").entered(); let config = snap.config.workspace_symbol(); let (all_symbols, libs) = decide_search_scope_and_kind(¶ms, &config); @@ -545,7 +545,7 @@ pub(crate) fn handle_will_rename_files( snap: GlobalStateSnapshot, params: lsp_types::RenameFilesParams, ) -> anyhow::Result> { - let _p = profile::span("handle_will_rename_files"); + let _p = tracing::span!(tracing::Level::INFO, "handle_will_rename_files").entered(); let source_changes: Vec = params .files @@ -607,7 +607,7 @@ pub(crate) fn handle_goto_definition( snap: GlobalStateSnapshot, params: lsp_types::GotoDefinitionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_goto_definition"); + let _p = tracing::span!(tracing::Level::INFO, "handle_goto_definition").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let nav_info = match snap.analysis.goto_definition(position)? { None => return Ok(None), @@ -622,7 +622,7 @@ pub(crate) fn handle_goto_declaration( snap: GlobalStateSnapshot, params: lsp_types::request::GotoDeclarationParams, ) -> anyhow::Result> { - let _p = profile::span("handle_goto_declaration"); + let _p = tracing::span!(tracing::Level::INFO, "handle_goto_declaration").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params.clone())?; let nav_info = match snap.analysis.goto_declaration(position)? { None => return handle_goto_definition(snap, params), @@ -637,7 +637,7 @@ pub(crate) fn handle_goto_implementation( snap: GlobalStateSnapshot, params: lsp_types::request::GotoImplementationParams, ) -> anyhow::Result> { - let _p = profile::span("handle_goto_implementation"); + let _p = tracing::span!(tracing::Level::INFO, "handle_goto_implementation").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let nav_info = match snap.analysis.goto_implementation(position)? { None => return Ok(None), @@ -652,7 +652,7 @@ pub(crate) fn handle_goto_type_definition( snap: GlobalStateSnapshot, params: lsp_types::request::GotoTypeDefinitionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_goto_type_definition"); + let _p = tracing::span!(tracing::Level::INFO, "handle_goto_type_definition").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let nav_info = match snap.analysis.goto_type_definition(position)? { None => return Ok(None), @@ -667,7 +667,7 @@ pub(crate) fn handle_parent_module( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_parent_module"); + let _p = tracing::span!(tracing::Level::INFO, "handle_parent_module").entered(); if let Ok(file_path) = ¶ms.text_document.uri.to_file_path() { if file_path.file_name().unwrap_or_default() == "Cargo.toml" { // search workspaces for parent packages or fallback to workspace root @@ -734,7 +734,7 @@ pub(crate) fn handle_runnables( snap: GlobalStateSnapshot, params: lsp_ext::RunnablesParams, ) -> anyhow::Result> { - let _p = profile::span("handle_runnables"); + let _p = tracing::span!(tracing::Level::INFO, "handle_runnables").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; let offset = params.position.and_then(|it| from_proto::offset(&line_index, it).ok()); @@ -829,7 +829,7 @@ pub(crate) fn handle_related_tests( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_related_tests"); + let _p = tracing::span!(tracing::Level::INFO, "handle_related_tests").entered(); let position = from_proto::file_position(&snap, params)?; let tests = snap.analysis.related_tests(position, None)?; @@ -847,7 +847,7 @@ pub(crate) fn handle_completion( snap: GlobalStateSnapshot, params: lsp_types::CompletionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_completion"); + let _p = tracing::span!(tracing::Level::INFO, "handle_completion").entered(); let text_document_position = params.text_document_position.clone(); let position = from_proto::file_position(&snap, params.text_document_position)?; let completion_trigger_character = @@ -875,7 +875,7 @@ pub(crate) fn handle_completion_resolve( snap: GlobalStateSnapshot, mut original_completion: CompletionItem, ) -> anyhow::Result { - let _p = profile::span("handle_completion_resolve"); + let _p = tracing::span!(tracing::Level::INFO, "handle_completion_resolve").entered(); if !all_edits_are_disjoint(&original_completion, &[]) { return Err(invalid_params_error( @@ -931,7 +931,7 @@ pub(crate) fn handle_folding_range( snap: GlobalStateSnapshot, params: FoldingRangeParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_folding_range"); + let _p = tracing::span!(tracing::Level::INFO, "handle_folding_range").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let folds = snap.analysis.folding_ranges(file_id)?; let text = snap.analysis.file_text(file_id)?; @@ -948,7 +948,7 @@ pub(crate) fn handle_signature_help( snap: GlobalStateSnapshot, params: lsp_types::SignatureHelpParams, ) -> anyhow::Result> { - let _p = profile::span("handle_signature_help"); + let _p = tracing::span!(tracing::Level::INFO, "handle_signature_help").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let help = match snap.analysis.signature_help(position)? { Some(it) => it, @@ -963,7 +963,7 @@ pub(crate) fn handle_hover( snap: GlobalStateSnapshot, params: lsp_ext::HoverParams, ) -> anyhow::Result> { - let _p = profile::span("handle_hover"); + let _p = tracing::span!(tracing::Level::INFO, "handle_hover").entered(); let range = match params.position { PositionOrRange::Position(position) => Range::new(position, position), PositionOrRange::Range(range) => range, @@ -1000,7 +1000,7 @@ pub(crate) fn handle_prepare_rename( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_prepare_rename"); + let _p = tracing::span!(tracing::Level::INFO, "handle_prepare_rename").entered(); let position = from_proto::file_position(&snap, params)?; let change = snap.analysis.prepare_rename(position)?.map_err(to_proto::rename_error)?; @@ -1014,7 +1014,7 @@ pub(crate) fn handle_rename( snap: GlobalStateSnapshot, params: RenameParams, ) -> anyhow::Result> { - let _p = profile::span("handle_rename"); + let _p = tracing::span!(tracing::Level::INFO, "handle_rename").entered(); let position = from_proto::file_position(&snap, params.text_document_position)?; let mut change = snap @@ -1051,7 +1051,7 @@ pub(crate) fn handle_references( snap: GlobalStateSnapshot, params: lsp_types::ReferenceParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_references"); + let _p = tracing::span!(tracing::Level::INFO, "handle_references").entered(); let position = from_proto::file_position(&snap, params.text_document_position)?; let exclude_imports = snap.config.find_all_refs_exclude_imports(); @@ -1094,7 +1094,7 @@ pub(crate) fn handle_formatting( snap: GlobalStateSnapshot, params: lsp_types::DocumentFormattingParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_formatting"); + let _p = tracing::span!(tracing::Level::INFO, "handle_formatting").entered(); run_rustfmt(&snap, params.text_document, None) } @@ -1103,7 +1103,7 @@ pub(crate) fn handle_range_formatting( snap: GlobalStateSnapshot, params: lsp_types::DocumentRangeFormattingParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_range_formatting"); + let _p = tracing::span!(tracing::Level::INFO, "handle_range_formatting").entered(); run_rustfmt(&snap, params.text_document, Some(params.range)) } @@ -1112,7 +1112,7 @@ pub(crate) fn handle_code_action( snap: GlobalStateSnapshot, params: lsp_types::CodeActionParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_code_action"); + let _p = tracing::span!(tracing::Level::INFO, "handle_code_action").entered(); if !snap.config.code_action_literals() { // We intentionally don't support command-based actions, as those either @@ -1186,7 +1186,7 @@ pub(crate) fn handle_code_action_resolve( snap: GlobalStateSnapshot, mut code_action: lsp_ext::CodeAction, ) -> anyhow::Result { - let _p = profile::span("handle_code_action_resolve"); + let _p = tracing::span!(tracing::Level::INFO, "handle_code_action_resolve").entered(); let params = match code_action.data.take() { Some(it) => it, None => return Err(invalid_params_error("code action without data".to_string()).into()), @@ -1276,7 +1276,7 @@ pub(crate) fn handle_code_lens( snap: GlobalStateSnapshot, params: lsp_types::CodeLensParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_code_lens"); + let _p = tracing::span!(tracing::Level::INFO, "handle_code_lens").entered(); let lens_config = snap.config.lens(); if lens_config.none() { @@ -1346,7 +1346,7 @@ pub(crate) fn handle_document_highlight( snap: GlobalStateSnapshot, params: lsp_types::DocumentHighlightParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_document_highlight"); + let _p = tracing::span!(tracing::Level::INFO, "handle_document_highlight").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let line_index = snap.file_line_index(position.file_id)?; @@ -1368,7 +1368,7 @@ pub(crate) fn handle_ssr( snap: GlobalStateSnapshot, params: lsp_ext::SsrParams, ) -> anyhow::Result { - let _p = profile::span("handle_ssr"); + let _p = tracing::span!(tracing::Level::INFO, "handle_ssr").entered(); let selections = params .selections .iter() @@ -1388,7 +1388,7 @@ pub(crate) fn handle_inlay_hints( snap: GlobalStateSnapshot, params: InlayHintParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_inlay_hints"); + let _p = tracing::span!(tracing::Level::INFO, "handle_inlay_hints").entered(); let document_uri = ¶ms.text_document.uri; let FileRange { file_id, range } = from_proto::file_range( &snap, @@ -1418,7 +1418,7 @@ pub(crate) fn handle_inlay_hints_resolve( snap: GlobalStateSnapshot, mut original_hint: InlayHint, ) -> anyhow::Result { - let _p = profile::span("handle_inlay_hints_resolve"); + let _p = tracing::span!(tracing::Level::INFO, "handle_inlay_hints_resolve").entered(); let data = match original_hint.data.take() { Some(it) => it, @@ -1465,7 +1465,7 @@ pub(crate) fn handle_call_hierarchy_prepare( snap: GlobalStateSnapshot, params: CallHierarchyPrepareParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_call_hierarchy_prepare"); + let _p = tracing::span!(tracing::Level::INFO, "handle_call_hierarchy_prepare").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let nav_info = match snap.analysis.call_hierarchy(position)? { @@ -1487,7 +1487,7 @@ pub(crate) fn handle_call_hierarchy_incoming( snap: GlobalStateSnapshot, params: CallHierarchyIncomingCallsParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_call_hierarchy_incoming"); + let _p = tracing::span!(tracing::Level::INFO, "handle_call_hierarchy_incoming").entered(); let item = params.item; let doc = TextDocumentIdentifier::new(item.uri); @@ -1522,7 +1522,7 @@ pub(crate) fn handle_call_hierarchy_outgoing( snap: GlobalStateSnapshot, params: CallHierarchyOutgoingCallsParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_call_hierarchy_outgoing"); + let _p = tracing::span!(tracing::Level::INFO, "handle_call_hierarchy_outgoing").entered(); let item = params.item; let doc = TextDocumentIdentifier::new(item.uri); @@ -1557,7 +1557,7 @@ pub(crate) fn handle_semantic_tokens_full( snap: GlobalStateSnapshot, params: SemanticTokensParams, ) -> anyhow::Result> { - let _p = profile::span("handle_semantic_tokens_full"); + let _p = tracing::span!(tracing::Level::INFO, "handle_semantic_tokens_full").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let text = snap.analysis.file_text(file_id)?; @@ -1587,7 +1587,7 @@ pub(crate) fn handle_semantic_tokens_full_delta( snap: GlobalStateSnapshot, params: SemanticTokensDeltaParams, ) -> anyhow::Result> { - let _p = profile::span("handle_semantic_tokens_full_delta"); + let _p = tracing::span!(tracing::Level::INFO, "handle_semantic_tokens_full_delta").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let text = snap.analysis.file_text(file_id)?; @@ -1630,7 +1630,7 @@ pub(crate) fn handle_semantic_tokens_range( snap: GlobalStateSnapshot, params: SemanticTokensRangeParams, ) -> anyhow::Result> { - let _p = profile::span("handle_semantic_tokens_range"); + let _p = tracing::span!(tracing::Level::INFO, "handle_semantic_tokens_range").entered(); let frange = from_proto::file_range(&snap, ¶ms.text_document, params.range)?; let text = snap.analysis.file_text(frange.file_id)?; @@ -1656,7 +1656,7 @@ pub(crate) fn handle_open_docs( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { - let _p = profile::span("handle_open_docs"); + let _p = tracing::span!(tracing::Level::INFO, "handle_open_docs").entered(); let position = from_proto::file_position(&snap, params)?; let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match ws { @@ -1695,7 +1695,7 @@ pub(crate) fn handle_open_cargo_toml( snap: GlobalStateSnapshot, params: lsp_ext::OpenCargoTomlParams, ) -> anyhow::Result> { - let _p = profile::span("handle_open_cargo_toml"); + let _p = tracing::span!(tracing::Level::INFO, "handle_open_cargo_toml").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let cargo_spec = match CargoTargetSpec::for_file(&snap, file_id)? { @@ -1713,7 +1713,7 @@ pub(crate) fn handle_move_item( snap: GlobalStateSnapshot, params: lsp_ext::MoveItemParams, ) -> anyhow::Result> { - let _p = profile::span("handle_move_item"); + let _p = tracing::span!(tracing::Level::INFO, "handle_move_item").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let range = from_proto::file_range(&snap, ¶ms.text_document, params.range)?; @@ -1735,7 +1735,7 @@ pub(crate) fn handle_view_recursive_memory_layout( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { - let _p = profile::span("view_recursive_memory_layout"); + let _p = tracing::span!(tracing::Level::INFO, "view_recursive_memory_layout").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; let offset = from_proto::offset(&line_index, params.position)?; diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs index d94f7cefa60ee..acc02d6447c63 100644 --- a/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -60,7 +60,7 @@ fn integrated_highlighting_benchmark() { analysis.highlight_as_html(file_id, false).unwrap(); } - profile::init_from("*>100"); + crate::tracing::hprof::init("*>100"); { let _it = stdx::timeit("change"); @@ -152,8 +152,7 @@ fn integrated_completion_benchmark() { analysis.completions(&config, position, None).unwrap(); } - profile::init_from("*>5"); - // let _s = profile::heartbeat_span(); + crate::tracing::hprof::init("*>5"); let completion_offset = { let _it = stdx::timeit("change"); @@ -168,7 +167,7 @@ fn integrated_completion_benchmark() { }; { - let _p = profile::span("unqualified path completion"); + let _p = tracing::span!(tracing::Level::INFO, "unqualified path completion").entered(); let _span = profile::cpu_span(); let analysis = host.analysis(); let config = CompletionConfig { @@ -209,7 +208,7 @@ fn integrated_completion_benchmark() { }; { - let _p = profile::span("dot completion"); + let _p = tracing::span!(tracing::Level::INFO, "dot completion").entered(); let _span = profile::cpu_span(); let analysis = host.analysis(); let config = CompletionConfig { diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs index 29bc0b80d8a1d..b77e1dca29f0d 100644 --- a/crates/rust-analyzer/src/lib.rs +++ b/crates/rust-analyzer/src/lib.rs @@ -39,6 +39,7 @@ mod handlers { pub mod config; pub mod lsp; +pub mod tracing; use self::lsp::ext as lsp_ext; #[cfg(test)] diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 0173805d44779..3c86414d025c1 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -196,7 +196,7 @@ impl GlobalState { fn handle_event(&mut self, event: Event) -> anyhow::Result<()> { let loop_start = Instant::now(); // NOTE: don't count blocking select! call as a loop-turn time - let _p = profile::span("GlobalState::handle_event"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::handle_event").entered(); let event_dbg_msg = format!("{event:?}"); tracing::debug!("{:?} handle_event({})", loop_start, event_dbg_msg); @@ -215,7 +215,8 @@ impl GlobalState { lsp_server::Message::Response(resp) => self.complete_request(resp), }, Event::Task(task) => { - let _p = profile::span("GlobalState::handle_event/task"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::handle_event/task") + .entered(); let mut prime_caches_progress = Vec::new(); self.handle_task(&mut prime_caches_progress, task); @@ -269,7 +270,8 @@ impl GlobalState { } } Event::Vfs(message) => { - let _p = profile::span("GlobalState::handle_event/vfs"); + let _p = + tracing::span!(tracing::Level::INFO, "GlobalState::handle_event/vfs").entered(); self.handle_vfs_msg(message); // Coalesce many VFS event into a single loop turn while let Ok(message) = self.loader.receiver.try_recv() { @@ -277,7 +279,8 @@ impl GlobalState { } } Event::Flycheck(message) => { - let _p = profile::span("GlobalState::handle_event/flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::handle_event/flycheck") + .entered(); self.handle_flycheck_msg(message); // Coalesce many flycheck updates into a single loop turn while let Ok(message) = self.flycheck_receiver.try_recv() { diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 969211f44007c..65c00cc08d1a1 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -70,7 +70,8 @@ impl GlobalState { } pub(crate) fn update_configuration(&mut self, config: Config) { - let _p = profile::span("GlobalState::update_configuration"); + let _p = + tracing::span!(tracing::Level::INFO, "GlobalState::update_configuration").entered(); let old_config = mem::replace(&mut self.config, Arc::new(config)); if self.config.lru_parse_query_capacity() != old_config.lru_parse_query_capacity() { self.analysis_host.update_lru_capacity(self.config.lru_parse_query_capacity()); @@ -355,7 +356,7 @@ impl GlobalState { } pub(crate) fn switch_workspaces(&mut self, cause: Cause) { - let _p = profile::span("GlobalState::switch_workspaces"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::switch_workspaces").entered(); tracing::info!(%cause, "will switch workspaces"); let Some((workspaces, force_reload_crate_graph)) = @@ -502,7 +503,7 @@ impl GlobalState { let mut crate_graph_file_dependencies = FxHashSet::default(); let mut load = |path: &AbsPath| { - let _p = profile::span("switch_workspaces::load"); + let _p = tracing::span!(tracing::Level::INFO, "switch_workspaces::load").entered(); let vfs_path = vfs::VfsPath::from(path.to_path_buf()); crate_graph_file_dependencies.insert(vfs_path.clone()); match vfs.file_id(&vfs_path) { @@ -585,7 +586,7 @@ impl GlobalState { } fn reload_flycheck(&mut self) { - let _p = profile::span("GlobalState::reload_flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::reload_flycheck").entered(); let config = self.config.flycheck(); let sender = self.flycheck_sender.clone(); let invocation_strategy = match config { diff --git a/crates/rust-analyzer/src/tracing/hprof.rs b/crates/rust-analyzer/src/tracing/hprof.rs new file mode 100644 index 0000000000000..f37262a17aa07 --- /dev/null +++ b/crates/rust-analyzer/src/tracing/hprof.rs @@ -0,0 +1,238 @@ +//! Consumer of `tracing` data, which prints a hierarchical profile. +//! +//! Based on https://github.com/davidbarsky/tracing-tree, but does less, while +//! actually printing timings for spans by default. The code here is vendored from +//! https://github.com/matklad/tracing-span-tree. +//! +//! Usage: +//! +//! ```rust +//! let layer = hprof::SpanTree::default(); +//! Registry::default().with(layer).init(); +//! ``` +//! +//! Example output: +//! +//! ```text +//! 8.37ms top_level +//! 1.09ms middle +//! 1.06ms leaf +//! 1.06ms middle +//! 3.12ms middle +//! 1.06ms leaf +//! 3.06ms middle +//! ``` +//! +//! Same data, but with `.aggregate(true)`: +//! +//! ```text +//! 8.39ms top_level +//! 8.35ms 4 middle +//! 2.13ms 2 leaf +//! ``` + +use std::{ + fmt, mem, + time::{Duration, Instant}, +}; + +use rustc_hash::FxHashSet; +use tracing::{ + field::{Field, Visit}, + span::Attributes, + Event, Id, Level, Subscriber, +}; +use tracing_subscriber::{ + filter, + layer::{Context, SubscriberExt}, + registry::LookupSpan, + Layer, Registry, +}; + +use crate::tracing::hprof; + +pub fn init(spec: &str) { + let (write_filter, allowed_names) = WriteFilter::from_spec(spec); + + // this filter the first pass for `tracing`: these are all the "profiling" spans, but things like + // span depth or duration are not filtered here: that only occurs at write time. + let profile_filter = filter::filter_fn(move |metadata| { + let allowed = match &allowed_names { + Some(names) => names.contains(metadata.name()), + None => true, + }; + + metadata.is_span() + && allowed + && metadata.level() >= &Level::INFO + && !metadata.target().starts_with("salsa") + && !metadata.target().starts_with("chalk") + }); + + let layer = hprof::SpanTree::default() + .aggregate(true) + .spec_filter(write_filter) + .with_filter(profile_filter); + + let subscriber = Registry::default().with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); +} + +#[derive(Default, Debug)] +pub(crate) struct SpanTree { + aggregate: bool, + write_filter: WriteFilter, +} + +impl SpanTree { + /// Merge identical sibling spans together. + pub(crate) fn aggregate(self, yes: bool) -> SpanTree { + SpanTree { aggregate: yes, ..self } + } + + /// Add a write-time filter for span duration or tree depth. + pub(crate) fn spec_filter(self, write_filter: WriteFilter) -> SpanTree { + SpanTree { write_filter, ..self } + } +} + +struct Data { + start: Instant, + children: Vec, +} + +impl Data { + fn new(attrs: &Attributes<'_>) -> Self { + let mut span = Self { start: Instant::now(), children: Vec::new() }; + attrs.record(&mut span); + span + } + fn into_node(self, name: &'static str) -> Node { + Node { name, count: 1, duration: self.start.elapsed(), children: self.children } + } +} + +impl Visit for Data { + fn record_debug(&mut self, _field: &Field, _value: &dyn fmt::Debug) {} +} + +impl Layer for SpanTree +where + S: Subscriber + for<'span> LookupSpan<'span>, +{ + fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) { + let span = ctx.span(id).unwrap(); + + let data = Data::new(attrs); + span.extensions_mut().insert(data); + } + + fn on_event(&self, _event: &Event<'_>, _ctx: Context<'_, S>) {} + + fn on_close(&self, id: Id, ctx: Context<'_, S>) { + let span = ctx.span(&id).unwrap(); + let data = span.extensions_mut().remove::().unwrap(); + let mut node = data.into_node(span.name()); + + match span.parent() { + Some(parent_span) => { + parent_span.extensions_mut().get_mut::().unwrap().children.push(node); + } + None => { + if self.aggregate { + node.aggregate() + } + node.print(&self.write_filter) + } + } + } +} + +#[derive(Default)] +struct Node { + name: &'static str, + count: u32, + duration: Duration, + children: Vec, +} + +impl Node { + fn print(&self, filter: &WriteFilter) { + self.go(0, filter) + } + + fn go(&self, level: usize, filter: &WriteFilter) { + if self.duration > filter.longer_than && level < filter.depth { + let duration = format!("{:3.2?}", self.duration); + let count = if self.count > 1 { self.count.to_string() } else { String::new() }; + eprintln!( + "{:width$} {:<9} {:<6} {}", + "", + duration, + count, + self.name, + width = level * 2 + ); + for child in &self.children { + child.go(level + 1, filter) + } + } + } + + fn aggregate(&mut self) { + if self.children.is_empty() { + return; + } + + self.children.sort_by_key(|it| it.name); + let mut idx = 0; + for i in 1..self.children.len() { + if self.children[idx].name == self.children[i].name { + let child = mem::take(&mut self.children[i]); + self.children[idx].duration += child.duration; + self.children[idx].count += child.count; + self.children[idx].children.extend(child.children); + } else { + idx += 1; + assert!(idx <= i); + self.children.swap(idx, i); + } + } + self.children.truncate(idx + 1); + for child in &mut self.children { + child.aggregate() + } + } +} + +#[derive(Default, Clone, Debug)] +pub(crate) struct WriteFilter { + depth: usize, + longer_than: Duration, +} + +impl WriteFilter { + pub(crate) fn from_spec(mut spec: &str) -> (WriteFilter, Option>) { + let longer_than = if let Some(idx) = spec.rfind('>') { + let longer_than = spec[idx + 1..].parse().expect("invalid profile longer_than"); + spec = &spec[..idx]; + Duration::from_millis(longer_than) + } else { + Duration::new(0, 0) + }; + + let depth = if let Some(idx) = spec.rfind('@') { + let depth: usize = spec[idx + 1..].parse().expect("invalid profile depth"); + spec = &spec[..idx]; + depth + } else { + 999 + }; + let allowed = if spec == "*" { + None + } else { + Some(FxHashSet::from_iter(spec.split('|').map(String::from))) + }; + (WriteFilter { depth, longer_than }, allowed) + } +} diff --git a/crates/rust-analyzer/src/tracing/mod.rs b/crates/rust-analyzer/src/tracing/mod.rs new file mode 100644 index 0000000000000..0e681c37094b9 --- /dev/null +++ b/crates/rust-analyzer/src/tracing/mod.rs @@ -0,0 +1,108 @@ +//! Simple logger that logs either to stderr or to a file, using `tracing_subscriber` +//! filter syntax and `tracing_appender` for non blocking output. + +use std::io; + +use anyhow::Context; +use tracing::{level_filters::LevelFilter, Level}; +use tracing_subscriber::{ + filter::{self, Targets}, + fmt::{format::FmtSpan, MakeWriter}, + layer::SubscriberExt, + util::SubscriberInitExt, + Layer, Registry, +}; +use tracing_tree::HierarchicalLayer; + +pub mod hprof; + +pub struct Config { + pub writer: T, + pub filter: String, + /// The meaning of CHALK_DEBUG is to tell chalk crates + /// (i.e. chalk-solve, chalk-ir, chalk-recursive) how to filter tracing + /// logs. But now we can only have just one filter, which means we have to + /// merge chalk filter to our main filter (from RA_LOG env). + /// + /// The acceptable syntax of CHALK_DEBUG is `target[span{field=value}]=level`. + /// As the value should only affect chalk crates, we'd better manually + /// specify the target. And for simplicity, CHALK_DEBUG only accept the value + /// that specify level. + pub chalk_filter: Option, + /// Filtering syntax, set in a shell: + /// ``` + /// env RA_PROFILE=* // dump everything + /// env RA_PROFILE=foo|bar|baz // enabled only selected entries + /// env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 + /// ``` + pub profile_filter: Option, +} + +impl Config +where + T: for<'writer> MakeWriter<'writer> + Send + Sync + 'static, +{ + pub fn init(self) -> anyhow::Result<()> { + let filter: Targets = self + .filter + .parse() + .with_context(|| format!("invalid log filter: `{}`", self.filter))?; + + let writer = self.writer; + + let ra_fmt_layer = tracing_subscriber::fmt::layer() + .with_span_events(FmtSpan::CLOSE) + .with_writer(writer) + .with_filter(filter); + + let mut chalk_layer = None; + if let Some(chalk_filter) = self.chalk_filter { + let level: LevelFilter = + chalk_filter.parse().with_context(|| "invalid chalk log filter")?; + + let chalk_filter = Targets::new() + .with_target("chalk_solve", level) + .with_target("chalk_ir", level) + .with_target("chalk_recursive", level); + chalk_layer = Some( + HierarchicalLayer::default() + .with_indent_lines(true) + .with_ansi(false) + .with_indent_amount(2) + .with_writer(io::stderr) + .with_filter(chalk_filter), + ); + }; + + let mut profiler_layer = None; + if let Some(spec) = self.profile_filter { + let (write_filter, allowed_names) = hprof::WriteFilter::from_spec(&spec); + + // this filter the first pass for `tracing`: these are all the "profiling" spans, but things like + // span depth or duration are not filtered here: that only occurs at write time. + let profile_filter = filter::filter_fn(move |metadata| { + let allowed = match &allowed_names { + Some(names) => names.contains(metadata.name()), + None => true, + }; + + metadata.is_span() + && allowed + && metadata.level() >= &Level::INFO + && !metadata.target().starts_with("salsa") + && !metadata.target().starts_with("chalk") + }); + + let layer = hprof::SpanTree::default() + .aggregate(true) + .spec_filter(write_filter) + .with_filter(profile_filter); + + profiler_layer = Some(layer); + } + + Registry::default().with(ra_fmt_layer).with(chalk_layer).with(profiler_layer).try_init()?; + + Ok(()) + } +} diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs index 58a99cc4471a9..f7f654b890e95 100644 --- a/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/crates/rust-analyzer/tests/slow-tests/main.rs @@ -38,9 +38,6 @@ use crate::{ testdir::TestDir, }; -const PROFILE: &str = ""; -// const PROFILE: &'static str = "*@3>100"; - #[test] fn completes_items_from_standard_library() { if skip_slow_tests() { diff --git a/crates/rust-analyzer/tests/slow-tests/support.rs b/crates/rust-analyzer/tests/slow-tests/support.rs index e16990eabd092..d699374f9cde6 100644 --- a/crates/rust-analyzer/tests/slow-tests/support.rs +++ b/crates/rust-analyzer/tests/slow-tests/support.rs @@ -9,11 +9,11 @@ use std::{ use crossbeam_channel::{after, select, Receiver}; use lsp_server::{Connection, Message, Notification, Request}; use lsp_types::{notification::Exit, request::Shutdown, TextDocumentIdentifier, Url}; -use rust_analyzer::{config::Config, lsp, main_loop}; +use rust_analyzer::{config::Config, lsp, main_loop, tracing}; use serde::Serialize; use serde_json::{json, to_string_pretty, Value}; use test_utils::FixtureWithProjectMeta; -use tracing_subscriber::{prelude::*, Layer}; +use tracing_subscriber::fmt::TestWriter; use vfs::AbsPathBuf; use crate::testdir::TestDir; @@ -91,12 +91,14 @@ impl Project<'_> { static INIT: Once = Once::new(); INIT.call_once(|| { - let filter: tracing_subscriber::filter::Targets = - std::env::var("RA_LOG").ok().and_then(|it| it.parse().ok()).unwrap_or_default(); - let layer = - tracing_subscriber::fmt::Layer::new().with_test_writer().with_filter(filter); - tracing_subscriber::Registry::default().with(layer).init(); - profile::init_from(crate::PROFILE); + let _ = tracing::Config { + writer: TestWriter::default(), + // Deliberately enable all `error` logs if the user has not set RA_LOG, as there is usually + // useful information in there for debugging. + filter: std::env::var("RA_LOG").ok().unwrap_or_else(|| "error".to_string()), + chalk_filter: std::env::var("CHALK_DEBUG").ok(), + profile_filter: std::env::var("RA_PROFILE").ok(), + }; }); let FixtureWithProjectMeta { fixture, mini_core, proc_macro_names, toolchain } = diff --git a/crates/stdx/Cargo.toml b/crates/stdx/Cargo.toml index e6014cf812e56..2e3f9113b066a 100644 --- a/crates/stdx/Cargo.toml +++ b/crates/stdx/Cargo.toml @@ -13,7 +13,7 @@ doctest = false [dependencies] backtrace = { version = "0.3.67", optional = true } -always-assert = { version = "0.1.2", features = ["log"] } +always-assert = { version = "0.2.0", features = ["tracing"] } jod-thread = "0.1.2" libc.workspace = true crossbeam-channel = "0.5.5" diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index 9f78614bba66b..a0fd73ee13f57 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml @@ -22,6 +22,7 @@ once_cell = "1.17.0" indexmap.workspace = true smol_str.workspace = true triomphe.workspace = true +tracing.workspace = true ra-ap-rustc_lexer.workspace = true diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs index c4548b1647472..01f2af419ed89 100644 --- a/crates/syntax/src/algo.rs +++ b/crates/syntax/src/algo.rs @@ -120,7 +120,7 @@ pub struct TreeDiff { impl TreeDiff { pub fn into_text_edit(&self, builder: &mut TextEditBuilder) { - let _p = profile::span("into_text_edit"); + let _p = tracing::span!(tracing::Level::INFO, "into_text_edit").entered(); for (anchor, to) in &self.insertions { let offset = match anchor { @@ -149,7 +149,7 @@ impl TreeDiff { /// /// This function tries to find a fine-grained diff. pub fn diff(from: &SyntaxNode, to: &SyntaxNode) -> TreeDiff { - let _p = profile::span("diff"); + let _p = tracing::span!(tracing::Level::INFO, "diff").entered(); let mut diff = TreeDiff { replacements: FxHashMap::default(), diff --git a/crates/test-utils/Cargo.toml b/crates/test-utils/Cargo.toml index 56067d8341789..2ff1fad6c29d9 100644 --- a/crates/test-utils/Cargo.toml +++ b/crates/test-utils/Cargo.toml @@ -15,10 +15,11 @@ doctest = false # 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 stdx.workspace = true profile.workspace = true [lints] -workspace = true \ No newline at end of file +workspace = true From 17d2e8d9101b547e6cc3b19d278b2f925e2d972f Mon Sep 17 00:00:00 2001 From: David Barsky Date: Tue, 30 Jan 2024 13:37:27 -0500 Subject: [PATCH 134/246] internal: remove `tracing/mod.rs` --- crates/rust-analyzer/src/lib.rs | 7 ++++++- crates/rust-analyzer/src/tracing/{mod.rs => config.rs} | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) rename crates/rust-analyzer/src/tracing/{mod.rs => config.rs} (99%) diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs index b77e1dca29f0d..c22834ee10020 100644 --- a/crates/rust-analyzer/src/lib.rs +++ b/crates/rust-analyzer/src/lib.rs @@ -37,9 +37,14 @@ mod handlers { pub(crate) mod request; } +pub mod tracing { + pub mod config; + pub use config::Config; + pub mod hprof; +} + pub mod config; pub mod lsp; -pub mod tracing; use self::lsp::ext as lsp_ext; #[cfg(test)] diff --git a/crates/rust-analyzer/src/tracing/mod.rs b/crates/rust-analyzer/src/tracing/config.rs similarity index 99% rename from crates/rust-analyzer/src/tracing/mod.rs rename to crates/rust-analyzer/src/tracing/config.rs index 0e681c37094b9..fcdbd1e6d9b56 100644 --- a/crates/rust-analyzer/src/tracing/mod.rs +++ b/crates/rust-analyzer/src/tracing/config.rs @@ -14,7 +14,7 @@ use tracing_subscriber::{ }; use tracing_tree::HierarchicalLayer; -pub mod hprof; +use crate::tracing::hprof; pub struct Config { pub writer: T, From 8f1a253a4c42c206d33883ae9826f4c505425a67 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 30 Jan 2024 19:46:00 +0100 Subject: [PATCH 135/246] internal: Undo special bracket classification for attributes in vscode config --- editors/code/language-configuration.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/editors/code/language-configuration.json b/editors/code/language-configuration.json index a2af8b51a908b..1c348b63f1a23 100644 --- a/editors/code/language-configuration.json +++ b/editors/code/language-configuration.json @@ -6,9 +6,7 @@ "brackets": [ ["{", "}"], ["[", "]"], - ["(", ")"], - ["#[", "]"], - ["#![", "]"] + ["(", ")"] ], "colorizedBracketPairs": [ ["{", "}"], @@ -19,8 +17,6 @@ { "open": "{", "close": "}" }, { "open": "[", "close": "]" }, { "open": "(", "close": ")" }, - { "open": "#[", "close": "]" }, - { "open": "#![", "close": "]" }, { "open": "\"", "close": "\"", "notIn": ["string"] }, { "open": "/*", "close": " */" }, { "open": "`", "close": "`", "notIn": ["string"] } From a97ff2a750edf9ba4a9cdfd72f419f6836fe6b2d Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Tue, 30 Jan 2024 14:37:59 -0500 Subject: [PATCH 136/246] Add additional test cases for is_val_statically_known --- tests/codegen/is_val_statically_known.rs | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/codegen/is_val_statically_known.rs b/tests/codegen/is_val_statically_known.rs index 44187d4f667dd..8f084f6c54bdc 100644 --- a/tests/codegen/is_val_statically_known.rs +++ b/tests/codegen/is_val_statically_known.rs @@ -46,3 +46,41 @@ pub fn _bool_false(b: bool) -> i32 { // CHECK: ret i32 2 _bool(b) } + +#[inline] +pub fn _iref(a: &u8) -> i32 { + if unsafe { is_val_statically_known(a) } { 5 } else { 4 } +} + +// CHECK-LABEL: @_iref_borrow( +#[no_mangle] +pub fn _iref_borrow() -> i32 { + // CHECK: ret i32 4 + _iref(&0) +} + +// CHECK-LABEL: @_iref_arg( +#[no_mangle] +pub fn _iref_arg(a: &u8) -> i32 { + // CHECK: ret i32 4 + _iref(a) +} + +#[inline] +pub fn _slice_ref(a: &[u8]) -> i32 { + if unsafe { is_val_statically_known(a) } { 7 } else { 6 } +} + +// CHECK-LABEL: @_slice_ref_borrow( +#[no_mangle] +pub fn _slice_ref_borrow() -> i32 { + // CHECK: ret i32 6 + _slice_ref(&[0;3]) +} + +// CHECK-LABEL: @_slice_ref_arg( +#[no_mangle] +pub fn _slice_ref_arg(a: &[u8]) -> i32 { + // CHECK: ret i32 6 + _slice_ref(a) +} From 4225a1e186afe39c1ae81c5065d24287d6d49fb9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jan 2024 16:57:29 +1100 Subject: [PATCH 137/246] Don't hash lints differently to non-lints. `Diagnostic::keys`, which is used for hashing and equating diagnostics, has a surprising behaviour: it ignores children, but only for lints. This was added in #88493 to fix some duplicated diagnostics, but it doesn't seem necessary any more. This commit removes the special case and only four tests have changed output, with additional errors. And those additional errors aren't exact duplicates, they're just similar. For example, in src/tools/clippy/tests/ui/same_name_method.rs we currently have this error: ``` error: method's name is the same as an existing method in a trait --> $DIR/same_name_method.rs:75:13 | LL | fn foo() {} | ^^^^^^^^^^^ | note: existing `foo` defined here --> $DIR/same_name_method.rs:79:9 | LL | impl T1 for S {} | ^^^^^^^^^^^^^^^^ ``` and with this change we also get this error: ``` error: method's name is the same as an existing method in a trait --> $DIR/same_name_method.rs:75:13 | LL | fn foo() {} | ^^^^^^^^^^^ | note: existing `foo` defined here --> $DIR/same_name_method.rs:81:9 | LL | impl T2 for S {} | ^^^^^^^^^^^^^^^^ ``` I think printing this second argument is reasonable, possibly even preferable to hiding it. And the other cases are similar. --- compiler/rustc_errors/src/diagnostic.rs | 16 ++++++++-------- src/tools/clippy/tests/ui/same_name_method.rs | 1 + .../clippy/tests/ui/same_name_method.stderr | 16 ++++++++++++++-- tests/rustdoc-ui/unescaped_backticks.stderr | 3 --- .../stable-metric/ctfe-simple-loop.warn.stderr | 1 - tests/ui/imports/ambiguous-9.stderr | 1 - 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index bf1ab37a1cf48..b87eef07fd53a 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -109,8 +109,6 @@ pub struct Diagnostic { /// `span` if there is one. Otherwise, it is `DUMMY_SP`. pub sort_span: Span, - /// If diagnostic is from Lint, custom hash function ignores children. - /// Otherwise hash is based on the all the fields. pub is_lint: Option, /// With `-Ztrack_diagnostics` enabled, @@ -980,22 +978,24 @@ impl Diagnostic { ) -> ( &Level, &[(DiagnosticMessage, Style)], - Vec<(&Cow<'static, str>, &DiagnosticArgValue)>, &Option, - &Option, &MultiSpan, + &[SubDiagnostic], &Result, SuggestionsDisabled>, - Option<&[SubDiagnostic]>, + Vec<(&DiagnosticArgName, &DiagnosticArgValue)>, + &Option, ) { ( &self.level, &self.messages, - self.args().collect(), &self.code, - &self.is_lint, &self.span, + &self.children, &self.suggestions, - (if self.is_lint.is_some() { None } else { Some(&self.children) }), + self.args().collect(), + // omit self.sort_span + &self.is_lint, + // omit self.emitted_at ) } } diff --git a/src/tools/clippy/tests/ui/same_name_method.rs b/src/tools/clippy/tests/ui/same_name_method.rs index 1c166a19b0ad7..26b1a299ba1cf 100644 --- a/src/tools/clippy/tests/ui/same_name_method.rs +++ b/src/tools/clippy/tests/ui/same_name_method.rs @@ -74,6 +74,7 @@ mod should_lint { impl S { fn foo() {} //~^ ERROR: method's name is the same as an existing method in a trait + //~| ERROR: method's name is the same as an existing method in a trait } impl T1 for S {} diff --git a/src/tools/clippy/tests/ui/same_name_method.stderr b/src/tools/clippy/tests/ui/same_name_method.stderr index 3c5c4a53ad1f6..82f5ef6a9e827 100644 --- a/src/tools/clippy/tests/ui/same_name_method.stderr +++ b/src/tools/clippy/tests/ui/same_name_method.stderr @@ -56,10 +56,22 @@ LL | fn foo() {} | ^^^^^^^^^^^ | note: existing `foo` defined here - --> $DIR/same_name_method.rs:79:9 + --> $DIR/same_name_method.rs:80:9 | LL | impl T1 for S {} | ^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: method's name is the same as an existing method in a trait + --> $DIR/same_name_method.rs:75:13 + | +LL | fn foo() {} + | ^^^^^^^^^^^ + | +note: existing `foo` defined here + --> $DIR/same_name_method.rs:82:9 + | +LL | impl T2 for S {} + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr index bd21dcb6e1af9..000a5b597d299 100644 --- a/tests/rustdoc-ui/unescaped_backticks.stderr +++ b/tests/rustdoc-ui/unescaped_backticks.stderr @@ -302,7 +302,6 @@ LL | | /// level changes. = help: if you meant to use a literal backtick, escape it change: or `None` if it isn't. to this: or `None\` if it isn't. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unescaped backtick --> $DIR/unescaped_backticks.rs:323:5 @@ -322,7 +321,6 @@ LL | | /// level changes. = help: if you meant to use a literal backtick, escape it change: `on_event` should be called. to this: `on_event\` should be called. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unescaped backtick --> $DIR/unescaped_backticks.rs:323:5 @@ -342,7 +340,6 @@ LL | | /// level changes. = help: if you meant to use a literal backtick, escape it change: [`rebuild_interest_cache`][rebuild] is called after the value of the max to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unescaped backtick --> $DIR/unescaped_backticks.rs:349:56 diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr index 8eee392d15cd5..40fc4a876e9e5 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr @@ -40,7 +40,6 @@ help: the constant being evaluated | LL | const Y: u32 = simple_loop(35); | ^^^^^^^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: constant evaluation is taking a long time --> $DIR/ctfe-simple-loop.rs:9:5 diff --git a/tests/ui/imports/ambiguous-9.stderr b/tests/ui/imports/ambiguous-9.stderr index 2731ed2ba86d3..6c7d79174daf6 100644 --- a/tests/ui/imports/ambiguous-9.stderr +++ b/tests/ui/imports/ambiguous-9.stderr @@ -60,7 +60,6 @@ note: `date_range` could also refer to the function imported here LL | use prelude::*; | ^^^^^^^^^^ = help: consider adding an explicit import of `date_range` to disambiguate - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 4 warnings emitted From 6efddac288643c4b0bc85ea317ea275e6cb4739f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 29 Jan 2024 18:31:02 +0000 Subject: [PATCH 138/246] Provide more context on derived obligation error primary label Expand the primary span of E0277 when the immediate unmet bound is not what the user wrote: ``` error[E0277]: the trait bound `i32: Bar` is not satisfied --> f100.rs:6:6 | 6 | ::foo(); | ^^^ the trait `Bar` is not implemented for `i32`, which is required by `i32: Foo` | help: this trait has no implementations, consider adding one --> f100.rs:2:1 | 2 | trait Bar {} | ^^^^^^^^^ note: required for `i32` to implement `Foo` --> f100.rs:3:14 | 3 | impl Foo for T {} | --- ^^^ ^ | | | unsatisfied trait bound introduced here ``` Fix #40120. --- .../src/traits/error_reporting/suggestions.rs | 41 +++++++++++-------- tests/ui/associated-consts/issue-58022.stderr | 2 +- .../return-type-notation/basic.without.stderr | 2 +- .../defaults-suitability.stderr | 6 +-- .../hr-associated-type-bound-1.stderr | 2 +- .../hr-associated-type-bound-param-1.stderr | 2 +- .../hr-associated-type-bound-param-2.stderr | 2 +- .../hr-associated-type-bound-param-3.stderr | 2 +- .../hr-associated-type-bound-param-4.stderr | 2 +- .../hr-associated-type-bound-param-5.stderr | 4 +- tests/ui/associated-types/issue-38821.stderr | 32 +++++++-------- .../issue-43784-associated-type.stderr | 2 +- .../ui/associated-types/issue-65774-1.stderr | 2 +- .../substs-ppaux.normal.stderr | 2 +- .../substs-ppaux.verbose.stderr | 2 +- .../async-await/async-await-let-else.stderr | 8 ++-- tests/ui/async-await/async-fn-nonsend.stderr | 4 +- .../ui/async-await/async-is-unwindsafe.stderr | 2 +- ...-ice-attempted-to-add-with-overflow.stderr | 2 +- .../drop-track-bad-field-in-fru.stderr | 2 +- .../drop-track-field-assign-nonsend.stderr | 2 +- .../async-await/field-assign-nonsend.stderr | 2 +- .../in-trait/missing-send-bound.stderr | 2 +- tests/ui/async-await/issue-101715.stderr | 2 +- .../ui/async-await/issue-64130-1-sync.stderr | 2 +- .../ui/async-await/issue-64130-2-send.stderr | 2 +- .../ui/async-await/issue-64130-3-other.stderr | 2 +- .../issue-64130-non-send-future-diags.stderr | 2 +- .../issue-67252-unnamed-future.stderr | 2 +- tests/ui/async-await/issue-68112.stderr | 6 +-- .../issue-70935-complex-spans.stderr | 2 +- tests/ui/async-await/issue-71137.stderr | 2 +- .../issue-72590-type-error-sized.stderr | 2 +- .../ui/async-await/issues/issue-67893.stderr | 2 +- .../partial-drop-partial-reinit.stderr | 2 +- .../async-await/pin-needed-to-poll-2.stderr | 2 +- tests/ui/async-await/unnecessary-await.stderr | 8 ++-- tests/ui/auto-traits/issue-83857-ub.stderr | 2 +- .../str-contains-slice-conceptually.stderr | 2 +- ...ault-trait-impl-constituent-types-2.stderr | 2 +- ...ypeck-default-trait-impl-precedence.stderr | 2 +- tests/ui/binop/binary-op-suggest-deref.stderr | 16 ++++---- tests/ui/block-result/issue-22645.stderr | 2 +- tests/ui/closures/closure-move-sync.stderr | 2 +- .../closure-return-type-must-be-sized.stderr | 18 ++++---- .../const_param_ty_bad_empty_array.stderr | 2 +- ...param_ty_generic_bounds_do_not_hold.stderr | 6 +-- .../generic_const_exprs/issue-85848.stderr | 2 +- .../issues/issue-67185-2.stderr | 4 +- .../const-blocks/fn-call-in-non-const.stderr | 2 +- .../consts/const-blocks/migrate-fail.stderr | 4 +- tests/ui/consts/const-blocks/nll-fail.stderr | 4 +- .../ui/consts/const-blocks/trait-error.stderr | 2 +- tests/ui/consts/const-fn-in-vec.stderr | 4 +- tests/ui/coroutine/clone-impl.stderr | 12 +++--- .../drop-tracking-parent-expression.stderr | 6 +-- tests/ui/coroutine/drop-yield-twice.stderr | 2 +- tests/ui/coroutine/issue-105084.stderr | 2 +- tests/ui/coroutine/issue-68112.stderr | 4 +- tests/ui/coroutine/not-send-sync.stderr | 4 +- tests/ui/coroutine/parent-expression.stderr | 6 +-- .../print/coroutine-print-verbose-1.stderr | 4 +- .../print/coroutine-print-verbose-2.stderr | 4 +- tests/ui/coroutine/ref-upvar-not-send.stderr | 4 +- tests/ui/coroutine/unresolved-ct-var.stderr | 2 +- ...yield-outside-coroutine-issue-78653.stderr | 2 +- ...ives-span-Debug-enum-struct-variant.stderr | 2 +- .../ui/derives/derives-span-Debug-enum.stderr | 2 +- .../derives/derives-span-Debug-struct.stderr | 2 +- .../derives-span-Debug-tuple-struct.stderr | 2 +- tests/ui/deriving/issue-103157.stderr | 2 +- tests/ui/dst/dst-bad-deep-2.stderr | 2 +- tests/ui/dst/dst-bad-deep.stderr | 2 +- tests/ui/error-codes/E0277-2.stderr | 2 +- tests/ui/error-codes/E0277.stderr | 2 +- .../blame-trait-error.stderr | 28 ++++++------- .../blame-trait-error-spans-on-exprs.stderr | 28 ++++++------- tests/ui/extern/extern-types-unsized.stderr | 6 +-- .../feature-gate-trivial_bounds.stderr | 2 +- tests/ui/fmt/ifmt-unimpl.stderr | 2 +- tests/ui/fmt/send-sync.stderr | 4 +- tests/ui/for/for-c-in-str.stderr | 2 +- tests/ui/for/for-loop-bogosity.stderr | 2 +- tests/ui/function-pointer/unsized-ret.stderr | 4 +- ...-gat-normalization-for-nested-goals.stderr | 2 +- .../impl_bounds.stderr | 4 +- .../issue-101020.stderr | 2 +- .../issue-74824.stderr | 2 +- .../normalize-under-binder/issue-89118.stderr | 6 +-- tests/ui/impl-trait/auto-trait-leak2.stderr | 4 +- ...n-trait-return-should-be-impl-trait.stderr | 4 +- .../impl-trait/impl_trait_projections.stderr | 4 +- tests/ui/impl-trait/issue-55872-1.stderr | 4 +- tests/ui/impl-trait/nested_impl_trait.stderr | 4 +- tests/ui/indexing/index-help.stderr | 2 +- .../indexing/indexing-requires-a-uint.stderr | 2 +- ...int-at-index-for-obligation-failure.stderr | 2 +- tests/ui/integral-indexing.stderr | 16 ++++---- .../interior-mutability.stderr | 2 +- tests/ui/issues/issue-21763.stderr | 2 +- tests/ui/issues/issue-22872.stderr | 2 +- tests/ui/issues/issue-40827.stderr | 4 +- tests/ui/issues/issue-7364.stderr | 2 +- tests/ui/iterators/float_iterator_hint.stderr | 2 +- tests/ui/iterators/integral.stderr | 24 +++++------ tests/ui/iterators/issue-28098.stderr | 4 +- tests/ui/iterators/ranges.stderr | 4 +- tests/ui/iterators/string.stderr | 4 +- .../kindck/kindck-impl-type-params-2.stderr | 2 +- .../ui/kindck/kindck-impl-type-params.stderr | 8 ++-- .../kindck-inherited-copy-bound.curr.stderr | 2 +- ...copy-bound.object_safe_for_dispatch.stderr | 2 +- tests/ui/kindck/kindck-nonsendable-1.stderr | 2 +- tests/ui/kindck/kindck-send-object.stderr | 4 +- tests/ui/kindck/kindck-send-object1.stderr | 4 +- tests/ui/kindck/kindck-send-object2.stderr | 4 +- tests/ui/kindck/kindck-send-owned.stderr | 2 +- tests/ui/modules/issue-107649.stderr | 2 +- tests/ui/mut/mutable-enum-indirect.stderr | 2 +- tests/ui/no-send-res-ports.stderr | 2 +- tests/ui/no_send-enum.stderr | 2 +- tests/ui/no_share-enum.stderr | 2 +- tests/ui/not-clone-closure.stderr | 2 +- tests/ui/not-panic/not-panic-safe-2.stderr | 4 +- tests/ui/not-panic/not-panic-safe-3.stderr | 4 +- tests/ui/not-panic/not-panic-safe-4.stderr | 4 +- tests/ui/not-panic/not-panic-safe-5.stderr | 2 +- tests/ui/not-panic/not-panic-safe-6.stderr | 4 +- tests/ui/offset-of/offset-of-dst-field.stderr | 2 +- tests/ui/on-unimplemented/slice-index.stderr | 4 +- tests/ui/parser/struct-literal-in-for.stderr | 2 +- tests/ui/range/range-1.stderr | 2 +- .../recursion/recursive-requirements.stderr | 4 +- .../termination-trait-test-wrong-type.stderr | 2 +- .../dbg-macro-requires-debug.stderr | 2 +- .../feature-gate-do_not_recommend.stderr | 2 +- .../min_specialization/issue-79224.stderr | 6 +-- tests/ui/str/str-idx.stderr | 4 +- tests/ui/str/str-mut-idx.stderr | 4 +- .../ui/suggestions/derive-clone-for-eq.stderr | 2 +- .../derive-macro-missing-bounds.stderr | 10 ++--- tests/ui/suggestions/into-str.stderr | 2 +- .../issue-71394-no-from-impl.stderr | 2 +- tests/ui/suggestions/issue-88696.stderr | 2 +- tests/ui/suggestions/issue-96223.stderr | 2 +- tests/ui/suggestions/issue-96555.stderr | 6 +-- tests/ui/suggestions/path-by-value.stderr | 2 +- tests/ui/suggestions/path-display.stderr | 2 +- .../suggest-dereferencing-index.stderr | 2 +- tests/ui/suggestions/suggest-pin-macro.stderr | 2 +- .../suggestions/suggest-remove-refs-1.stderr | 2 +- .../suggestions/suggest-remove-refs-2.stderr | 2 +- .../suggestions/suggest-remove-refs-3.stderr | 2 +- .../suggestions/suggest-remove-refs-4.stderr | 2 +- .../suggestions/suggest-remove-refs-5.stderr | 4 +- tests/ui/sync/mutexguard-sync.stderr | 2 +- tests/ui/traits/alias/cross-crate.stderr | 4 +- ...ssue-108072-unmet-trait-alias-bound.stderr | 2 +- .../assoc-fn-bound-root-obligation.stderr | 2 +- .../traits/copy-impl-cannot-normalize.stderr | 2 +- ...dont-autoderef-ty-with-escaping-var.stderr | 2 +- .../supertrait-auto-trait.stderr | 2 +- tests/ui/traits/issue-43784-supertrait.stderr | 2 +- tests/ui/traits/issue-7013.stderr | 2 +- tests/ui/traits/issue-71036.stderr | 2 +- tests/ui/traits/issue-71136.stderr | 2 +- tests/ui/traits/issue-91594.stderr | 2 +- tests/ui/traits/issue-97576.stderr | 2 +- .../negated-auto-traits-error.stderr | 6 +-- .../bad-sized-cond.stderr | 4 +- .../question-mark-result-err-mismatch.stderr | 6 +-- .../dont-suggest-unsize-deref.stderr | 2 +- .../suggest-dereferences/issue-39029.stderr | 2 +- .../root-obligation.stderr | 2 +- ...est-dereferencing-receiver-argument.stderr | 2 +- tests/ui/traits/unsend-future.stderr | 2 +- tests/ui/try-block/try-block-bad-type.stderr | 2 +- tests/ui/try-trait/bad-interconversion.stderr | 2 +- tests/ui/try-trait/issue-32709.stderr | 2 +- .../auto-trait-leakage2.stderr | 2 +- .../issue-90400-2.stderr | 2 +- .../multiple-def-uses-in-one-fn.stderr | 2 +- .../underconstrained_generic.stderr | 2 +- tests/ui/type/issue-58355.stderr | 2 +- .../ui/typeck/bad-index-due-to-nested.stderr | 4 +- tests/ui/typeck/issue-90101.stderr | 2 +- ...ck-default-trait-impl-negation-sync.stderr | 4 +- .../typeck/typeck-unsafe-always-share.stderr | 2 +- .../projection-as-union-type-error-2.stderr | 2 +- .../issue-50940-with-feature.stderr | 2 +- tests/ui/unsized-locals/rust-call.stderr | 2 +- tests/ui/unsized-locals/unsized-exprs.stderr | 6 +-- tests/ui/unsized/unsized-enum2.stderr | 8 ++-- tests/ui/wf/hir-wf-check-erase-regions.stderr | 6 +-- tests/ui/wf/wf-const-type.stderr | 4 +- tests/ui/wf/wf-static-type.stderr | 4 +- 196 files changed, 382 insertions(+), 373 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 69649e3617832..5bab57ca56cb4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1432,20 +1432,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> bool { let span = obligation.cause.span; - let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = - obligation.cause.code() - { - parent_code - } else if let ObligationCauseCode::ItemObligation(_) - | ObligationCauseCode::ExprItemObligation(..) = obligation.cause.code() - { - obligation.cause.code() - } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) = - span.ctxt().outer_expn_data().kind - { - obligation.cause.code() - } else { - return false; + let code = match obligation.cause.code() { + ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => parent_code, + c @ ObligationCauseCode::ItemObligation(_) + | c @ ObligationCauseCode::ExprItemObligation(..) => c, + c if matches!( + span.ctxt().outer_expn_data().kind, + ExpnKind::Desugaring(DesugaringKind::ForLoop) + ) => + { + c + } + _ => return false, }; // List of traits for which it would be nonsensical to suggest borrowing. @@ -4978,16 +4976,27 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>( _ => None, }; + let pred = obligation.predicate; + let (_, base) = obligation.cause.code().peel_derives_with_predicate(); + let post = if let ty::PredicateKind::Clause(clause) = pred.kind().skip_binder() + && let ty::ClauseKind::Trait(pred) = clause + && let Some(base) = base + && base.skip_binder() != pred + { + format!(", which is required by `{base}`") + } else { + String::new() + }; match ty_desc { Some(desc) => format!( - "{}the trait `{}` is not implemented for {} `{}`", + "{}the trait `{}` is not implemented for {} `{}`{post}", pre_message, trait_predicate.print_modifiers_and_trait_path(), desc, tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None), ), None => format!( - "{}the trait `{}` is not implemented for `{}`", + "{}the trait `{}` is not implemented for `{}`{post}", pre_message, trait_predicate.print_modifiers_and_trait_path(), tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None), diff --git a/tests/ui/associated-consts/issue-58022.stderr b/tests/ui/associated-consts/issue-58022.stderr index 82cbc9ed3b094..6ce995eaab716 100644 --- a/tests/ui/associated-consts/issue-58022.stderr +++ b/tests/ui/associated-consts/issue-58022.stderr @@ -13,7 +13,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | fn new(slice: &[u8; Self::SIZE]) -> Self { | ^^^^ doesn't have a size known at compile-time | - = help: within `Bar<[u8]>`, the trait `Sized` is not implemented for `[u8]` + = help: within `Bar<[u8]>`, the trait `Sized` is not implemented for `[u8]`, which is required by `Bar<[u8]>: Sized` note: required because it appears within the type `Bar<[u8]>` --> $DIR/issue-58022.rs:8:12 | diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr index f576cc9c95f09..dde7036231e21 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr @@ -13,7 +13,7 @@ error: future cannot be sent between threads safely LL | is_send(foo::()); | ^^^^^^^^^^ future returned by `foo` is not `Send` | - = help: within `impl Future>`, the trait `Send` is not implemented for `impl Future> { ::method() }` + = help: within `impl Future>`, the trait `Send` is not implemented for `impl Future> { ::method() }`, which is required by `impl Future>: Send` note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/basic.rs:13:5 | diff --git a/tests/ui/associated-types/defaults-suitability.stderr b/tests/ui/associated-types/defaults-suitability.stderr index 0a8ad0f89e212..82b35a4863788 100644 --- a/tests/ui/associated-types/defaults-suitability.stderr +++ b/tests/ui/associated-types/defaults-suitability.stderr @@ -39,7 +39,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied --> $DIR/defaults-suitability.rs:28:23 | LL | type Bar: Clone = Vec; - | ^^^^^^ the trait `Clone` is not implemented for `T` + | ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `Vec: Clone` | = note: required for `Vec` to implement `Clone` note: required by a bound in `Foo::Bar` @@ -88,7 +88,7 @@ error[E0277]: the trait bound `>::Baz: Clone` is not satisfied --> $DIR/defaults-suitability.rs:65:23 | LL | type Bar: Clone = Vec; - | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz` + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz`, which is required by `Vec<>::Baz>: Clone` | = note: required for `Vec<>::Baz>` to implement `Clone` note: required by a bound in `Foo2::Bar` @@ -105,7 +105,7 @@ error[E0277]: the trait bound `>::Baz: Clone` is not satisfied --> $DIR/defaults-suitability.rs:74:23 | LL | type Bar: Clone = Vec; - | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz` + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz`, which is required by `Vec<>::Baz>: Clone` | = note: required for `Vec<>::Baz>` to implement `Clone` note: required by a bound in `Foo25::Bar` diff --git a/tests/ui/associated-types/hr-associated-type-bound-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-1.stderr index ab5dc803cdf47..01005b6b22d1f 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-1.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-1.rs:12:14 | LL | type U = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> >::U: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr index 9e03936422491..0031d205b8426 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-1.rs:14:14 | LL | type V = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> >::V: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `Y` diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr index 1a749007ab674..bb484da6a77b1 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr @@ -18,7 +18,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-2.rs:15:14 | LL | type W = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> >::W: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr index f8be4ec241052..f4d2f43a9b4d9 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-3.rs:13:14 | LL | type U = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> <(T,) as X<'b, (T,)>>::U: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr index 22c4bd68690e3..7f03d1553912d 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-4.rs:13:14 | LL | type U = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> <(T,) as X<'b, T>>::U: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr index aae80a9b2e196..fbbc2f4577243 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-5.rs:26:14 | LL | type U = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> < as Cycle>::Next as X<'b, as Cycle>::Next>>::U: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` @@ -18,7 +18,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-5.rs:31:14 | LL | type U = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> < as Cycle>::Next as X<'b, as Cycle>::Next>>::U: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 0e34f541ea303..50d622c89bb57 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -21,7 +21,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:38:1 | LL | pub enum ColumnInsertValue where - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -45,7 +45,7 @@ LL | | Col: Column, ... | LL | | Default(Col), LL | | } - | |_^ the trait `NotNull` is not implemented for `::SqlType` + | |_^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -63,7 +63,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -82,7 +82,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -102,7 +102,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -117,7 +117,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -133,7 +133,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -153,7 +153,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -172,7 +172,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -192,7 +192,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -207,7 +207,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -223,7 +223,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -239,7 +239,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -255,7 +255,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -271,7 +271,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 diff --git a/tests/ui/associated-types/issue-43784-associated-type.stderr b/tests/ui/associated-types/issue-43784-associated-type.stderr index 529fc1f119a9c..b2cbe8ee86e56 100644 --- a/tests/ui/associated-types/issue-43784-associated-type.stderr +++ b/tests/ui/associated-types/issue-43784-associated-type.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/issue-43784-associated-type.rs:14:18 | LL | type Assoc = T; - | ^ the trait `Copy` is not implemented for `T` + | ^ the trait `Copy` is not implemented for `T`, which is required by `::Assoc: Partial` | note: required for `::Assoc` to implement `Partial` --> $DIR/issue-43784-associated-type.rs:1:11 diff --git a/tests/ui/associated-types/issue-65774-1.stderr b/tests/ui/associated-types/issue-65774-1.stderr index 9c77a25c4320d..9748a8fbbf491 100644 --- a/tests/ui/associated-types/issue-65774-1.stderr +++ b/tests/ui/associated-types/issue-65774-1.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied --> $DIR/issue-65774-1.rs:44:76 | LL | let closure = |config: &mut ::MpuConfig| writer.my_write(&config); - | ^^^^^^^ the trait `MyDisplay` is not implemented for `T` + | ^^^^^^^ the trait `MyDisplay` is not implemented for `T`, which is required by `&mut T: MyDisplay` | = help: the trait `MyDisplay` is implemented for `&'a mut T` note: required for `&mut T` to implement `MyDisplay` diff --git a/tests/ui/associated-types/substs-ppaux.normal.stderr b/tests/ui/associated-types/substs-ppaux.normal.stderr index 015b22f790f8a..93118616f02c7 100644 --- a/tests/ui/associated-types/substs-ppaux.normal.stderr +++ b/tests/ui/associated-types/substs-ppaux.normal.stderr @@ -76,7 +76,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | >::bar; | ^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `str` + = help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>` note: required for `str` to implement `Foo<'_, '_, u8>` --> $DIR/substs-ppaux.rs:11:17 | diff --git a/tests/ui/associated-types/substs-ppaux.verbose.stderr b/tests/ui/associated-types/substs-ppaux.verbose.stderr index 484581b10288b..13d3156fb8018 100644 --- a/tests/ui/associated-types/substs-ppaux.verbose.stderr +++ b/tests/ui/associated-types/substs-ppaux.verbose.stderr @@ -76,7 +76,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | >::bar; | ^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `str` + = help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>` note: required for `str` to implement `Foo<'?0, '?1, u8>` --> $DIR/substs-ppaux.rs:11:17 | diff --git a/tests/ui/async-await/async-await-let-else.stderr b/tests/ui/async-await/async-await-let-else.stderr index b360aab6b595f..057906b49a37b 100644 --- a/tests/ui/async-await/async-await-let-else.stderr +++ b/tests/ui/async-await/async-await-let-else.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | is_send(foo(Some(true))); | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/async-await-let-else.rs:8:15 | @@ -29,7 +29,7 @@ LL | is_send(foo2(Some(true))); | | | required by a bound introduced by this call | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future: Send` note: required because it's used within this `async` fn body --> $DIR/async-await-let-else.rs:24:29 | @@ -61,7 +61,7 @@ error: future cannot be sent between threads safely LL | is_send(foo3(Some(true))); | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/async-await-let-else.rs:30:29 | @@ -81,7 +81,7 @@ error: future cannot be sent between threads safely LL | is_send(foo4(Some(true))); | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/async-await-let-else.rs:38:15 | diff --git a/tests/ui/async-await/async-fn-nonsend.stderr b/tests/ui/async-await/async-fn-nonsend.stderr index 0ced6c36f4715..8b245281da991 100644 --- a/tests/ui/async-await/async-fn-nonsend.stderr +++ b/tests/ui/async-await/async-fn-nonsend.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | assert_send(non_send_temporary_in_match()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:33:26 | @@ -24,7 +24,7 @@ error: future cannot be sent between threads safely LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `dyn std::fmt::Write` + = help: within `impl Future`, the trait `Send` is not implemented for `dyn std::fmt::Write`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:46:15 | diff --git a/tests/ui/async-await/async-is-unwindsafe.stderr b/tests/ui/async-await/async-is-unwindsafe.stderr index 4098b29c55716..5d87fc747682a 100644 --- a/tests/ui/async-await/async-is-unwindsafe.stderr +++ b/tests/ui/async-await/async-is-unwindsafe.stderr @@ -15,7 +15,7 @@ LL | || }); | |_____| | within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}` | - = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>` + = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}: UnwindSafe` = note: `UnwindSafe` is implemented for `&Context<'_>`, but not for `&mut Context<'_>` note: future does not implement `UnwindSafe` as this value is used across an await --> $DIR/async-is-unwindsafe.rs:25:18 diff --git a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr index 8c9d06c79ca42..eab5bea681cb1 100644 --- a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr +++ b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr @@ -7,7 +7,7 @@ LL | [0usize; 0xffff_ffff_ffff_ffff].await; | |`[usize; usize::MAX]` is not a future | help: remove the `.await` | - = help: the trait `Future` is not implemented for `[usize; usize::MAX]` + = help: the trait `Future` is not implemented for `[usize; usize::MAX]`, which is required by `[usize; usize::MAX]: IntoFuture` = note: [usize; usize::MAX] must be a future or must implement `IntoFuture` to be awaited = note: required for `[usize; usize::MAX]` to implement `IntoFuture` diff --git a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr index 721e01062937e..53cdc9b61d32b 100644 --- a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr +++ b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr @@ -15,7 +15,7 @@ LL | None { value: (), ..Default::default() }.await; | |`Option<_>` is not a future | help: remove the `.await` | - = help: the trait `Future` is not implemented for `Option<_>` + = help: the trait `Future` is not implemented for `Option<_>`, which is required by `Option<_>: IntoFuture` = note: Option<_> must be a future or must implement `IntoFuture` to be awaited = note: required for `Option<_>` to implement `IntoFuture` diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr index 9fce4d61b3b6f..ce2cee6ed4735 100644 --- a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr +++ b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | assert_send(agent.handle()); | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/drop-track-field-assign-nonsend.rs:20:39 | diff --git a/tests/ui/async-await/field-assign-nonsend.stderr b/tests/ui/async-await/field-assign-nonsend.stderr index 418a0829c657e..525a2cc78b493 100644 --- a/tests/ui/async-await/field-assign-nonsend.stderr +++ b/tests/ui/async-await/field-assign-nonsend.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | assert_send(agent.handle()); | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/field-assign-nonsend.rs:20:39 | diff --git a/tests/ui/async-await/in-trait/missing-send-bound.stderr b/tests/ui/async-await/in-trait/missing-send-bound.stderr index aeabb5931dfc7..93f37a9a8e904 100644 --- a/tests/ui/async-await/in-trait/missing-send-bound.stderr +++ b/tests/ui/async-await/in-trait/missing-send-bound.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | assert_is_send(test::()); | ^^^^^^^^^^^ future returned by `test` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `impl Future` + = help: within `impl Future`, the trait `Send` is not implemented for `impl Future`, which is required by `impl Future: Send` note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/missing-send-bound.rs:9:5 | diff --git a/tests/ui/async-await/issue-101715.stderr b/tests/ui/async-await/issue-101715.stderr index f6af15c00d621..3b429793b786f 100644 --- a/tests/ui/async-await/issue-101715.stderr +++ b/tests/ui/async-await/issue-101715.stderr @@ -7,7 +7,7 @@ LL | .await | |`()` is not a future | help: remove the `.await` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` diff --git a/tests/ui/async-await/issue-64130-1-sync.stderr b/tests/ui/async-await/issue-64130-1-sync.stderr index 5428d7ef71b30..15f49124f6fa0 100644 --- a/tests/ui/async-await/issue-64130-1-sync.stderr +++ b/tests/ui/async-await/issue-64130-1-sync.stderr @@ -4,7 +4,7 @@ error: future cannot be shared between threads safely LL | is_sync(bar()); | ^^^^^ future returned by `bar` is not `Sync` | - = help: within `impl Future`, the trait `Sync` is not implemented for `Foo` + = help: within `impl Future`, the trait `Sync` is not implemented for `Foo`, which is required by `impl Future: Sync` note: future is not `Sync` as this value is used across an await --> $DIR/issue-64130-1-sync.rs:15:11 | diff --git a/tests/ui/async-await/issue-64130-2-send.stderr b/tests/ui/async-await/issue-64130-2-send.stderr index f05e954d2d714..67368314b1b77 100644 --- a/tests/ui/async-await/issue-64130-2-send.stderr +++ b/tests/ui/async-await/issue-64130-2-send.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | is_send(bar()); | ^^^^^ future returned by `bar` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Foo` + = help: within `impl Future`, the trait `Send` is not implemented for `Foo`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-2-send.rs:15:11 | diff --git a/tests/ui/async-await/issue-64130-3-other.stderr b/tests/ui/async-await/issue-64130-3-other.stderr index 3ac30bdc23e63..e3a73920c921a 100644 --- a/tests/ui/async-await/issue-64130-3-other.stderr +++ b/tests/ui/async-await/issue-64130-3-other.stderr @@ -5,7 +5,7 @@ LL | async fn bar() { | -------------- within this `impl Future` ... LL | is_qux(bar()); - | ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo` + | ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo`, which is required by `impl Future: Qux` | note: future does not implement `Qux` as this value is used across an await --> $DIR/issue-64130-3-other.rs:18:11 diff --git a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr index d28807e223bef..bd890c838179e 100644 --- a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | is_send(foo()); | ^^^^^ future returned by `foo` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>` + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-non-send-future-diags.rs:17:11 | diff --git a/tests/ui/async-await/issue-67252-unnamed-future.stderr b/tests/ui/async-await/issue-67252-unnamed-future.stderr index 62ffb7d2edafe..51c06b9c8afef 100644 --- a/tests/ui/async-await/issue-67252-unnamed-future.stderr +++ b/tests/ui/async-await/issue-67252-unnamed-future.stderr @@ -8,7 +8,7 @@ LL | | let _a = a; LL | | }); | |______^ future created by async block is not `Send` | - = help: within `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 22:6}`, the trait `Send` is not implemented for `*mut ()` + = help: within `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 22:6}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 22:6}: Send` note: future is not `Send` as this value is used across an await --> $DIR/issue-67252-unnamed-future.rs:20:17 | diff --git a/tests/ui/async-await/issue-68112.stderr b/tests/ui/async-await/issue-68112.stderr index 438782e0e4534..f92ac5dd0bc56 100644 --- a/tests/ui/async-await/issue-68112.stderr +++ b/tests/ui/async-await/issue-68112.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | require_send(send_fut); | ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{async block@$DIR/issue-68112.rs:29:20: 33:6}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/issue-68112.rs:31:17 @@ -23,7 +23,7 @@ error: future cannot be sent between threads safely LL | require_send(send_fut); | ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{async block@$DIR/issue-68112.rs:39:20: 42:6}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/issue-68112.rs:40:17 @@ -42,7 +42,7 @@ error[E0277]: `RefCell` cannot be shared between threads safely LL | require_send(send_fut); | ^^^^^^^^^^^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{async block@$DIR/issue-68112.rs:57:20: 61:6}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Arc>` to implement `Send` note: required because it's used within this `async` fn body diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index 14ef1cbb67c50..36e297ed88422 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -4,7 +4,7 @@ error[E0277]: `*mut ()` cannot be shared between threads safely LL | fn foo(x: NotSync) -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely | - = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` + = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:17:5: 21:6}: Send` note: required because it appears within the type `PhantomData<*mut ()>` --> $SRC_DIR/core/src/marker.rs:LL:COL note: required because it appears within the type `NotSync` diff --git a/tests/ui/async-await/issue-71137.stderr b/tests/ui/async-await/issue-71137.stderr index 8739c22a31048..75d72e425f57b 100644 --- a/tests/ui/async-await/issue-71137.stderr +++ b/tests/ui/async-await/issue-71137.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | fake_spawn(wrong_mutex()); | ^^^^^^^^^^^^^ future returned by `wrong_mutex` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>` + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/issue-71137.rs:14:26 | diff --git a/tests/ui/async-await/issue-72590-type-error-sized.stderr b/tests/ui/async-await/issue-72590-type-error-sized.stderr index 778423578e169..1b822234d80cc 100644 --- a/tests/ui/async-await/issue-72590-type-error-sized.stderr +++ b/tests/ui/async-await/issue-72590-type-error-sized.stderr @@ -16,7 +16,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | async fn frob(self) {} | ^^^^ doesn't have a size known at compile-time | - = help: within `Foo`, the trait `Sized` is not implemented for `str` + = help: within `Foo`, the trait `Sized` is not implemented for `str`, which is required by `Foo: Sized` note: required because it appears within the type `Foo` --> $DIR/issue-72590-type-error-sized.rs:5:8 | diff --git a/tests/ui/async-await/issues/issue-67893.stderr b/tests/ui/async-await/issues/issue-67893.stderr index 90c1e976dcee6..12bbfc125521d 100644 --- a/tests/ui/async-await/issues/issue-67893.stderr +++ b/tests/ui/async-await/issues/issue-67893.stderr @@ -11,7 +11,7 @@ LL | g(issue_67893::run()) LL | pub async fn run() { | ------------------ within this `impl Future` | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`, which is required by `impl Future: Send` = note: required because it captures the following types: `Arc>`, `MutexGuard<'_, ()>`, `impl Future` note: required because it's used within this `async` fn body --> $DIR/auxiliary/issue_67893.rs:9:20 diff --git a/tests/ui/async-await/partial-drop-partial-reinit.stderr b/tests/ui/async-await/partial-drop-partial-reinit.stderr index f088b118730aa..a6140c6db8286 100644 --- a/tests/ui/async-await/partial-drop-partial-reinit.stderr +++ b/tests/ui/async-await/partial-drop-partial-reinit.stderr @@ -9,7 +9,7 @@ LL | gimme_send(foo()); LL | async fn foo() { | -------------- within this `impl Future` | - = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` + = help: within `impl Future`, the trait `Send` is not implemented for `NotSend`, which is required by `impl Future: Send` = note: required because it appears within the type `(NotSend,)` = note: required because it captures the following types: `(NotSend,)`, `impl Future` note: required because it's used within this `async` fn body diff --git a/tests/ui/async-await/pin-needed-to-poll-2.stderr b/tests/ui/async-await/pin-needed-to-poll-2.stderr index 8eb671531e792..e22baabc25b53 100644 --- a/tests/ui/async-await/pin-needed-to-poll-2.stderr +++ b/tests/ui/async-await/pin-needed-to-poll-2.stderr @@ -2,7 +2,7 @@ error[E0277]: `PhantomPinned` cannot be unpinned --> $DIR/pin-needed-to-poll-2.rs:43:18 | LL | Pin::new(&mut self.sleep).poll(cx) - | -------- ^^^^^^^^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned` + | -------- ^^^^^^^^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned`, which is required by `Sleep: Unpin` | | | required by a bound introduced by this call | diff --git a/tests/ui/async-await/unnecessary-await.stderr b/tests/ui/async-await/unnecessary-await.stderr index 620370a6113a3..8d81957653240 100644 --- a/tests/ui/async-await/unnecessary-await.stderr +++ b/tests/ui/async-await/unnecessary-await.stderr @@ -6,7 +6,7 @@ LL | boo().await; | | | this call returns `()` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` help: remove the `.await` @@ -28,7 +28,7 @@ LL | e!().await; | |`()` is not a future | help: remove the `.await` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` @@ -44,7 +44,7 @@ LL | $expr.await LL | f!(()); | ------ in this macro invocation | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -58,7 +58,7 @@ LL | for x in [] {}.await | |`()` is not a future | help: remove the `.await` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` diff --git a/tests/ui/auto-traits/issue-83857-ub.stderr b/tests/ui/auto-traits/issue-83857-ub.stderr index 80f9330eb8180..97f1a6032086e 100644 --- a/tests/ui/auto-traits/issue-83857-ub.stderr +++ b/tests/ui/auto-traits/issue-83857-ub.stderr @@ -4,7 +4,7 @@ error[E0277]: `Foo` cannot be sent between threads safely LL | fn generic(v: Foo, f: fn( as WithAssoc>::Output) -> i32) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `Foo` + = help: the trait `Send` is not implemented for `Foo`, which is required by `Foo: WithAssoc` note: required for `Foo` to implement `WithAssoc` --> $DIR/issue-83857-ub.rs:15:15 | diff --git a/tests/ui/auto-traits/str-contains-slice-conceptually.stderr b/tests/ui/auto-traits/str-contains-slice-conceptually.stderr index e1dae35be006d..ebd3a556e7579 100644 --- a/tests/ui/auto-traits/str-contains-slice-conceptually.stderr +++ b/tests/ui/auto-traits/str-contains-slice-conceptually.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `[u8]: AutoTrait` is not satisfied in `str` --> $DIR/str-contains-slice-conceptually.rs:11:22 | LL | needs_auto_trait::(); - | ^^^ within `str`, the trait `AutoTrait` is not implemented for `[u8]` + | ^^^ within `str`, the trait `AutoTrait` is not implemented for `[u8]`, which is required by `str: AutoTrait` | = note: `str` is considered to contain a `[u8]` slice for auto trait purposes note: required by a bound in `needs_auto_trait` diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr index aa5585a5371f6..b7c9738991274 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr +++ b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)` --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:18 | LL | is_mytrait::<(MyS2, MyS)>(); - | ^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2` + | ^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2`, which is required by `(MyS2, MyS): MyTrait` | = note: required because it appears within the type `(MyS2, MyS)` note: required by a bound in `is_mytrait` diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr index 2498af996eabd..e699422ae2b86 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr +++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied --> $DIR/typeck-default-trait-impl-precedence.rs:19:20 | LL | is_defaulted::<&'static u32>(); - | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` + | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted` | note: required for `&'static u32` to implement `Defaulted` --> $DIR/typeck-default-trait-impl-precedence.rs:10:19 diff --git a/tests/ui/binop/binary-op-suggest-deref.stderr b/tests/ui/binop/binary-op-suggest-deref.stderr index a98a2ab070666..8a226d712ff58 100644 --- a/tests/ui/binop/binary-op-suggest-deref.stderr +++ b/tests/ui/binop/binary-op-suggest-deref.stderr @@ -27,7 +27,7 @@ error[E0277]: can't compare `&{integer}` with `{integer}` LL | _ = foo == &0; | ^^ no implementation for `&{integer} == {integer}` | - = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}` + = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}`, which is required by `&&{integer}: PartialEq<&{integer}>` = note: required for `&&{integer}` to implement `PartialEq<&{integer}>` help: consider dereferencing here | @@ -65,7 +65,7 @@ error[E0277]: can't compare `&&{integer}` with `{integer}` LL | _ = &&foo == &&0; | ^^ no implementation for `&&{integer} == {integer}` | - = help: the trait `PartialEq<{integer}>` is not implemented for `&&{integer}` + = help: the trait `PartialEq<{integer}>` is not implemented for `&&{integer}`, which is required by `&&&&{integer}: PartialEq<&&{integer}>` = note: required for `&&&{integer}` to implement `PartialEq<&{integer}>` = note: 1 redundant requirement hidden = note: required for `&&&&{integer}` to implement `PartialEq<&&{integer}>` @@ -119,7 +119,7 @@ error[E0277]: can't compare `{integer}` with `&{integer}` LL | _ = &0 == foo; | ^^ no implementation for `{integer} == &{integer}` | - = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}` + = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`, which is required by `&{integer}: PartialEq<&&{integer}>` = note: required for `&{integer}` to implement `PartialEq<&&{integer}>` help: consider dereferencing here | @@ -157,7 +157,7 @@ error[E0277]: can't compare `{integer}` with `&&{integer}` LL | _ = &&0 == &&foo; | ^^ no implementation for `{integer} == &&{integer}` | - = help: the trait `PartialEq<&&{integer}>` is not implemented for `{integer}` + = help: the trait `PartialEq<&&{integer}>` is not implemented for `{integer}`, which is required by `&&{integer}: PartialEq<&&&&{integer}>` = note: required for `&{integer}` to implement `PartialEq<&&&{integer}>` = note: 1 redundant requirement hidden = note: required for `&&{integer}` to implement `PartialEq<&&&&{integer}>` @@ -173,7 +173,7 @@ error[E0277]: can't compare `Box>` with `&&{integer}` LL | _ = &Box::new(Box::new(42)) == &foo; | ^^ no implementation for `Box> == &&{integer}` | - = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box>` + = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box>`, which is required by `&Box>: PartialEq<&&&{integer}>` = note: required for `&Box>` to implement `PartialEq<&&&{integer}>` help: consider dereferencing both sides of the expression | @@ -187,7 +187,7 @@ error[E0277]: can't compare `Box<{integer}>` with `&&{integer}` LL | _ = &Box::new(42) == &foo; | ^^ no implementation for `Box<{integer}> == &&{integer}` | - = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box<{integer}>` + = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box<{integer}>`, which is required by `&Box<{integer}>: PartialEq<&&&{integer}>` = note: required for `&Box<{integer}>` to implement `PartialEq<&&&{integer}>` help: consider dereferencing both sides of the expression | @@ -201,7 +201,7 @@ error[E0277]: can't compare `Box>>>` with `&&{integer}` LL | _ = &Box::new(Box::new(Box::new(Box::new(42)))) == &foo; | ^^ no implementation for `Box>>> == &&{integer}` | - = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box>>>` + = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box>>>`, which is required by `&Box>>>: PartialEq<&&&{integer}>` = note: required for `&Box>>>` to implement `PartialEq<&&&{integer}>` help: consider dereferencing both sides of the expression | @@ -215,7 +215,7 @@ error[E0277]: can't compare `&&{integer}` with `Box>>>` LL | _ = &foo == &Box::new(Box::new(Box::new(Box::new(42)))); | ^^ no implementation for `&&{integer} == Box>>>` | - = help: the trait `PartialEq>>>>` is not implemented for `&&{integer}` + = help: the trait `PartialEq>>>>` is not implemented for `&&{integer}`, which is required by `&&&{integer}: PartialEq<&Box>>>>` = note: required for `&&&{integer}` to implement `PartialEq<&Box>>>>` help: consider dereferencing both sides of the expression | diff --git a/tests/ui/block-result/issue-22645.stderr b/tests/ui/block-result/issue-22645.stderr index 1064848f5139e..2a267ce792fde 100644 --- a/tests/ui/block-result/issue-22645.stderr +++ b/tests/ui/block-result/issue-22645.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied --> $DIR/issue-22645.rs:15:5 | LL | b + 3 - | ^ the trait `Scalar` is not implemented for `{integer}` + | ^ the trait `Scalar` is not implemented for `{integer}`, which is required by `Bob: Add<_>` | = help: the trait `Scalar` is implemented for `f64` note: required for `Bob` to implement `Add<{integer}>` diff --git a/tests/ui/closures/closure-move-sync.stderr b/tests/ui/closures/closure-move-sync.stderr index 2bb26b0c0b7d4..6cade0c09dd7e 100644 --- a/tests/ui/closures/closure-move-sync.stderr +++ b/tests/ui/closures/closure-move-sync.stderr @@ -10,7 +10,7 @@ LL | | LL | | }); | |_____^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>` + = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>`, which is required by `{closure@$DIR/closure-move-sync.rs:6:27: 6:29}: Send` = note: required for `&std::sync::mpsc::Receiver<()>` to implement `Send` note: required because it's used within this closure --> $DIR/closure-move-sync.rs:6:27 diff --git a/tests/ui/closures/closure-return-type-must-be-sized.stderr b/tests/ui/closures/closure-return-type-must-be-sized.stderr index 04ae7343bbe9b..167d326e26edf 100644 --- a/tests/ui/closures/closure-return-type-must-be-sized.stderr +++ b/tests/ui/closures/closure-return-type-must-be-sized.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | a::foo:: dyn A>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time @@ -13,7 +13,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | a::bar:: dyn A, _>(); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` note: required by a bound in `a::bar` --> $DIR/closure-return-type-must-be-sized.rs:14:19 @@ -27,7 +27,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | a::baz:: dyn A>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time @@ -36,7 +36,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | b::foo:: dyn A>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time @@ -45,7 +45,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | b::bar:: dyn A, _>(); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: Fn()` = note: required because it appears within the type `fn() -> dyn A` note: required by a bound in `b::bar` --> $DIR/closure-return-type-must-be-sized.rs:28:19 @@ -59,7 +59,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | b::baz:: dyn A>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time @@ -68,7 +68,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | c::foo:: dyn A>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time @@ -77,7 +77,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | c::bar:: dyn A, _>(); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnMut()` = note: required because it appears within the type `fn() -> dyn A` note: required by a bound in `c::bar` --> $DIR/closure-return-type-must-be-sized.rs:42:19 @@ -91,7 +91,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | c::baz:: dyn A>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error: aborting due to 9 previous errors diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr index 1177965d0d2c2..771d661f615ec 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr @@ -2,7 +2,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type --> $DIR/const_param_ty_bad_empty_array.rs:10:13 | LL | check::<[NotParam; 0]>(); - | ^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | ^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam; 0]: ConstParamTy` | = note: required for `[NotParam; 0]` to implement `ConstParamTy` note: required by a bound in `check` diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr index 86d1c94e87f96..83c34c41f1059 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr @@ -2,7 +2,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:10:13 | LL | check::<&NotParam>(); - | ^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | ^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `&NotParam: ConstParamTy` | = note: required for `&NotParam` to implement `ConstParamTy` note: required by a bound in `check` @@ -15,7 +15,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:11:13 | LL | check::<[NotParam]>(); - | ^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | ^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam]: ConstParamTy` | = note: required for `[NotParam]` to implement `ConstParamTy` note: required by a bound in `check` @@ -28,7 +28,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:12:13 | LL | check::<[NotParam; 17]>(); - | ^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | ^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam; 17]: ConstParamTy` | = note: required for `[NotParam; 17]` to implement `ConstParamTy` note: required by a bound in `check` diff --git a/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr index 8b7120035cab5..3acccba026f26 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied --> $DIR/issue-85848.rs:24:29 | LL | writes_to_specific_path(&cap); - | ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()` + | ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()`, which is required by `&C: Delegates<()>` | | | required by a bound introduced by this call | diff --git a/tests/ui/const-generics/issues/issue-67185-2.stderr b/tests/ui/const-generics/issues/issue-67185-2.stderr index a2e5b8053688b..24a2d60f2e1f0 100644 --- a/tests/ui/const-generics/issues/issue-67185-2.stderr +++ b/tests/ui/const-generics/issues/issue-67185-2.stderr @@ -26,7 +26,7 @@ error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} - | ^^^ the trait `Bar` is not implemented for `[u16; 3]` + | ^^^ the trait `Bar` is not implemented for `[u16; 3]`, which is required by `::Quaks: Bar` | = help: the following other types implement trait `Bar`: [u16; 4] @@ -44,7 +44,7 @@ error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} - | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`, which is required by `[::Quaks; 2]: Bar` | = help: the following other types implement trait `Bar`: [u16; 4] diff --git a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr index b13df67b423bb..14bce10f78744 100644 --- a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr +++ b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied --> $DIR/fn-call-in-non-const.rs:14:32 | LL | let _: [Option; 2] = [no_copy(); 2]; - | ^^^^^^^^^ the trait `Copy` is not implemented for `Bar` + | ^^^^^^^^^ the trait `Copy` is not implemented for `Bar`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array diff --git a/tests/ui/consts/const-blocks/migrate-fail.stderr b/tests/ui/consts/const-blocks/migrate-fail.stderr index 3c116026e5804..3887658f74835 100644 --- a/tests/ui/consts/const-blocks/migrate-fail.stderr +++ b/tests/ui/consts/const-blocks/migrate-fail.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied --> $DIR/migrate-fail.rs:11:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^ the trait `Copy` is not implemented for `Bar` + | ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array @@ -18,7 +18,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied --> $DIR/migrate-fail.rs:17:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^ the trait `Copy` is not implemented for `Bar` + | ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array diff --git a/tests/ui/consts/const-blocks/nll-fail.stderr b/tests/ui/consts/const-blocks/nll-fail.stderr index ff2b62da66828..a2ea833f650e3 100644 --- a/tests/ui/consts/const-blocks/nll-fail.stderr +++ b/tests/ui/consts/const-blocks/nll-fail.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied --> $DIR/nll-fail.rs:11:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^ the trait `Copy` is not implemented for `Bar` + | ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array @@ -18,7 +18,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied --> $DIR/nll-fail.rs:17:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^ the trait `Copy` is not implemented for `Bar` + | ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 36249bf3f6d4e..b0b1378bb7de0 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/trait-error.rs:5:6 | LL | [Foo(String::new()); 4]; - | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`, which is required by `Foo: Copy` | note: required for `Foo` to implement `Copy` --> $DIR/trait-error.rs:1:10 diff --git a/tests/ui/consts/const-fn-in-vec.stderr b/tests/ui/consts/const-fn-in-vec.stderr index 4593034bfaea3..12098e8199cd7 100644 --- a/tests/ui/consts/const-fn-in-vec.stderr +++ b/tests/ui/consts/const-fn-in-vec.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/const-fn-in-vec.rs:1:47 | LL | static _MAYBE_STRINGS: [Option; 5] = [None; 5]; - | ^^^^ the trait `Copy` is not implemented for `String` + | ^^^^ the trait `Copy` is not implemented for `String`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array @@ -31,7 +31,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/const-fn-in-vec.rs:9:48 | LL | let _maybe_strings: [Option; 5] = [None; 5]; - | ^^^^ the trait `Copy` is not implemented for `String` + | ^^^^ the trait `Copy` is not implemented for `String`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr index 9ee011ebc36b0..1d4804501d8bc 100644 --- a/tests/ui/coroutine/clone-impl.stderr +++ b/tests/ui/coroutine/clone-impl.stderr @@ -5,7 +5,7 @@ LL | let gen_clone_0 = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}: Copy` | note: captured value does not implement `Copy` --> $DIR/clone-impl.rs:40:14 @@ -25,7 +25,7 @@ LL | let gen_clone_0 = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}: Copy` | note: coroutine does not implement `Copy` as this value is used across a yield --> $DIR/clone-impl.rs:38:9 @@ -47,7 +47,7 @@ LL | let gen_clone_1 = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}: Copy` | note: captured value does not implement `Copy` --> $DIR/clone-impl.rs:56:14 @@ -67,7 +67,7 @@ LL | let gen_clone_1 = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}: Copy` | note: coroutine does not implement `Copy` as this value is used across a yield --> $DIR/clone-impl.rs:52:9 @@ -90,7 +90,7 @@ LL | let gen_non_clone = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}` ... LL | check_copy(&gen_non_clone); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Copy` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}: Copy` | note: captured value does not implement `Copy` --> $DIR/clone-impl.rs:64:14 @@ -115,7 +115,7 @@ LL | let gen_non_clone = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}` ... LL | check_clone(&gen_non_clone); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Clone` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}: Clone` | note: captured value does not implement `Clone` --> $DIR/clone-impl.rs:64:14 diff --git a/tests/ui/coroutine/drop-tracking-parent-expression.stderr b/tests/ui/coroutine/drop-tracking-parent-expression.stderr index a57b7ffab4d63..21aa35b9579bc 100644 --- a/tests/ui/coroutine/drop-tracking-parent-expression.stderr +++ b/tests/ui/coroutine/drop-tracking-parent-expression.stderr @@ -13,7 +13,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client` + = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-tracking-parent-expression.rs:21:22 | @@ -53,7 +53,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client` + = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-tracking-parent-expression.rs:21:22 | @@ -93,7 +93,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client` + = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-tracking-parent-expression.rs:21:22 | diff --git a/tests/ui/coroutine/drop-yield-twice.stderr b/tests/ui/coroutine/drop-yield-twice.stderr index 5766e95f0888b..c6a9e20b8b51f 100644 --- a/tests/ui/coroutine/drop-yield-twice.stderr +++ b/tests/ui/coroutine/drop-yield-twice.stderr @@ -9,7 +9,7 @@ LL | | yield; LL | | }) | |______^ coroutine is not `Send` | - = help: within `{coroutine@$DIR/drop-yield-twice.rs:7:17: 7:19}`, the trait `Send` is not implemented for `Foo` + = help: within `{coroutine@$DIR/drop-yield-twice.rs:7:17: 7:19}`, the trait `Send` is not implemented for `Foo`, which is required by `{coroutine@$DIR/drop-yield-twice.rs:7:17: 7:19}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-yield-twice.rs:9:9 | diff --git a/tests/ui/coroutine/issue-105084.stderr b/tests/ui/coroutine/issue-105084.stderr index 34e97752f6cdc..c8a6522dbd938 100644 --- a/tests/ui/coroutine/issue-105084.stderr +++ b/tests/ui/coroutine/issue-105084.stderr @@ -29,7 +29,7 @@ LL | let mut g = || { | -- within this `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}` ... LL | let mut h = copy(g); - | ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`, the trait `Copy` is not implemented for `Box<(i32, ())>` + | ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`, the trait `Copy` is not implemented for `Box<(i32, ())>`, which is required by `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}: Copy` | note: coroutine does not implement `Copy` as this value is used across a yield --> $DIR/issue-105084.rs:21:22 diff --git a/tests/ui/coroutine/issue-68112.stderr b/tests/ui/coroutine/issue-68112.stderr index 320350034872c..ded325eda544c 100644 --- a/tests/ui/coroutine/issue-68112.stderr +++ b/tests/ui/coroutine/issue-68112.stderr @@ -4,7 +4,7 @@ error: coroutine cannot be sent between threads safely LL | require_send(send_gen); | ^^^^^^^^^^^^^^^^^^^^^^ coroutine is not `Send` | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{coroutine@$DIR/issue-68112.rs:33:20: 33:22}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: coroutine is not `Send` as this value is used across a yield --> $DIR/issue-68112.rs:36:9 @@ -26,7 +26,7 @@ error[E0277]: `RefCell` cannot be shared between threads safely LL | require_send(send_gen); | ^^^^^^^^^^^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{coroutine@$DIR/issue-68112.rs:60:20: 60:22}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Arc>` to implement `Send` note: required because it's used within this coroutine diff --git a/tests/ui/coroutine/not-send-sync.stderr b/tests/ui/coroutine/not-send-sync.stderr index e00c0d9158c92..9228340c710dd 100644 --- a/tests/ui/coroutine/not-send-sync.stderr +++ b/tests/ui/coroutine/not-send-sync.stderr @@ -9,7 +9,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Sync` | - = help: within `{coroutine@$DIR/not-send-sync.rs:14:17: 14:19}`, the trait `Sync` is not implemented for `NotSync` + = help: within `{coroutine@$DIR/not-send-sync.rs:14:17: 14:19}`, the trait `Sync` is not implemented for `NotSync`, which is required by `{coroutine@$DIR/not-send-sync.rs:14:17: 14:19}: Sync` note: coroutine is not `Sync` as this value is used across a yield --> $DIR/not-send-sync.rs:17:9 | @@ -34,7 +34,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Send` | - = help: within `{coroutine@$DIR/not-send-sync.rs:21:17: 21:19}`, the trait `Send` is not implemented for `NotSend` + = help: within `{coroutine@$DIR/not-send-sync.rs:21:17: 21:19}`, the trait `Send` is not implemented for `NotSend`, which is required by `{coroutine@$DIR/not-send-sync.rs:21:17: 21:19}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/not-send-sync.rs:24:9 | diff --git a/tests/ui/coroutine/parent-expression.stderr b/tests/ui/coroutine/parent-expression.stderr index d2c09432b3a16..5b3737069e6c1 100644 --- a/tests/ui/coroutine/parent-expression.stderr +++ b/tests/ui/coroutine/parent-expression.stderr @@ -13,7 +13,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client` + = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/parent-expression.rs:21:22 | @@ -53,7 +53,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client` + = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/parent-expression.rs:21:22 | @@ -93,7 +93,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client` + = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/parent-expression.rs:21:22 | diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr index 6cf0f6e73ac4c..1b9ca632f0cb6 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr @@ -4,7 +4,7 @@ error: coroutine cannot be sent between threads safely LL | require_send(send_gen); | ^^^^^^^^^^^^^^^^^^^^^^ coroutine is not `Send` | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{test1::{closure#0} upvar_tys=() witness={test1::{closure#0}}}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: coroutine is not `Send` as this value is used across a yield --> $DIR/coroutine-print-verbose-1.rs:35:9 @@ -25,7 +25,7 @@ error[E0277]: `RefCell` cannot be shared between threads safely LL | require_send(send_gen); | ^^^^^^^^^^^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{test2::{closure#0} upvar_tys=() witness={test2::{closure#0}}}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Arc>` to implement `Send` note: required because it's used within this coroutine diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr index aef48b7522b38..26c9c27743c01 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr @@ -9,7 +9,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Sync` | - = help: within `{main::{closure#0} upvar_tys=() witness={main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync` + = help: within `{main::{closure#0} upvar_tys=() witness={main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync`, which is required by `{main::{closure#0} upvar_tys=() witness={main::{closure#0}}}: Sync` note: coroutine is not `Sync` as this value is used across a yield --> $DIR/coroutine-print-verbose-2.rs:20:9 | @@ -34,7 +34,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Send` | - = help: within `{main::{closure#1} upvar_tys=() witness={main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend` + = help: within `{main::{closure#1} upvar_tys=() witness={main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend`, which is required by `{main::{closure#1} upvar_tys=() witness={main::{closure#1}}}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/coroutine-print-verbose-2.rs:27:9 | diff --git a/tests/ui/coroutine/ref-upvar-not-send.stderr b/tests/ui/coroutine/ref-upvar-not-send.stderr index 7f18c6fba775f..0f91bcf40533f 100644 --- a/tests/ui/coroutine/ref-upvar-not-send.stderr +++ b/tests/ui/coroutine/ref-upvar-not-send.stderr @@ -10,7 +10,7 @@ LL | | let _x = x; LL | | }); | |_____^ coroutine is not `Send` | - = help: the trait `Sync` is not implemented for `*mut ()` + = help: the trait `Sync` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:15:17: 15:24}: Send` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` --> $DIR/ref-upvar-not-send.rs:19:18 | @@ -34,7 +34,7 @@ LL | | let _y = y; LL | | }); | |_____^ coroutine is not `Send` | - = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:17: 23:24}`, the trait `Send` is not implemented for `*mut ()` + = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:17: 23:24}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:23:17: 23:24}: Send` note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send` --> $DIR/ref-upvar-not-send.rs:27:18 | diff --git a/tests/ui/coroutine/unresolved-ct-var.stderr b/tests/ui/coroutine/unresolved-ct-var.stderr index da2ec272f9fff..8b87bac05acb2 100644 --- a/tests/ui/coroutine/unresolved-ct-var.stderr +++ b/tests/ui/coroutine/unresolved-ct-var.stderr @@ -8,7 +8,7 @@ LL | let s = std::array::from_fn(|_| ()).await; | | help: remove the `.await` | this call returns `[(); _]` | - = help: the trait `Future` is not implemented for `[(); _]` + = help: the trait `Future` is not implemented for `[(); _]`, which is required by `[(); _]: IntoFuture` = note: [(); _] must be a future or must implement `IntoFuture` to be awaited = note: required for `[(); _]` to implement `IntoFuture` diff --git a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr index f28f8913508f2..8f8bec9945847 100644 --- a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr +++ b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr @@ -10,7 +10,7 @@ error[E0277]: `{integer}` is not an iterator LL | yield || for i in 0 { } | ^ `{integer}` is not an iterator | - = help: the trait `Iterator` is not implemented for `{integer}` + = help: the trait `Iterator` is not implemented for `{integer}`, which is required by `{integer}: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `{integer}` to implement `IntoIterator` diff --git a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr index 3f6c39bf9396e..b10805ac8f06f 100644 --- a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr @@ -7,7 +7,7 @@ LL | #[derive(Debug)] LL | x: Error | ^^^^^^^^ `Error` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `Error` + = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` diff --git a/tests/ui/derives/derives-span-Debug-enum.stderr b/tests/ui/derives/derives-span-Debug-enum.stderr index eaeffaeb84956..0329744390166 100644 --- a/tests/ui/derives/derives-span-Debug-enum.stderr +++ b/tests/ui/derives/derives-span-Debug-enum.stderr @@ -7,7 +7,7 @@ LL | #[derive(Debug)] LL | Error | ^^^^^ `Error` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `Error` + = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` diff --git a/tests/ui/derives/derives-span-Debug-struct.stderr b/tests/ui/derives/derives-span-Debug-struct.stderr index 4a725e260deae..369c0b56ac4e8 100644 --- a/tests/ui/derives/derives-span-Debug-struct.stderr +++ b/tests/ui/derives/derives-span-Debug-struct.stderr @@ -7,7 +7,7 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ `Error` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `Error` + = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` diff --git a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr index 2f816e1c85b25..abfef9ef35425 100644 --- a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr @@ -7,7 +7,7 @@ LL | struct Struct( LL | Error | ^^^^^ `Error` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `Error` + = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` diff --git a/tests/ui/deriving/issue-103157.stderr b/tests/ui/deriving/issue-103157.stderr index 384899ea43334..f76701860efb5 100644 --- a/tests/ui/deriving/issue-103157.stderr +++ b/tests/ui/deriving/issue-103157.stderr @@ -5,7 +5,7 @@ LL | #[derive(PartialEq, Eq)] | -- in this derive macro expansion ... LL | Float(Option), - | ^^^^^^^^^^^ the trait `Eq` is not implemented for `f64` + | ^^^^^^^^^^^ the trait `Eq` is not implemented for `f64`, which is required by `Option: Eq` | = help: the following other types implement trait `Eq`: isize diff --git a/tests/ui/dst/dst-bad-deep-2.stderr b/tests/ui/dst/dst-bad-deep-2.stderr index c7e9854340f09..554e81bee10a5 100644 --- a/tests/ui/dst/dst-bad-deep-2.stderr +++ b/tests/ui/dst/dst-bad-deep-2.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[isize]` cannot be known at compilati LL | let h: &(([isize],),) = &(*g,); | ^^^^^ doesn't have a size known at compile-time | - = help: within `(([isize],),)`, the trait `Sized` is not implemented for `[isize]` + = help: within `(([isize],),)`, the trait `Sized` is not implemented for `[isize]`, which is required by `(([isize],),): Sized` = note: required because it appears within the type `([isize],)` = note: required because it appears within the type `(([isize],),)` = note: tuples must have a statically known size to be initialized diff --git a/tests/ui/dst/dst-bad-deep.stderr b/tests/ui/dst/dst-bad-deep.stderr index 1b0f9738ab09a..4f180e593f8ae 100644 --- a/tests/ui/dst/dst-bad-deep.stderr +++ b/tests/ui/dst/dst-bad-deep.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[isize]` cannot be known at compilati LL | let h: &Fat> = &Fat { ptr: *g }; | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `Fat>`, the trait `Sized` is not implemented for `[isize]` + = help: within `Fat>`, the trait `Sized` is not implemented for `[isize]`, which is required by `Fat>: Sized` note: required because it appears within the type `Fat<[isize]>` --> $DIR/dst-bad-deep.rs:6:8 | diff --git a/tests/ui/error-codes/E0277-2.stderr b/tests/ui/error-codes/E0277-2.stderr index 9a262f7559075..f4e18e3bb539c 100644 --- a/tests/ui/error-codes/E0277-2.stderr +++ b/tests/ui/error-codes/E0277-2.stderr @@ -4,7 +4,7 @@ error[E0277]: `*const u8` cannot be sent between threads safely LL | is_send::(); | ^^^ `*const u8` cannot be sent between threads safely | - = help: within `Foo`, the trait `Send` is not implemented for `*const u8` + = help: within `Foo`, the trait `Send` is not implemented for `*const u8`, which is required by `Foo: Send` note: required because it appears within the type `Baz` --> $DIR/E0277-2.rs:9:8 | diff --git a/tests/ui/error-codes/E0277.stderr b/tests/ui/error-codes/E0277.stderr index 0b0d2b09720cd..aeb97290cf856 100644 --- a/tests/ui/error-codes/E0277.stderr +++ b/tests/ui/error-codes/E0277.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | fn f(p: Path) { } | ^ doesn't have a size known at compile-time | - = help: within `Path`, the trait `Sized` is not implemented for `[u8]` + = help: within `Path`, the trait `Sized` is not implemented for `[u8]`, which is required by `Path: Sized` note: required because it appears within the type `Path` --> $SRC_DIR/std/src/path.rs:LL:COL = help: unsized fn params are gated as an unstable feature diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr index 9228a047e8785..bd4e934822751 100644 --- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr +++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:53:46 | LL | want(Wrapper { value: Burrito { filling: q } }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | | | required by a bound introduced by this call | @@ -38,7 +38,7 @@ LL | want(Some(())); | | | required by a bound introduced by this call | - = help: the trait `Iterator` is not implemented for `()` + = help: the trait `Iterator` is not implemented for `()`, which is required by `Option<()>: T1` = help: the trait `T1` is implemented for `Option` note: required for `Option<()>` to implement `T1` --> $DIR/blame-trait-error.rs:21:20 @@ -109,7 +109,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:65:45 | LL | want(&ExampleTuple::ExampleTupleVariant(q)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple: T1` | | | required by a bound introduced by this call | @@ -134,7 +134,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:68:31 | LL | want(&ExampleTupleVariant(q)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple: T1` | | | required by a bound introduced by this call | @@ -159,7 +159,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:71:50 | LL | want(&ExampleOtherTuple::ExampleTupleVariant(q)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple: T1` | | | required by a bound introduced by this call | @@ -184,7 +184,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:74:44 | LL | want(&ExampleDifferentTupleVariantName(q)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple: T1` | | | required by a bound introduced by this call | @@ -209,7 +209,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:77:45 | LL | want(&ExampleYetAnotherTupleVariantName(q)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple: T1` | | | required by a bound introduced by this call | @@ -234,7 +234,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:80:56 | LL | want(&ExampleStruct::ExampleStructVariant { field: q }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct: T1` | note: required for `ExampleStruct` to implement `T1` --> $DIR/blame-trait-error.rs:45:9 @@ -257,7 +257,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:83:41 | LL | want(&ExampleStructVariant { field: q }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct: T1` | | | required by a bound introduced by this call | @@ -282,7 +282,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:86:61 | LL | want(&ExampleOtherStruct::ExampleStructVariant { field: q }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct: T1` | note: required for `ExampleStruct` to implement `T1` --> $DIR/blame-trait-error.rs:45:9 @@ -305,7 +305,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:89:54 | LL | want(&ExampleDifferentStructVariantName { field: q }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct: T1` | note: required for `ExampleStruct` to implement `T1` --> $DIR/blame-trait-error.rs:45:9 @@ -328,7 +328,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:92:55 | LL | want(&ExampleYetAnotherStructVariantName { field: q }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct: T1` | note: required for `ExampleStruct` to implement `T1` --> $DIR/blame-trait-error.rs:45:9 @@ -351,7 +351,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:95:38 | LL | want(&ExampleActuallyTupleStruct(q, 0)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleActuallyTupleStruct: T1` | | | required by a bound introduced by this call | @@ -376,7 +376,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:98:43 | LL | want(&ExampleActuallyTupleStructOther(q, 0)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleActuallyTupleStruct: T1` | | | required by a bound introduced by this call | diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr index b6a24e12bcc76..a2df6843f43b9 100644 --- a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr +++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:81:60 | LL | want(Wrapper { value: Burrito { spicy: false, filling: q } }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | note: required for `Burrito` to implement `T2` --> $DIR/blame-trait-error-spans-on-exprs.rs:22:13 @@ -32,7 +32,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:85:84 | LL | want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | note: required for `BurritoKinds` to implement `T2` --> $DIR/blame-trait-error-spans-on-exprs.rs:32:13 @@ -62,7 +62,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:89:39 | LL | want(Wrapper { value: Taco(false, q) }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | | | required by a bound introduced by this call | @@ -94,7 +94,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:93:53 | LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | | | required by a bound introduced by this call | @@ -126,7 +126,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:97:74 | LL | want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | note: required for `GenericBurrito` to implement `T2` --> $DIR/blame-trait-error-spans-on-exprs.rs:47:16 @@ -156,7 +156,7 @@ error[E0277]: the trait bound `Q: T2` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:101:14 | LL | want((3, q)); - | ---- ^ the trait `T2` is not implemented for `Q` + | ---- ^ the trait `T2` is not implemented for `Q`, which is required by `({integer}, Q): T1` | | | required by a bound introduced by this call | @@ -181,7 +181,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:105:31 | LL | want(Wrapper { value: (3, q) }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper<({integer}, Q)>: T1` | | | required by a bound introduced by this call | @@ -213,7 +213,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:109:15 | LL | want(((3, q), 5)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `(({integer}, Q), {integer}): T1` | | | required by a bound introduced by this call | @@ -245,7 +245,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:112:49 | LL | want(DoubleWrapper { item: Wrapper { value: q } }); - | ---- ^ the trait `T1` is not implemented for `Q` + | ---- ^ the trait `T1` is not implemented for `Q`, which is required by `DoubleWrapper: T1` | | | required by a bound introduced by this call | @@ -270,7 +270,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:115:88 | LL | want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } }); - | ---- required by a bound introduced by this call ^ the trait `T1` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T1` is not implemented for `Q`, which is required by `DoubleWrapper>: T1` | note: required for `DoubleWrapper` to implement `T1` --> $DIR/blame-trait-error-spans-on-exprs.rs:72:13 @@ -295,7 +295,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:119:27 | LL | want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } }); - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q` + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | | | required by a bound introduced by this call | @@ -327,7 +327,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:122:35 | LL | want(Two { a: Two { a: (), b: q }, b: () }); - | ---- ^ the trait `T1` is not implemented for `Q` + | ---- ^ the trait `T1` is not implemented for `Q`, which is required by `Two, ()>: T1` | | | required by a bound introduced by this call | @@ -354,7 +354,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied LL | want( | ---- required by a bound introduced by this call LL | Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () }, - | ^ the trait `T1` is not implemented for `Q` + | ^ the trait `T1` is not implemented for `Q`, which is required by `Two, ()>>, ()>: T1` | note: required for `Two, ()>` to implement `T1` --> $DIR/blame-trait-error-spans-on-exprs.rs:66:19 @@ -379,7 +379,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:133:44 | LL | want(&Burrito { spicy: false, filling: q }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&Burrito: T1` | | | required by a bound introduced by this call | diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr index a79caced111bb..0ae33e25b811e 100644 --- a/tests/ui/extern/extern-types-unsized.stderr +++ b/tests/ui/extern/extern-types-unsized.stderr @@ -21,7 +21,7 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim LL | assert_sized::(); | ^^^ doesn't have a size known at compile-time | - = help: within `Foo`, the trait `Sized` is not implemented for `A` + = help: within `Foo`, the trait `Sized` is not implemented for `A`, which is required by `Foo: Sized` note: required because it appears within the type `Foo` --> $DIR/extern-types-unsized.rs:9:8 | @@ -43,7 +43,7 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim LL | assert_sized::>(); | ^^^^^^ doesn't have a size known at compile-time | - = help: within `Bar`, the trait `Sized` is not implemented for `A` + = help: within `Bar`, the trait `Sized` is not implemented for `A`, which is required by `Bar: Sized` note: required because it appears within the type `Bar` --> $DIR/extern-types-unsized.rs:14:8 | @@ -65,7 +65,7 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim LL | assert_sized::>>(); | ^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `Bar>`, the trait `Sized` is not implemented for `A` + = help: within `Bar>`, the trait `Sized` is not implemented for `A`, which is required by `Bar>: Sized` note: required because it appears within the type `Bar` --> $DIR/extern-types-unsized.rs:14:8 | diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr index 1b87ebd9f20ce..7fc726409ce40 100644 --- a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -94,7 +94,7 @@ error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at LL | fn unsized_local() where Dst: Sized { | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)` + = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)`, which is required by `Dst<(dyn A + 'static)>: Sized` note: required because it appears within the type `Dst<(dyn A + 'static)>` --> $DIR/feature-gate-trivial_bounds.rs:48:8 | diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr index c0650ff17c5ed..58531c61bbe80 100644 --- a/tests/ui/fmt/ifmt-unimpl.stderr +++ b/tests/ui/fmt/ifmt-unimpl.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: UpperHex` is not satisfied --> $DIR/ifmt-unimpl.rs:2:21 | LL | format!("{:X}", "3"); - | ---- ^^^ the trait `UpperHex` is not implemented for `str` + | ---- ^^^ the trait `UpperHex` is not implemented for `str`, which is required by `&str: UpperHex` | | | required by a bound introduced by this call | diff --git a/tests/ui/fmt/send-sync.stderr b/tests/ui/fmt/send-sync.stderr index 6c9c7941eb339..aa377553c5041 100644 --- a/tests/ui/fmt/send-sync.stderr +++ b/tests/ui/fmt/send-sync.stderr @@ -6,7 +6,7 @@ LL | send(format_args!("{:?}", c)); | | | required by a bound introduced by this call | - = help: within `[core::fmt::rt::Argument<'_>]`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque` + = help: within `[core::fmt::rt::Argument<'_>]`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`, which is required by `Arguments<'_>: Send` = note: required because it appears within the type `&core::fmt::rt::Opaque` note: required because it appears within the type `core::fmt::rt::Argument<'_>` --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL @@ -28,7 +28,7 @@ LL | sync(format_args!("{:?}", c)); | | | required by a bound introduced by this call | - = help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque` + = help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`, which is required by `Arguments<'_>: Sync` = note: required because it appears within the type `&core::fmt::rt::Opaque` note: required because it appears within the type `core::fmt::rt::Argument<'_>` --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL diff --git a/tests/ui/for/for-c-in-str.stderr b/tests/ui/for/for-c-in-str.stderr index 475cf8c887491..2544df646299b 100644 --- a/tests/ui/for/for-c-in-str.stderr +++ b/tests/ui/for/for-c-in-str.stderr @@ -4,7 +4,7 @@ error[E0277]: `&str` is not an iterator LL | for c in "asdf" { | ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` | - = help: the trait `Iterator` is not implemented for `&str` + = help: the trait `Iterator` is not implemented for `&str`, which is required by `&str: IntoIterator` = note: required for `&str` to implement `IntoIterator` error: aborting due to 1 previous error diff --git a/tests/ui/for/for-loop-bogosity.stderr b/tests/ui/for/for-loop-bogosity.stderr index 194a2fa08ceab..143e4a4efd1f0 100644 --- a/tests/ui/for/for-loop-bogosity.stderr +++ b/tests/ui/for/for-loop-bogosity.stderr @@ -4,7 +4,7 @@ error[E0277]: `MyStruct` is not an iterator LL | for x in bogus { | ^^^^^ `MyStruct` is not an iterator | - = help: the trait `Iterator` is not implemented for `MyStruct` + = help: the trait `Iterator` is not implemented for `MyStruct`, which is required by `MyStruct: IntoIterator` = note: required for `MyStruct` to implement `IntoIterator` error: aborting due to 1 previous error diff --git a/tests/ui/function-pointer/unsized-ret.stderr b/tests/ui/function-pointer/unsized-ret.stderr index 66116273ff4d6..81d603f4b20e3 100644 --- a/tests/ui/function-pointer/unsized-ret.stderr +++ b/tests/ui/function-pointer/unsized-ret.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | foo:: str, _>(None, ()); | ^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> str`, the trait `Sized` is not implemented for `str` + = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`, which is required by `fn() -> str: Fn<_>` = note: required because it appears within the type `fn() -> str` note: required by a bound in `foo` --> $DIR/unsized-ret.rs:5:11 @@ -18,7 +18,7 @@ error[E0277]: the size for values of type `(dyn std::fmt::Display + 'a)` cannot LL | foo:: fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)` + = help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)`, which is required by `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a): Fn<_>` = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)` note: required by a bound in `foo` --> $DIR/unsized-ret.rs:5:11 diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr index 685c2794967b2..314a5509da8bc 100644 --- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `::Bar<()>: Eq` is not satisfied --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:30 | LL | type Bar: Baz = i32; - | ^^^ the trait `Eq` is not implemented for `::Bar<()>` + | ^^^ the trait `Eq` is not implemented for `::Bar<()>`, which is required by `i32: Baz` | note: required for `i32` to implement `Baz` --> $DIR/assume-gat-normalization-for-nested-goals.rs:13:23 diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 261070d1db4bf..c3b119e21443d 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -25,7 +25,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/impl_bounds.rs:18:33 | LL | type C = String where Self: Copy; - | ^^^^ the trait `Copy` is not implemented for `T` + | ^^^^ the trait `Copy` is not implemented for `T`, which is required by `Fooy: Copy` | note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 @@ -50,7 +50,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/impl_bounds.rs:20:24 | LL | fn d() where Self: Copy {} - | ^^^^ the trait `Copy` is not implemented for `T` + | ^^^^ the trait `Copy` is not implemented for `T`, which is required by `Fooy: Copy` | note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 diff --git a/tests/ui/generic-associated-types/issue-101020.stderr b/tests/ui/generic-associated-types/issue-101020.stderr index 9c3753c2d1809..7faab4e527463 100644 --- a/tests/ui/generic-associated-types/issue-101020.stderr +++ b/tests/ui/generic-associated-types/issue-101020.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satis --> $DIR/issue-101020.rs:31:22 | LL | (&mut EmptyIter).consume(()); - | ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()` + | ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`, which is required by `for<'a> &'a mut (): FuncInput<'a, &'a mut ()>` | help: this trait has no implementations, consider adding one --> $DIR/issue-101020.rs:28:1 diff --git a/tests/ui/generic-associated-types/issue-74824.stderr b/tests/ui/generic-associated-types/issue-74824.stderr index e5638d90ee8e7..942d9583be1b1 100644 --- a/tests/ui/generic-associated-types/issue-74824.stderr +++ b/tests/ui/generic-associated-types/issue-74824.stderr @@ -14,7 +14,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied --> $DIR/issue-74824.rs:6:26 | LL | type Copy: Copy = Box; - | ^^^^^^ the trait `Clone` is not implemented for `T` + | ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `::Copy: Copy` | = note: required for `Box` to implement `Clone` = note: required for `::Copy` to implement `Copy` diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr index 7fe803550bddf..761fd9045a13a 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied --> $DIR/issue-89118.rs:19:8 | LL | C: StackContext, - | ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`, which is required by `for<'a> Ctx<()>: BufferUdpStateContext<&'a ()>` | help: this trait has no implementations, consider adding one --> $DIR/issue-89118.rs:1:1 @@ -29,7 +29,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied --> $DIR/issue-89118.rs:29:9 | LL | impl EthernetWorker {} - | ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`, which is required by `for<'a> Ctx<()>: BufferUdpStateContext<&'a ()>` | help: this trait has no implementations, consider adding one --> $DIR/issue-89118.rs:1:1 @@ -56,7 +56,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied --> $DIR/issue-89118.rs:22:20 | LL | type Handler = Ctx; - | ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`, which is required by `for<'a> Ctx<()>: BufferUdpStateContext<&'a ()>` | help: this trait has no implementations, consider adding one --> $DIR/issue-89118.rs:1:1 diff --git a/tests/ui/impl-trait/auto-trait-leak2.stderr b/tests/ui/impl-trait/auto-trait-leak2.stderr index 52fa28145d664..1fcde0372fc96 100644 --- a/tests/ui/impl-trait/auto-trait-leak2.stderr +++ b/tests/ui/impl-trait/auto-trait-leak2.stderr @@ -9,7 +9,7 @@ LL | send(before()); | | | required by a bound introduced by this call | - = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>` + = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>`, which is required by `impl Fn(i32): Send` note: required because it's used within this closure --> $DIR/auto-trait-leak2.rs:10:5 | @@ -37,7 +37,7 @@ LL | send(after()); LL | fn after() -> impl Fn(i32) { | ------------ within this `impl Fn(i32)` | - = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>` + = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>`, which is required by `impl Fn(i32): Send` note: required because it's used within this closure --> $DIR/auto-trait-leak2.rs:38:5 | diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr index 9cc199d1e0ec6..f25269ca03207 100644 --- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr +++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr @@ -16,7 +16,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) } | | | doesn't have a size known at compile-time | - = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` + = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`, which is required by `(usize, (dyn Trait + 'static)): Sized` = note: required because it appears within the type `(usize, (dyn Trait + 'static))` = note: the return type of a function must have a statically known size @@ -38,7 +38,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } | | | doesn't have a size known at compile-time | - = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` + = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`, which is required by `(usize, (dyn Trait + 'static)): Sized` = note: required because it appears within the type `(usize, (dyn Trait + 'static))` = note: the return type of a function must have a statically known size diff --git a/tests/ui/impl-trait/impl_trait_projections.stderr b/tests/ui/impl-trait/impl_trait_projections.stderr index 700aff36aa509..421afc96eed07 100644 --- a/tests/ui/impl-trait/impl_trait_projections.stderr +++ b/tests/ui/impl-trait/impl_trait_projections.stderr @@ -32,7 +32,7 @@ error[E0277]: the trait bound `impl Debug: Step` is not satisfied --> $DIR/impl_trait_projections.rs:26:8 | LL | -> <::std::ops::Range as Iterator>::Item - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Step` is not implemented for `impl Debug` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Step` is not implemented for `impl Debug`, which is required by `std::ops::Range: Iterator` | = help: the following other types implement trait `Step`: char @@ -53,7 +53,7 @@ LL | / { LL | | LL | | (1i32..100).next().unwrap() LL | | } - | |_^ the trait `Step` is not implemented for `impl Debug` + | |_^ the trait `Step` is not implemented for `impl Debug`, which is required by `std::ops::Range: Iterator` | = help: the following other types implement trait `Step`: char diff --git a/tests/ui/impl-trait/issue-55872-1.stderr b/tests/ui/impl-trait/issue-55872-1.stderr index 8912cce1b4b5b..0c86824e62217 100644 --- a/tests/ui/impl-trait/issue-55872-1.stderr +++ b/tests/ui/impl-trait/issue-55872-1.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)` --> $DIR/issue-55872-1.rs:12:29 | LL | fn foo() -> Self::E { - | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S` + | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`, which is required by `(S, T): Copy` | = note: required because it appears within the type `(S, T)` help: consider further restricting this bound @@ -23,7 +23,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)` --> $DIR/issue-55872-1.rs:12:29 | LL | fn foo() -> Self::E { - | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T` + | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`, which is required by `(S, T): Copy` | = note: required because it appears within the type `(S, T)` help: consider further restricting this bound diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr index 31c3e0c901365..83d1347aff431 100644 --- a/tests/ui/impl-trait/nested_impl_trait.stderr +++ b/tests/ui/impl-trait/nested_impl_trait.stderr @@ -46,7 +46,7 @@ error[E0277]: the trait bound `impl Debug: From>` is not satisfie --> $DIR/nested_impl_trait.rs:6:46 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug`, which is required by `impl Into: Into` | = help: the trait `Into` is implemented for `T` = note: required for `impl Into` to implement `Into` @@ -55,7 +55,7 @@ error[E0277]: the trait bound `impl Debug: From>` is not satisfie --> $DIR/nested_impl_trait.rs:19:34 | LL | fn bad(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug`, which is required by `impl Into: Into` | = help: the trait `Into` is implemented for `T` = note: required for `impl Into` to implement `Into` diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr index 4ec28ddf87171..1291bf2a4611e 100644 --- a/tests/ui/indexing/index-help.stderr +++ b/tests/ui/indexing/index-help.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `i32` LL | x[0i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`, which is required by `Vec<{integer}>: Index<_>` = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `Vec<{integer}>` to implement `Index` diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr index 3041c2c99a108..38e7881dcc675 100644 --- a/tests/ui/indexing/indexing-requires-a-uint.stderr +++ b/tests/ui/indexing/indexing-requires-a-uint.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `u8` LL | [0][0u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`, which is required by `[{integer}; 1]: Index<_>` = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `[{integer}]` to implement `Index` diff --git a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr index 4cced22789f74..df4d7cc0683d5 100644 --- a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr +++ b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `String: Borrow<&str>` is not satisfied --> $DIR/point-at-index-for-obligation-failure.rs:5:9 | LL | &s - | ^^ the trait `Borrow<&str>` is not implemented for `String` + | ^^ the trait `Borrow<&str>` is not implemented for `String`, which is required by `HashMap: Index<&_>` | = help: the trait `Borrow` is implemented for `String` = help: for that trait implementation, expected `str`, found `&str` diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr index 97e658617cf03..ad2c3af424be8 100644 --- a/tests/ui/integral-indexing.stderr +++ b/tests/ui/integral-indexing.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `u8` LL | v[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` + = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`, which is required by `Vec: Index<_>` = help: the trait `SliceIndex<[isize]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `Vec` to implement `Index` @@ -15,7 +15,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `i8` LL | v[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` + = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`, which is required by `Vec: Index<_>` = help: the trait `SliceIndex<[isize]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i8` = note: required for `Vec` to implement `Index` @@ -26,7 +26,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `u32` LL | v[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` + = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`, which is required by `Vec: Index<_>` = help: the trait `SliceIndex<[isize]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u32` = note: required for `Vec` to implement `Index` @@ -37,7 +37,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `i32` LL | v[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` + = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`, which is required by `Vec: Index<_>` = help: the trait `SliceIndex<[isize]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `Vec` to implement `Index` @@ -48,7 +48,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `u8` LL | s.as_bytes()[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` + = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`, which is required by `[u8]: Index<_>` = help: the trait `SliceIndex<[u8]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `[u8]` to implement `Index` @@ -59,7 +59,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `i8` LL | s.as_bytes()[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` + = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`, which is required by `[u8]: Index<_>` = help: the trait `SliceIndex<[u8]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i8` = note: required for `[u8]` to implement `Index` @@ -70,7 +70,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `u32` LL | s.as_bytes()[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` + = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`, which is required by `[u8]: Index<_>` = help: the trait `SliceIndex<[u8]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u32` = note: required for `[u8]` to implement `Index` @@ -81,7 +81,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `i32` LL | s.as_bytes()[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` + = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`, which is required by `[u8]: Index<_>` = help: the trait `SliceIndex<[u8]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `[u8]` to implement `Index` diff --git a/tests/ui/interior-mutability/interior-mutability.stderr b/tests/ui/interior-mutability/interior-mutability.stderr index 36686565e2e3a..7b08a6454052d 100644 --- a/tests/ui/interior-mutability/interior-mutability.stderr +++ b/tests/ui/interior-mutability/interior-mutability.stderr @@ -6,7 +6,7 @@ LL | catch_unwind(|| { x.set(23); }); | | | required by a bound introduced by this call | - = help: within `Cell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `Cell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `{closure@$DIR/interior-mutability.rs:5:18: 5:20}: UnwindSafe` note: required because it appears within the type `Cell` --> $SRC_DIR/core/src/cell.rs:LL:COL = note: required for `&Cell` to implement `UnwindSafe` diff --git a/tests/ui/issues/issue-21763.stderr b/tests/ui/issues/issue-21763.stderr index 135b705eeeff2..aa4938a0c0b3a 100644 --- a/tests/ui/issues/issue-21763.stderr +++ b/tests/ui/issues/issue-21763.stderr @@ -4,7 +4,7 @@ error[E0277]: `Rc<()>` cannot be sent between threads safely LL | foo::, Rc<()>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely | - = help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>` + = help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>`, which is required by `HashMap, Rc<()>>: Send` = note: required because it appears within the type `(Rc<()>, Rc<()>)` = note: required for `hashbrown::raw::RawTable<(Rc<()>, Rc<()>)>` to implement `Send` note: required because it appears within the type `hashbrown::map::HashMap, Rc<()>, RandomState>` diff --git a/tests/ui/issues/issue-22872.stderr b/tests/ui/issues/issue-22872.stderr index 6ff710b113325..03e5393da4882 100644 --- a/tests/ui/issues/issue-22872.stderr +++ b/tests/ui/issues/issue-22872.stderr @@ -4,7 +4,7 @@ error[E0277]: `

>::Item` is not an iterator LL | let _: Box Wrap<'b>> = Box::new(Wrapper(process)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `

>::Item` is not an iterator | - = help: the trait `Iterator` is not implemented for `

>::Item` + = help: the trait `Iterator` is not implemented for `

>::Item`, which is required by `for<'b> Wrapper

: Wrap<'b>` note: required for `Wrapper

` to implement `for<'b> Wrap<'b>` --> $DIR/issue-22872.rs:7:13 | diff --git a/tests/ui/issues/issue-40827.stderr b/tests/ui/issues/issue-40827.stderr index 7f5c578ae4fff..44ae90cbc0ff8 100644 --- a/tests/ui/issues/issue-40827.stderr +++ b/tests/ui/issues/issue-40827.stderr @@ -6,7 +6,7 @@ LL | f(Foo(Arc::new(Bar::B(None)))); | | | required by a bound introduced by this call | - = help: within `Bar`, the trait `Sync` is not implemented for `Rc` + = help: within `Bar`, the trait `Sync` is not implemented for `Rc`, which is required by `Foo: Send` note: required because it appears within the type `Bar` --> $DIR/issue-40827.rs:6:6 | @@ -32,7 +32,7 @@ LL | f(Foo(Arc::new(Bar::B(None)))); | | | required by a bound introduced by this call | - = help: within `Bar`, the trait `Send` is not implemented for `Rc` + = help: within `Bar`, the trait `Send` is not implemented for `Rc`, which is required by `Foo: Send` note: required because it appears within the type `Bar` --> $DIR/issue-40827.rs:6:6 | diff --git a/tests/ui/issues/issue-7364.stderr b/tests/ui/issues/issue-7364.stderr index 7371e2105de8d..15cb2d875c13c 100644 --- a/tests/ui/issues/issue-7364.stderr +++ b/tests/ui/issues/issue-7364.stderr @@ -4,7 +4,7 @@ error[E0277]: `RefCell` cannot be shared between threads safely LL | static boxed: Box> = Box::new(RefCell::new(0)); | ^^^^^^^^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `Box>: Sync` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Unique>` to implement `Sync` note: required because it appears within the type `Box>` diff --git a/tests/ui/iterators/float_iterator_hint.stderr b/tests/ui/iterators/float_iterator_hint.stderr index c3cb00c3c684c..29319b9400f03 100644 --- a/tests/ui/iterators/float_iterator_hint.stderr +++ b/tests/ui/iterators/float_iterator_hint.stderr @@ -4,7 +4,7 @@ error[E0277]: `{float}` is not an iterator LL | for i in 0.2 { | ^^^ `{float}` is not an iterator | - = help: the trait `Iterator` is not implemented for `{float}` + = help: the trait `Iterator` is not implemented for `{float}`, which is required by `{float}: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `{float}` to implement `IntoIterator` diff --git a/tests/ui/iterators/integral.stderr b/tests/ui/iterators/integral.stderr index c142fec8da0f6..74bbe28d6b719 100644 --- a/tests/ui/iterators/integral.stderr +++ b/tests/ui/iterators/integral.stderr @@ -4,7 +4,7 @@ error[E0277]: `{integer}` is not an iterator LL | for _ in 42 {} | ^^ `{integer}` is not an iterator | - = help: the trait `Iterator` is not implemented for `{integer}` + = help: the trait `Iterator` is not implemented for `{integer}`, which is required by `{integer}: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `{integer}` to implement `IntoIterator` @@ -14,7 +14,7 @@ error[E0277]: `u8` is not an iterator LL | for _ in 42 as u8 {} | ^^^^^^^^ `u8` is not an iterator | - = help: the trait `Iterator` is not implemented for `u8` + = help: the trait `Iterator` is not implemented for `u8`, which is required by `u8: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `u8` to implement `IntoIterator` @@ -24,7 +24,7 @@ error[E0277]: `i8` is not an iterator LL | for _ in 42 as i8 {} | ^^^^^^^^ `i8` is not an iterator | - = help: the trait `Iterator` is not implemented for `i8` + = help: the trait `Iterator` is not implemented for `i8`, which is required by `i8: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `i8` to implement `IntoIterator` @@ -34,7 +34,7 @@ error[E0277]: `u16` is not an iterator LL | for _ in 42 as u16 {} | ^^^^^^^^^ `u16` is not an iterator | - = help: the trait `Iterator` is not implemented for `u16` + = help: the trait `Iterator` is not implemented for `u16`, which is required by `u16: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `u16` to implement `IntoIterator` @@ -44,7 +44,7 @@ error[E0277]: `i16` is not an iterator LL | for _ in 42 as i16 {} | ^^^^^^^^^ `i16` is not an iterator | - = help: the trait `Iterator` is not implemented for `i16` + = help: the trait `Iterator` is not implemented for `i16`, which is required by `i16: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `i16` to implement `IntoIterator` @@ -54,7 +54,7 @@ error[E0277]: `u32` is not an iterator LL | for _ in 42 as u32 {} | ^^^^^^^^^ `u32` is not an iterator | - = help: the trait `Iterator` is not implemented for `u32` + = help: the trait `Iterator` is not implemented for `u32`, which is required by `u32: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `u32` to implement `IntoIterator` @@ -64,7 +64,7 @@ error[E0277]: `i32` is not an iterator LL | for _ in 42 as i32 {} | ^^^^^^^^^ `i32` is not an iterator | - = help: the trait `Iterator` is not implemented for `i32` + = help: the trait `Iterator` is not implemented for `i32`, which is required by `i32: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `i32` to implement `IntoIterator` @@ -74,7 +74,7 @@ error[E0277]: `u64` is not an iterator LL | for _ in 42 as u64 {} | ^^^^^^^^^ `u64` is not an iterator | - = help: the trait `Iterator` is not implemented for `u64` + = help: the trait `Iterator` is not implemented for `u64`, which is required by `u64: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `u64` to implement `IntoIterator` @@ -84,7 +84,7 @@ error[E0277]: `i64` is not an iterator LL | for _ in 42 as i64 {} | ^^^^^^^^^ `i64` is not an iterator | - = help: the trait `Iterator` is not implemented for `i64` + = help: the trait `Iterator` is not implemented for `i64`, which is required by `i64: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `i64` to implement `IntoIterator` @@ -94,7 +94,7 @@ error[E0277]: `usize` is not an iterator LL | for _ in 42 as usize {} | ^^^^^^^^^^^ `usize` is not an iterator | - = help: the trait `Iterator` is not implemented for `usize` + = help: the trait `Iterator` is not implemented for `usize`, which is required by `usize: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `usize` to implement `IntoIterator` @@ -104,7 +104,7 @@ error[E0277]: `isize` is not an iterator LL | for _ in 42 as isize {} | ^^^^^^^^^^^ `isize` is not an iterator | - = help: the trait `Iterator` is not implemented for `isize` + = help: the trait `Iterator` is not implemented for `isize`, which is required by `isize: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `isize` to implement `IntoIterator` @@ -114,7 +114,7 @@ error[E0277]: `{float}` is not an iterator LL | for _ in 42.0 {} | ^^^^ `{float}` is not an iterator | - = help: the trait `Iterator` is not implemented for `{float}` + = help: the trait `Iterator` is not implemented for `{float}`, which is required by `{float}: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `{float}` to implement `IntoIterator` diff --git a/tests/ui/iterators/issue-28098.stderr b/tests/ui/iterators/issue-28098.stderr index a724f03ad4af1..3cb1b2f72700c 100644 --- a/tests/ui/iterators/issue-28098.stderr +++ b/tests/ui/iterators/issue-28098.stderr @@ -14,7 +14,7 @@ error[E0277]: `bool` is not an iterator LL | for _ in false {} | ^^^^^ `bool` is not an iterator | - = help: the trait `Iterator` is not implemented for `bool` + = help: the trait `Iterator` is not implemented for `bool`, which is required by `bool: IntoIterator` = note: required for `bool` to implement `IntoIterator` error[E0277]: `()` is not an iterator @@ -61,7 +61,7 @@ error[E0277]: `bool` is not an iterator LL | for _ in false {} | ^^^^^ `bool` is not an iterator | - = help: the trait `Iterator` is not implemented for `bool` + = help: the trait `Iterator` is not implemented for `bool`, which is required by `bool: IntoIterator` = note: required for `bool` to implement `IntoIterator` error[E0277]: `()` is not an iterator diff --git a/tests/ui/iterators/ranges.stderr b/tests/ui/iterators/ranges.stderr index b9fbcd5304b1f..a5d43ecbb6331 100644 --- a/tests/ui/iterators/ranges.stderr +++ b/tests/ui/iterators/ranges.stderr @@ -4,7 +4,7 @@ error[E0277]: `RangeTo<{integer}>` is not an iterator LL | for _ in ..10 {} | ^^^^ if you meant to iterate until a value, add a starting value | - = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>` + = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>`, which is required by `RangeTo<{integer}>: IntoIterator` = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end` = note: required for `RangeTo<{integer}>` to implement `IntoIterator` @@ -14,7 +14,7 @@ error[E0277]: `RangeToInclusive<{integer}>` is not an iterator LL | for _ in ..=10 {} | ^^^^^ if you meant to iterate until a value (including it), add a starting value | - = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>` + = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>`, which is required by `RangeToInclusive<{integer}>: IntoIterator` = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end` = note: required for `RangeToInclusive<{integer}>` to implement `IntoIterator` diff --git a/tests/ui/iterators/string.stderr b/tests/ui/iterators/string.stderr index ddfe0169b848f..29f560677c07d 100644 --- a/tests/ui/iterators/string.stderr +++ b/tests/ui/iterators/string.stderr @@ -4,7 +4,7 @@ error[E0277]: `String` is not an iterator LL | for _ in "".to_owned() {} | ^^^^^^^^^^^^^ `String` is not an iterator; try calling `.chars()` or `.bytes()` | - = help: the trait `Iterator` is not implemented for `String` + = help: the trait `Iterator` is not implemented for `String`, which is required by `String: IntoIterator` = note: required for `String` to implement `IntoIterator` error[E0277]: `&str` is not an iterator @@ -13,7 +13,7 @@ error[E0277]: `&str` is not an iterator LL | for _ in "" {} | ^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` | - = help: the trait `Iterator` is not implemented for `&str` + = help: the trait `Iterator` is not implemented for `&str`, which is required by `&str: IntoIterator` = note: required for `&str` to implement `IntoIterator` error: aborting due to 2 previous errors diff --git a/tests/ui/kindck/kindck-impl-type-params-2.stderr b/tests/ui/kindck/kindck-impl-type-params-2.stderr index a51232090adbb..46c0bda95352f 100644 --- a/tests/ui/kindck/kindck-impl-type-params-2.stderr +++ b/tests/ui/kindck/kindck-impl-type-params-2.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied --> $DIR/kindck-impl-type-params-2.rs:13:16 | LL | take_param(&x); - | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo` | | | required by a bound introduced by this call | diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr index 53c1940491f84..fe03ac422d2d2 100644 --- a/tests/ui/kindck/kindck-impl-type-params.stderr +++ b/tests/ui/kindck/kindck-impl-type-params.stderr @@ -21,7 +21,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:16:13 | LL | let a = &t as &dyn Gettable; - | ^^ the trait `Copy` is not implemented for `T` + | ^^ the trait `Copy` is not implemented for `T`, which is required by `S: Gettable` | note: required for `S` to implement `Gettable` --> $DIR/kindck-impl-type-params.rs:12:32 @@ -59,7 +59,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:23:31 | LL | let a: &dyn Gettable = &t; - | ^^ the trait `Copy` is not implemented for `T` + | ^^ the trait `Copy` is not implemented for `T`, which is required by `S: Gettable` | note: required for `S` to implement `Gettable` --> $DIR/kindck-impl-type-params.rs:12:32 @@ -78,7 +78,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:35:13 | LL | let a = t as Box>; - | ^ the trait `Copy` is not implemented for `String` + | ^ the trait `Copy` is not implemented for `String`, which is required by `S: Gettable` | = help: the trait `Gettable` is implemented for `S` note: required for `S` to implement `Gettable` @@ -94,7 +94,7 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:43:37 | LL | let a: Box> = t; - | ^ the trait `Copy` is not implemented for `Foo` + | ^ the trait `Copy` is not implemented for `Foo`, which is required by `S: Gettable` | = help: the trait `Gettable` is implemented for `S` note: required for `S` to implement `Gettable` diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr index 2949517655640..a85815d8cc498 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied --> $DIR/kindck-inherited-copy-bound.rs:21:16 | LL | take_param(&x); - | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo` | | | required by a bound introduced by this call | diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr index 3e164ebf51439..687660fe7eea3 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied --> $DIR/kindck-inherited-copy-bound.rs:21:16 | LL | take_param(&x); - | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo` | | | required by a bound introduced by this call | diff --git a/tests/ui/kindck/kindck-nonsendable-1.stderr b/tests/ui/kindck/kindck-nonsendable-1.stderr index 8bb784d1d4966..8cc931bc48ed3 100644 --- a/tests/ui/kindck/kindck-nonsendable-1.stderr +++ b/tests/ui/kindck/kindck-nonsendable-1.stderr @@ -8,7 +8,7 @@ LL | bar(move|| foo(x)); | | within this `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}` | required by a bound introduced by this call | - = help: within `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}`, the trait `Send` is not implemented for `Rc` + = help: within `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}`, the trait `Send` is not implemented for `Rc`, which is required by `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}: Send` note: required because it's used within this closure --> $DIR/kindck-nonsendable-1.rs:9:9 | diff --git a/tests/ui/kindck/kindck-send-object.stderr b/tests/ui/kindck/kindck-send-object.stderr index 284d5dcec3107..0fc9cb14c7d46 100644 --- a/tests/ui/kindck/kindck-send-object.stderr +++ b/tests/ui/kindck/kindck-send-object.stderr @@ -4,7 +4,7 @@ error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely LL | assert_send::<&'static (dyn Dummy + 'static)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)` + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object.rs:5:18 @@ -18,7 +18,7 @@ error[E0277]: `dyn Dummy` cannot be sent between threads safely LL | assert_send::>(); | ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `dyn Dummy` + = help: the trait `Send` is not implemented for `dyn Dummy`, which is required by `Box: Send` = note: required for `Unique` to implement `Send` note: required because it appears within the type `Box` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr index c0d516e3f626b..771c54dce0d10 100644 --- a/tests/ui/kindck/kindck-send-object1.stderr +++ b/tests/ui/kindck/kindck-send-object1.stderr @@ -4,7 +4,7 @@ error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely LL | assert_send::<&'a dyn Dummy>(); | ^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)` + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send` = note: required for `&'a (dyn Dummy + 'a)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object1.rs:5:18 @@ -18,7 +18,7 @@ error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `(dyn Dummy + 'a)` + = help: the trait `Send` is not implemented for `(dyn Dummy + 'a)`, which is required by `Box<(dyn Dummy + 'a)>: Send` = note: required for `Unique<(dyn Dummy + 'a)>` to implement `Send` note: required because it appears within the type `Box<(dyn Dummy + 'a)>` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/ui/kindck/kindck-send-object2.stderr b/tests/ui/kindck/kindck-send-object2.stderr index 6b8df60227f55..758a517e12885 100644 --- a/tests/ui/kindck/kindck-send-object2.stderr +++ b/tests/ui/kindck/kindck-send-object2.stderr @@ -4,7 +4,7 @@ error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely LL | assert_send::<&'static dyn Dummy>(); | ^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)` + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object2.rs:3:18 @@ -18,7 +18,7 @@ error[E0277]: `dyn Dummy` cannot be sent between threads safely LL | assert_send::>(); | ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `dyn Dummy` + = help: the trait `Send` is not implemented for `dyn Dummy`, which is required by `Box: Send` = note: required for `Unique` to implement `Send` note: required because it appears within the type `Box` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/ui/kindck/kindck-send-owned.stderr b/tests/ui/kindck/kindck-send-owned.stderr index 860a9391bbb08..4bc0212089b11 100644 --- a/tests/ui/kindck/kindck-send-owned.stderr +++ b/tests/ui/kindck/kindck-send-owned.stderr @@ -4,7 +4,7 @@ error[E0277]: `*mut u8` cannot be sent between threads safely LL | assert_send::>(); | ^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `*mut u8` + = help: the trait `Send` is not implemented for `*mut u8`, which is required by `Box<*mut u8>: Send` = note: required for `Unique<*mut u8>` to implement `Send` note: required because it appears within the type `Box<*mut u8>` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/ui/modules/issue-107649.stderr b/tests/ui/modules/issue-107649.stderr index 0d203c1aacba4..d5405c6576a8b 100644 --- a/tests/ui/modules/issue-107649.stderr +++ b/tests/ui/modules/issue-107649.stderr @@ -4,7 +4,7 @@ error[E0277]: `Dummy` doesn't implement `Debug` 105 | dbg!(lib::Dummy); | ^^^^^^^^^^^^^^^^ `Dummy` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `Dummy` + = help: the trait `Debug` is not implemented for `Dummy`, which is required by `&Dummy: Debug` = note: add `#[derive(Debug)]` to `Dummy` or manually `impl Debug for Dummy` = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Dummy` with `#[derive(Debug)]` diff --git a/tests/ui/mut/mutable-enum-indirect.stderr b/tests/ui/mut/mutable-enum-indirect.stderr index 0b7783b3318b1..d7af327df5a33 100644 --- a/tests/ui/mut/mutable-enum-indirect.stderr +++ b/tests/ui/mut/mutable-enum-indirect.stderr @@ -6,7 +6,7 @@ LL | bar(&x); | | | required by a bound introduced by this call | - = help: within `&Foo`, the trait `Sync` is not implemented for `NoSync` + = help: within `&Foo`, the trait `Sync` is not implemented for `NoSync`, which is required by `&Foo: Sync` note: required because it appears within the type `Foo` --> $DIR/mutable-enum-indirect.rs:11:6 | diff --git a/tests/ui/no-send-res-ports.stderr b/tests/ui/no-send-res-ports.stderr index 9c30261e5cb73..c71d8ecba371c 100644 --- a/tests/ui/no-send-res-ports.stderr +++ b/tests/ui/no-send-res-ports.stderr @@ -13,7 +13,7 @@ LL | | println!("{:?}", y); LL | | }); | |_____^ `Rc<()>` cannot be sent between threads safely | - = help: within `{closure@$DIR/no-send-res-ports.rs:25:19: 25:25}`, the trait `Send` is not implemented for `Rc<()>` + = help: within `{closure@$DIR/no-send-res-ports.rs:25:19: 25:25}`, the trait `Send` is not implemented for `Rc<()>`, which is required by `{closure@$DIR/no-send-res-ports.rs:25:19: 25:25}: Send` note: required because it appears within the type `Port<()>` --> $DIR/no-send-res-ports.rs:5:8 | diff --git a/tests/ui/no_send-enum.stderr b/tests/ui/no_send-enum.stderr index 3b66c7db545e1..e24f79c7dd6aa 100644 --- a/tests/ui/no_send-enum.stderr +++ b/tests/ui/no_send-enum.stderr @@ -6,7 +6,7 @@ LL | bar(x); | | | required by a bound introduced by this call | - = help: within `Foo`, the trait `Send` is not implemented for `NoSend` + = help: within `Foo`, the trait `Send` is not implemented for `NoSend`, which is required by `Foo: Send` note: required because it appears within the type `Foo` --> $DIR/no_send-enum.rs:8:6 | diff --git a/tests/ui/no_share-enum.stderr b/tests/ui/no_share-enum.stderr index 89939216d5b16..5b6c8bf0b4fd9 100644 --- a/tests/ui/no_share-enum.stderr +++ b/tests/ui/no_share-enum.stderr @@ -6,7 +6,7 @@ LL | bar(x); | | | required by a bound introduced by this call | - = help: within `Foo`, the trait `Sync` is not implemented for `NoSync` + = help: within `Foo`, the trait `Sync` is not implemented for `NoSync`, which is required by `Foo: Sync` note: required because it appears within the type `Foo` --> $DIR/no_share-enum.rs:8:6 | diff --git a/tests/ui/not-clone-closure.stderr b/tests/ui/not-clone-closure.stderr index 783c165eeb21c..9b557b1558290 100644 --- a/tests/ui/not-clone-closure.stderr +++ b/tests/ui/not-clone-closure.stderr @@ -5,7 +5,7 @@ LL | let hello = move || { | ------- within this `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}` ... LL | let hello = hello.clone(); - | ^^^^^ within `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}`, the trait `Clone` is not implemented for `S` + | ^^^^^ within `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}`, the trait `Clone` is not implemented for `S`, which is required by `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}: Clone` | note: required because it's used within this closure --> $DIR/not-clone-closure.rs:7:17 diff --git a/tests/ui/not-panic/not-panic-safe-2.stderr b/tests/ui/not-panic/not-panic-safe-2.stderr index 0c399f15a25bb..8c4cf9c98ed61 100644 --- a/tests/ui/not-panic/not-panic-safe-2.stderr +++ b/tests/ui/not-panic/not-panic-safe-2.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a r LL | assert::>>(); | ^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `Rc>: UnwindSafe` note: required because it appears within the type `RefCell` --> $SRC_DIR/core/src/cell.rs:LL:COL = note: required for `Rc>` to implement `UnwindSafe` @@ -20,7 +20,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a LL | assert::>>(); | ^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `Rc>: UnwindSafe` note: required because it appears within the type `Cell` --> $SRC_DIR/core/src/cell.rs:LL:COL note: required because it appears within the type `RefCell` diff --git a/tests/ui/not-panic/not-panic-safe-3.stderr b/tests/ui/not-panic/not-panic-safe-3.stderr index 53028d6a3371a..2373ada63f66d 100644 --- a/tests/ui/not-panic/not-panic-safe-3.stderr +++ b/tests/ui/not-panic/not-panic-safe-3.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a r LL | assert::>>(); | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `Arc>: UnwindSafe` note: required because it appears within the type `RefCell` --> $SRC_DIR/core/src/cell.rs:LL:COL = note: required for `Arc>` to implement `UnwindSafe` @@ -20,7 +20,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a LL | assert::>>(); | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `Arc>: UnwindSafe` note: required because it appears within the type `Cell` --> $SRC_DIR/core/src/cell.rs:LL:COL note: required because it appears within the type `RefCell` diff --git a/tests/ui/not-panic/not-panic-safe-4.stderr b/tests/ui/not-panic/not-panic-safe-4.stderr index b1361cfd87ef2..d77cac8f272d0 100644 --- a/tests/ui/not-panic/not-panic-safe-4.stderr +++ b/tests/ui/not-panic/not-panic-safe-4.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a r LL | assert::<&RefCell>(); | ^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `&RefCell: UnwindSafe` note: required because it appears within the type `RefCell` --> $SRC_DIR/core/src/cell.rs:LL:COL = note: required for `&RefCell` to implement `UnwindSafe` @@ -25,7 +25,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a LL | assert::<&RefCell>(); | ^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `&RefCell: UnwindSafe` note: required because it appears within the type `Cell` --> $SRC_DIR/core/src/cell.rs:LL:COL note: required because it appears within the type `RefCell` diff --git a/tests/ui/not-panic/not-panic-safe-5.stderr b/tests/ui/not-panic/not-panic-safe-5.stderr index fbbd81d6d4c53..0de9a2cc0cd93 100644 --- a/tests/ui/not-panic/not-panic-safe-5.stderr +++ b/tests/ui/not-panic/not-panic-safe-5.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a r LL | assert::<*const UnsafeCell>(); | ^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `*const UnsafeCell: UnwindSafe` = note: required for `*const UnsafeCell` to implement `UnwindSafe` note: required by a bound in `assert` --> $DIR/not-panic-safe-5.rs:6:14 diff --git a/tests/ui/not-panic/not-panic-safe-6.stderr b/tests/ui/not-panic/not-panic-safe-6.stderr index 47f28257409eb..7714a577f8a25 100644 --- a/tests/ui/not-panic/not-panic-safe-6.stderr +++ b/tests/ui/not-panic/not-panic-safe-6.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a r LL | assert::<*mut RefCell>(); | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `*mut RefCell: UnwindSafe` note: required because it appears within the type `RefCell` --> $SRC_DIR/core/src/cell.rs:LL:COL = note: required for `*mut RefCell` to implement `UnwindSafe` @@ -20,7 +20,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a LL | assert::<*mut RefCell>(); | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `*mut RefCell: UnwindSafe` note: required because it appears within the type `Cell` --> $SRC_DIR/core/src/cell.rs:LL:COL note: required because it appears within the type `RefCell` diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr index 658678dc4ed3c..753ba809e7da1 100644 --- a/tests/ui/offset-of/offset-of-dst-field.stderr +++ b/tests/ui/offset-of/offset-of-dst-field.stderr @@ -40,7 +40,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | offset_of!(Delta, z); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]` + = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`, which is required by `Alpha: Sized` note: required because it appears within the type `Alpha` --> $DIR/offset-of-dst-field.rs:5:8 | diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr index 5e0117be5295c..c0314fa42d721 100644 --- a/tests/ui/on-unimplemented/slice-index.stderr +++ b/tests/ui/on-unimplemented/slice-index.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `[i32]` cannot be indexed by `i32` LL | x[1i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` + = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`, which is required by `[i32]: Index<_>` = help: the trait `SliceIndex<[i32]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `[i32]` to implement `Index` @@ -15,7 +15,7 @@ error[E0277]: the type `[i32]` cannot be indexed by `RangeTo` LL | x[..1i32]; | ^^^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo` + = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo`, which is required by `[i32]: Index<_>` = help: the following other types implement trait `SliceIndex`: as SliceIndex> as SliceIndex<[T]>> diff --git a/tests/ui/parser/struct-literal-in-for.stderr b/tests/ui/parser/struct-literal-in-for.stderr index 1c91eba68e399..d2ef2ad7b5ad1 100644 --- a/tests/ui/parser/struct-literal-in-for.stderr +++ b/tests/ui/parser/struct-literal-in-for.stderr @@ -23,7 +23,7 @@ LL | | x: 3 LL | | }.hi() { | |__________^ `bool` is not an iterator | - = help: the trait `Iterator` is not implemented for `bool` + = help: the trait `Iterator` is not implemented for `bool`, which is required by `bool: IntoIterator` = note: required for `bool` to implement `IntoIterator` error: aborting due to 2 previous errors diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr index 96c1ffb2f7e32..569f700cf10ba 100644 --- a/tests/ui/range/range-1.stderr +++ b/tests/ui/range/range-1.stderr @@ -8,7 +8,7 @@ error[E0277]: the trait bound `bool: Step` is not satisfied --> $DIR/range-1.rs:9:14 | LL | for i in false..true {} - | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool` + | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool`, which is required by `std::ops::Range: IntoIterator` | = help: the following other types implement trait `Step`: char diff --git a/tests/ui/recursion/recursive-requirements.stderr b/tests/ui/recursion/recursive-requirements.stderr index bb63f7cd0dce0..f5cbed0ce3475 100644 --- a/tests/ui/recursion/recursive-requirements.stderr +++ b/tests/ui/recursion/recursive-requirements.stderr @@ -4,7 +4,7 @@ error[E0277]: `*const Bar` cannot be shared between threads safely LL | let _: AssertSync = unimplemented!(); | ^^^^^^^^^^^^^^^ `*const Bar` cannot be shared between threads safely | - = help: within `Foo`, the trait `Sync` is not implemented for `*const Bar` + = help: within `Foo`, the trait `Sync` is not implemented for `*const Bar`, which is required by `Foo: Sync` note: required because it appears within the type `Foo` --> $DIR/recursive-requirements.rs:5:12 | @@ -22,7 +22,7 @@ error[E0277]: `*const Foo` cannot be shared between threads safely LL | let _: AssertSync = unimplemented!(); | ^^^^^^^^^^^^^^^ `*const Foo` cannot be shared between threads safely | - = help: within `Foo`, the trait `Sync` is not implemented for `*const Foo` + = help: within `Foo`, the trait `Sync` is not implemented for `*const Foo`, which is required by `Foo: Sync` note: required because it appears within the type `Bar` --> $DIR/recursive-requirements.rs:10:12 | diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr index 0a703367d969d..4d23922892ea9 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `f32: Termination` is not satisfied LL | #[test] | ------- in this procedural macro expansion LL | fn can_parse_zero_as_f32() -> Result { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32`, which is required by `Result: Termination` | = note: required for `Result` to implement `Termination` note: required by a bound in `assert_test_result` diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr index 7ec018a95cc72..eb6abbf80451c 100644 --- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr +++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr @@ -4,7 +4,7 @@ error[E0277]: `NotDebug` doesn't implement `Debug` LL | let _: NotDebug = dbg!(NotDebug); | ^^^^^^^^^^^^^^ `NotDebug` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `NotDebug` + = help: the trait `Debug` is not implemented for `NotDebug`, which is required by `&NotDebug: Debug` = note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug` = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `NotDebug` with `#[derive(Debug)]` diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr index 6af1d4533b7c2..99d318a793364 100644 --- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr +++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `u8: Foo` is not satisfied --> $DIR/feature-gate-do_not_recommend.rs:19:11 | LL | stuff(1u8); - | ----- ^^^ the trait `Foo` is not implemented for `u8` + | ----- ^^^ the trait `Foo` is not implemented for `u8`, which is required by `u8: Bar` | | | required by a bound introduced by this call | diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr index 37ced4cf267fe..da19ed44ce6f1 100644 --- a/tests/ui/specialization/min_specialization/issue-79224.stderr +++ b/tests/ui/specialization/min_specialization/issue-79224.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `B: Clone` is not satisfied --> $DIR/issue-79224.rs:18:29 | LL | impl Display for Cow<'_, B> { - | ^^^^^^^^^^ the trait `Clone` is not implemented for `B` + | ^^^^^^^^^^ the trait `Clone` is not implemented for `B`, which is required by `B: ToOwned` | = note: required for `B` to implement `ToOwned` help: consider further restricting this bound @@ -14,7 +14,7 @@ error[E0277]: the trait bound `B: Clone` is not satisfied --> $DIR/issue-79224.rs:20:5 | LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B`, which is required by `B: ToOwned` | = note: required for `B` to implement `ToOwned` help: consider further restricting this bound @@ -26,7 +26,7 @@ error[E0277]: the trait bound `B: Clone` is not satisfied --> $DIR/issue-79224.rs:20:13 | LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - | ^^^^ the trait `Clone` is not implemented for `B` + | ^^^^ the trait `Clone` is not implemented for `B`, which is required by `B: ToOwned` | = note: required for `B` to implement `ToOwned` help: consider further restricting this bound diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr index e8bbb8058faf3..84806cbea0dea 100644 --- a/tests/ui/str/str-idx.stderr +++ b/tests/ui/str/str-idx.stderr @@ -4,7 +4,7 @@ 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}` + = help: the trait `SliceIndex` is not implemented for `{integer}`, which is required by `str: Index<_>` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: = help: the trait `SliceIndex<[_]>` is implemented for `usize` @@ -49,7 +49,7 @@ error[E0277]: the type `str` cannot be indexed by `char` LL | let _: u8 = s['c']; | ^^^ string indices are ranges of `usize` | - = help: the trait `SliceIndex` is not implemented for `char` + = help: the trait `SliceIndex` is not implemented for `char`, which is required by `str: Index<_>` = note: required for `str` to implement `Index` error: aborting due to 4 previous errors diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr index d41f5808752c9..17a75bf8c2ae6 100644 --- a/tests/ui/str/str-mut-idx.stderr +++ b/tests/ui/str/str-mut-idx.stderr @@ -30,7 +30,7 @@ error[E0277]: the type `str` cannot be indexed by `usize` LL | s[1usize] = bot(); | ^^^^^^ string indices are ranges of `usize` | - = help: the trait `SliceIndex` is not implemented for `usize` + = help: the trait `SliceIndex` is not implemented for `usize`, which is required by `str: Index<_>` = help: the trait `SliceIndex<[_]>` is implemented for `usize` = help: for that trait implementation, expected `[_]`, found `str` = note: required for `str` to implement `Index` @@ -73,7 +73,7 @@ error[E0277]: the type `str` cannot be indexed by `char` LL | s['c']; | ^^^ string indices are ranges of `usize` | - = help: the trait `SliceIndex` is not implemented for `char` + = help: the trait `SliceIndex` is not implemented for `char`, which is required by `str: Index<_>` = note: required for `str` to implement `Index` error: aborting due to 6 previous errors diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index 680890e880ca6..6fae6e1316df0 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied --> $DIR/derive-clone-for-eq.rs:4:17 | LL | #[derive(Clone, Eq)] - | ^^ the trait `Clone` is not implemented for `T` + | ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct: PartialEq` | note: required for `Struct` to implement `PartialEq` --> $DIR/derive-clone-for-eq.rs:7:19 diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr index bffcb1af487e9..5da85a9d0619c 100644 --- a/tests/ui/suggestions/derive-macro-missing-bounds.stderr +++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr @@ -6,7 +6,7 @@ LL | #[derive(Debug)] LL | struct Outer(Inner); | ^^^^^^^^ `a::Inner` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `a::Inner` + = help: the trait `Debug` is not implemented for `a::Inner`, which is required by `&a::Inner: Debug` = note: add `#[derive(Debug)]` to `a::Inner` or manually `impl Debug for a::Inner` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `a::Inner` with `#[derive(Debug)]` @@ -25,7 +25,7 @@ error[E0277]: the trait bound `T: c::Trait` is not satisfied LL | #[derive(Debug)] | ----- in this derive macro expansion LL | struct Outer(Inner); - | ^^^^^^^^ the trait `c::Trait` is not implemented for `T` + | ^^^^^^^^ the trait `c::Trait` is not implemented for `T`, which is required by `&c::Inner: Debug` | note: required for `c::Inner` to implement `Debug` --> $DIR/derive-macro-missing-bounds.rs:34:28 @@ -49,7 +49,7 @@ error[E0277]: the trait bound `T: d::Trait` is not satisfied LL | #[derive(Debug)] | ----- in this derive macro expansion LL | struct Outer(Inner); - | ^^^^^^^^ the trait `d::Trait` is not implemented for `T` + | ^^^^^^^^ the trait `d::Trait` is not implemented for `T`, which is required by `&d::Inner: Debug` | note: required for `d::Inner` to implement `Debug` --> $DIR/derive-macro-missing-bounds.rs:49:13 @@ -71,7 +71,7 @@ error[E0277]: the trait bound `T: e::Trait` is not satisfied LL | #[derive(Debug)] | ----- in this derive macro expansion LL | struct Outer(Inner); - | ^^^^^^^^ the trait `e::Trait` is not implemented for `T` + | ^^^^^^^^ the trait `e::Trait` is not implemented for `T`, which is required by `&e::Inner: Debug` | note: required for `e::Inner` to implement `Debug` --> $DIR/derive-macro-missing-bounds.rs:64:13 @@ -93,7 +93,7 @@ error[E0277]: the trait bound `T: f::Trait` is not satisfied LL | #[derive(Debug)] | ----- in this derive macro expansion LL | struct Outer(Inner); - | ^^^^^^^^ the trait `f::Trait` is not implemented for `T` + | ^^^^^^^^ the trait `f::Trait` is not implemented for `T`, which is required by `&f::Inner: Debug` | note: required for `f::Inner` to implement `Debug` --> $DIR/derive-macro-missing-bounds.rs:79:20 diff --git a/tests/ui/suggestions/into-str.stderr b/tests/ui/suggestions/into-str.stderr index d6efc8173cb7c..d10a294c7d2dd 100644 --- a/tests/ui/suggestions/into-str.stderr +++ b/tests/ui/suggestions/into-str.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&str: From` is not satisfied --> $DIR/into-str.rs:4:9 | LL | foo(String::new()); - | --- ^^^^^^^^^^^^^ the trait `From` is not implemented for `&str` + | --- ^^^^^^^^^^^^^ the trait `From` is not implemented for `&str`, which is required by `String: Into<&str>` | | | required by a bound introduced by this call | diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr index b9b72e0e63f14..0f6bfbeec45f3 100644 --- a/tests/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied --> $DIR/issue-71394-no-from-impl.rs:8:25 | LL | let _: &[i8] = data.into(); - | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]` + | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`, which is required by `&[u8]: Into<_>` | = help: the following other types implement trait `From`: <[bool; N] as From>> diff --git a/tests/ui/suggestions/issue-88696.stderr b/tests/ui/suggestions/issue-88696.stderr index b4f0793c225ff..a8bc970e055b8 100644 --- a/tests/ui/suggestions/issue-88696.stderr +++ b/tests/ui/suggestions/issue-88696.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Result: From>` is not --> $DIR/issue-88696.rs:9:9 | LL | a().into() - | ^^^^ the trait `From>` is not implemented for `Result` + | ^^^^ the trait `From>` is not implemented for `Result`, which is required by `Result: Into<_>` | = note: required for `Result` to implement `Into>` diff --git a/tests/ui/suggestions/issue-96223.stderr b/tests/ui/suggestions/issue-96223.stderr index a54a4e7b3be4d..4a77b240f3e54 100644 --- a/tests/ui/suggestions/issue-96223.stderr +++ b/tests/ui/suggestions/issue-96223.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'de> EmptyBis<'de>: Foo<'_>` is not satisfied --> $DIR/issue-96223.rs:49:17 | LL | icey_bounds(&p); - | ----------- ^^ the trait `for<'de> Foo<'_>` is not implemented for `EmptyBis<'de>` + | ----------- ^^ the trait `for<'de> Foo<'_>` is not implemented for `EmptyBis<'de>`, which is required by `Empty: Dummy` | | | required by a bound introduced by this call | diff --git a/tests/ui/suggestions/issue-96555.stderr b/tests/ui/suggestions/issue-96555.stderr index 1a1e069f09eb4..f77681ae80faa 100644 --- a/tests/ui/suggestions/issue-96555.stderr +++ b/tests/ui/suggestions/issue-96555.stderr @@ -6,7 +6,7 @@ LL | m::f1().await; | | | this call returns `()` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` help: remove the `.await` @@ -27,7 +27,7 @@ LL | m::f2().await; | | | this call returns `()` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` help: remove the `.await` @@ -48,7 +48,7 @@ LL | m::f3().await; | | | this call returns `()` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` help: remove the `.await` diff --git a/tests/ui/suggestions/path-by-value.stderr b/tests/ui/suggestions/path-by-value.stderr index 567d9d5b9e7a4..46002d4e257e6 100644 --- a/tests/ui/suggestions/path-by-value.stderr +++ b/tests/ui/suggestions/path-by-value.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | fn f(p: Path) { } | ^ doesn't have a size known at compile-time | - = help: within `Path`, the trait `Sized` is not implemented for `[u8]` + = help: within `Path`, the trait `Sized` is not implemented for `[u8]`, which is required by `Path: Sized` note: required because it appears within the type `Path` --> $SRC_DIR/std/src/path.rs:LL:COL = help: unsized fn params are gated as an unstable feature diff --git a/tests/ui/suggestions/path-display.stderr b/tests/ui/suggestions/path-display.stderr index 46d0b35825bca..f9159c450301b 100644 --- a/tests/ui/suggestions/path-display.stderr +++ b/tests/ui/suggestions/path-display.stderr @@ -4,7 +4,7 @@ error[E0277]: `Path` doesn't implement `std::fmt::Display` LL | println!("{}", path); | ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it | - = help: the trait `std::fmt::Display` is not implemented for `Path` + = help: the trait `std::fmt::Display` is not implemented for `Path`, which is required by `&Path: std::fmt::Display` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr index 2316acbe9da28..86487cdcc444a 100644 --- a/tests/ui/suggestions/suggest-dereferencing-index.stderr +++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr @@ -4,7 +4,7 @@ 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 `&usize` + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`, which is required by `[{integer}; 3]: Index<_>` = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `&usize` = note: required for `[{integer}]` to implement `Index<&usize>` diff --git a/tests/ui/suggestions/suggest-pin-macro.stderr b/tests/ui/suggestions/suggest-pin-macro.stderr index a761a454ad5a3..68f4099a976d0 100644 --- a/tests/ui/suggestions/suggest-pin-macro.stderr +++ b/tests/ui/suggestions/suggest-pin-macro.stderr @@ -2,7 +2,7 @@ error[E0277]: `PhantomPinned` cannot be unpinned --> $DIR/suggest-pin-macro.rs:22:17 | LL | dummy(test1.get_mut()); - | ^^^^^^^ within `Test`, the trait `Unpin` is not implemented for `PhantomPinned` + | ^^^^^^^ within `Test`, the trait `Unpin` is not implemented for `PhantomPinned`, which is required by `Test: Unpin` | = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope diff --git a/tests/ui/suggestions/suggest-remove-refs-1.stderr b/tests/ui/suggestions/suggest-remove-refs-1.stderr index 523f78dffcc67..171184bf77d30 100644 --- a/tests/ui/suggestions/suggest-remove-refs-1.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-1.stderr @@ -4,7 +4,7 @@ error[E0277]: `&Enumerate>` is not an iterator LL | for (i, _) in &v.iter().enumerate() { | ^^^^^^^^^^^^^^^^^^^^^ `&Enumerate>` is not an iterator | - = help: the trait `Iterator` is not implemented for `&Enumerate>` + = help: the trait `Iterator` is not implemented for `&Enumerate>`, which is required by `&Enumerate>: IntoIterator` = note: required for `&Enumerate>` to implement `IntoIterator` help: consider removing the leading `&`-reference | diff --git a/tests/ui/suggestions/suggest-remove-refs-2.stderr b/tests/ui/suggestions/suggest-remove-refs-2.stderr index bbe3261e14869..4e1994523dc2b 100644 --- a/tests/ui/suggestions/suggest-remove-refs-2.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-2.stderr @@ -4,7 +4,7 @@ error[E0277]: `&&&&&Enumerate>` is not an iterat LL | for (i, _) in & & & & &v.iter().enumerate() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&&&&&Enumerate>` is not an iterator | - = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` + = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>`, which is required by `&&&&&Enumerate>: IntoIterator` = note: required for `&&&&&Enumerate>` to implement `IntoIterator` help: consider removing 5 leading `&`-references | diff --git a/tests/ui/suggestions/suggest-remove-refs-3.stderr b/tests/ui/suggestions/suggest-remove-refs-3.stderr index a3e142563ff84..1d180f9d8be24 100644 --- a/tests/ui/suggestions/suggest-remove-refs-3.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-3.stderr @@ -8,7 +8,7 @@ LL | | .iter() LL | | .enumerate() { | |____________________^ `&&&&&Enumerate>` is not an iterator | - = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` + = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>`, which is required by `&&&&&Enumerate>: IntoIterator` = note: required for `&&&&&Enumerate>` to implement `IntoIterator` help: consider removing 5 leading `&`-references | diff --git a/tests/ui/suggestions/suggest-remove-refs-4.stderr b/tests/ui/suggestions/suggest-remove-refs-4.stderr index ed9fc2dd2568b..7ab34c4af511c 100644 --- a/tests/ui/suggestions/suggest-remove-refs-4.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-4.stderr @@ -4,7 +4,7 @@ error[E0277]: `&&std::slice::Iter<'_, {integer}>` is not an iterator LL | for _i in &foo {} | ^^^^ `&&std::slice::Iter<'_, {integer}>` is not an iterator | - = help: the trait `Iterator` is not implemented for `&&std::slice::Iter<'_, {integer}>` + = help: the trait `Iterator` is not implemented for `&&std::slice::Iter<'_, {integer}>`, which is required by `&&std::slice::Iter<'_, {integer}>: IntoIterator` = note: required for `&&std::slice::Iter<'_, {integer}>` to implement `IntoIterator` help: consider removing 2 leading `&`-references | diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr index 7de84d6122b58..6b2f330e1a36d 100644 --- a/tests/ui/suggestions/suggest-remove-refs-5.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr @@ -4,7 +4,7 @@ error[E0277]: `Vec` is not an iterator LL | for _ in &mut &mut v {} | ^^^^^^^^^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` | - = help: the trait `Iterator` is not implemented for `Vec` + = help: the trait `Iterator` is not implemented for `Vec`, which is required by `&mut &mut &mut &mut Vec: IntoIterator` = note: required for `&mut Vec` to implement `Iterator` = note: 3 redundant requirements hidden = note: required for `&mut &mut &mut &mut Vec` to implement `Iterator` @@ -21,7 +21,7 @@ error[E0277]: `[u8; 1]` is not an iterator LL | for _ in &mut v {} | ^^^^^^ `[u8; 1]` is not an iterator; try calling `.into_iter()` or `.iter()` | - = help: the trait `Iterator` is not implemented for `[u8; 1]` + = help: the trait `Iterator` is not implemented for `[u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator` = note: required for `&mut [u8; 1]` to implement `Iterator` = note: 2 redundant requirements hidden = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator` diff --git a/tests/ui/sync/mutexguard-sync.stderr b/tests/ui/sync/mutexguard-sync.stderr index 1501a793d5e8b..6b686741d1f82 100644 --- a/tests/ui/sync/mutexguard-sync.stderr +++ b/tests/ui/sync/mutexguard-sync.stderr @@ -6,7 +6,7 @@ LL | test_sync(guard); | | | required by a bound introduced by this call | - = help: the trait `Sync` is not implemented for `Cell` + = help: the trait `Sync` is not implemented for `Cell`, which is required by `MutexGuard<'_, Cell>: Sync` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead = note: required for `MutexGuard<'_, Cell>` to implement `Sync` note: required by a bound in `test_sync` diff --git a/tests/ui/traits/alias/cross-crate.stderr b/tests/ui/traits/alias/cross-crate.stderr index ae9d7d0a9b4a4..fd614b4bcd58a 100644 --- a/tests/ui/traits/alias/cross-crate.stderr +++ b/tests/ui/traits/alias/cross-crate.stderr @@ -4,7 +4,7 @@ error[E0277]: `Rc` cannot be sent between threads safely LL | use_alias::>(); | ^^^^^^^ `Rc` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `Rc` + = help: the trait `Send` is not implemented for `Rc`, which is required by `Rc: SendSync` = note: required for `Rc` to implement `SendSync` note: required by a bound in `use_alias` --> $DIR/cross-crate.rs:10:17 @@ -18,7 +18,7 @@ error[E0277]: `Rc` cannot be shared between threads safely LL | use_alias::>(); | ^^^^^^^ `Rc` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `Rc` + = help: the trait `Sync` is not implemented for `Rc`, which is required by `Rc: SendSync` = note: required for `Rc` to implement `SendSync` note: required by a bound in `use_alias` --> $DIR/cross-crate.rs:10:17 diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr index 968ad2667a210..1e4f4cb70463c 100644 --- a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr +++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr @@ -6,7 +6,7 @@ LL | f(()) | | | required by a bound introduced by this call | - = help: the trait `Iterator` is not implemented for `()` + = help: the trait `Iterator` is not implemented for `()`, which is required by `(): IteratorAlias` = note: required for `()` to implement `IteratorAlias` note: required by a bound in `f` --> $DIR/issue-108072-unmet-trait-alias-bound.rs:7:14 diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr index c8631ed3677e8..bd9838bc62354 100644 --- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr +++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr @@ -4,7 +4,7 @@ error[E0277]: expected a `FnMut(char)` closure, found `u8` LL | s.strip_suffix(b'\n').unwrap_or(s) | ^^^^^^^^^^^^ expected an `FnMut(char)` closure, found `u8` | - = help: the trait `FnMut<(char,)>` is not implemented for `u8` + = help: the trait `FnMut<(char,)>` is not implemented for `u8`, which is required by `u8: Pattern<'_>` = help: the following other types implement trait `Pattern<'a>`: char [char; N] diff --git a/tests/ui/traits/copy-impl-cannot-normalize.stderr b/tests/ui/traits/copy-impl-cannot-normalize.stderr index 3bdb8b70172c4..a98bb47f54fc1 100644 --- a/tests/ui/traits/copy-impl-cannot-normalize.stderr +++ b/tests/ui/traits/copy-impl-cannot-normalize.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: TraitFoo` is not satisfied --> $DIR/copy-impl-cannot-normalize.rs:22:18 | LL | impl Copy for Foo {} - | ^^^^^^ the trait `TraitFoo` is not implemented for `T` + | ^^^^^^ the trait `TraitFoo` is not implemented for `T`, which is required by `Foo: Clone` | note: required for `Foo` to implement `Clone` --> $DIR/copy-impl-cannot-normalize.rs:12:9 diff --git a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr index a5d0e6ab09569..fecb05cade758 100644 --- a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr +++ b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr @@ -8,7 +8,7 @@ error[E0277]: the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>` --> $DIR/dont-autoderef-ty-with-escaping-var.rs:17:6 | LL | >::ref_foo(unknown); - | ^^^ the trait `for<'a> Foo<'static, i32>` is not implemented for `&'a mut Vec<&'a u32>` + | ^^^ the trait `for<'a> Foo<'static, i32>` is not implemented for `&'a mut Vec<&'a u32>`, which is required by `i32: RefFoo` | help: this trait has no implementations, consider adding one --> $DIR/dont-autoderef-ty-with-escaping-var.rs:3:1 diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr index e723c7c51814a..629ccac49c56a 100644 --- a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr +++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr @@ -10,7 +10,7 @@ error[E0277]: the trait bound `NoClone: Copy` is not satisfied --> $DIR/supertrait-auto-trait.rs:16:23 | LL | let (a, b) = copy(NoClone); - | ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone` + | ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone`, which is required by `NoClone: Magic` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr index 2bf365745a6bd..4c565c3fa1db5 100644 --- a/tests/ui/traits/issue-43784-supertrait.stderr +++ b/tests/ui/traits/issue-43784-supertrait.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/issue-43784-supertrait.rs:8:22 | LL | impl Complete for T {} - | ^ the trait `Copy` is not implemented for `T` + | ^ the trait `Copy` is not implemented for `T`, which is required by `T: Partial` | note: required for `T` to implement `Partial` --> $DIR/issue-43784-supertrait.rs:1:11 diff --git a/tests/ui/traits/issue-7013.stderr b/tests/ui/traits/issue-7013.stderr index 1749366317286..5067c7d7dd7d7 100644 --- a/tests/ui/traits/issue-7013.stderr +++ b/tests/ui/traits/issue-7013.stderr @@ -4,7 +4,7 @@ error[E0277]: `Rc>` cannot be sent between threads safely LL | let a = A {v: Box::new(B{v: None}) as Box}; | ^^^^^^^^^^^^^^^^^^^^ `Rc>` cannot be sent between threads safely | - = help: within `B`, the trait `Send` is not implemented for `Rc>` + = help: within `B`, the trait `Send` is not implemented for `Rc>`, which is required by `B: Send` note: required because it appears within the type `Option>>` --> $SRC_DIR/core/src/option.rs:LL:COL note: required because it appears within the type `B` diff --git a/tests/ui/traits/issue-71036.stderr b/tests/ui/traits/issue-71036.stderr index 2452731f19f16..35d543eb0177a 100644 --- a/tests/ui/traits/issue-71036.stderr +++ b/tests/ui/traits/issue-71036.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied --> $DIR/issue-71036.rs:11:1 | LL | impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn> for Foo<'a, T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T`, which is required by `&'a &'a T: DispatchFromDyn<&'a &'a U>` | = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information = note: required for `&'a &'a T` to implement `DispatchFromDyn<&'a &'a U>` diff --git a/tests/ui/traits/issue-71136.stderr b/tests/ui/traits/issue-71136.stderr index 2c03c6bf08ed8..d37ad8ae34d0d 100644 --- a/tests/ui/traits/issue-71136.stderr +++ b/tests/ui/traits/issue-71136.stderr @@ -5,7 +5,7 @@ LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct FooHolster { LL | the_foos: Vec, - | ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo` + | ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo`, which is required by `Vec: Clone` | = note: required for `Vec` to implement `Clone` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/traits/issue-91594.stderr b/tests/ui/traits/issue-91594.stderr index 13568179e81f4..726ee5b61461b 100644 --- a/tests/ui/traits/issue-91594.stderr +++ b/tests/ui/traits/issue-91594.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied --> $DIR/issue-91594.rs:10:19 | LL | impl HasComponent<>::Interface> for Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`, which is required by `Foo: Component` | = help: the trait `HasComponent<>::Interface>` is implemented for `Foo` note: required for `Foo` to implement `Component` diff --git a/tests/ui/traits/issue-97576.stderr b/tests/ui/traits/issue-97576.stderr index 2c6cfd83b9571..bee254461f1bd 100644 --- a/tests/ui/traits/issue-97576.stderr +++ b/tests/ui/traits/issue-97576.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `String: From` is not satisfied --> $DIR/issue-97576.rs:8:22 | LL | bar: bar.into(), - | ^^^^ the trait `From` is not implemented for `String` + | ^^^^ the trait `From` is not implemented for `String`, which is required by `impl ToString: Into<_>` | = note: required for `impl ToString` to implement `Into` diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr index 8f5b937e586ae..2a3833beb26b3 100644 --- a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -49,7 +49,7 @@ LL | is_send((8, TestType)); | | | required by a bound introduced by this call | - = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType` + = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType`, which is required by `({integer}, dummy1c::TestType): Send` = note: required because it appears within the type `({integer}, dummy1c::TestType)` note: required by a bound in `is_send` --> $DIR/negated-auto-traits-error.rs:16:15 @@ -87,7 +87,7 @@ LL | is_send(Box::new(Outer2(TestType))); | | | required by a bound introduced by this call | - = help: within `Outer2`, the trait `Send` is not implemented for `dummy3::TestType` + = help: within `Outer2`, the trait `Send` is not implemented for `dummy3::TestType`, which is required by `Box>: Send` note: required because it appears within the type `Outer2` --> $DIR/negated-auto-traits-error.rs:12:8 | @@ -110,7 +110,7 @@ LL | is_sync(Outer2(TestType)); | | | required by a bound introduced by this call | - = help: the trait `Send` is not implemented for `main::TestType` + = help: the trait `Send` is not implemented for `main::TestType`, which is required by `Outer2: Sync` note: required for `Outer2` to implement `Sync` --> $DIR/negated-auto-traits-error.rs:14:22 | diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr index f4deb169516cf..f7d5d6fcee4db 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr @@ -29,7 +29,7 @@ error[E0277]: `V` is not an iterator LL | bar(); | ^^^^^ `V` is not an iterator | - = help: the trait `Iterator` is not implemented for `V` + = help: the trait `Iterator` is not implemented for `V`, which is required by `V: IntoIterator` = note: required for `V` to implement `IntoIterator` note: required by a bound in `bar` --> $DIR/bad-sized-cond.rs:12:15 @@ -46,7 +46,7 @@ error[E0277]: the size for values of type `V` cannot be known at compilation tim LL | bar(); | ^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `V` + = help: the trait `Sized` is not implemented for `V`, which is required by `V: IntoIterator` = note: required for `V` to implement `IntoIterator` note: required by a bound in `bar` --> $DIR/bad-sized-cond.rs:12:15 diff --git a/tests/ui/traits/question-mark-result-err-mismatch.stderr b/tests/ui/traits/question-mark-result-err-mismatch.stderr index 3059e0beca3e4..79f270fd1bbd6 100644 --- a/tests/ui/traits/question-mark-result-err-mismatch.stderr +++ b/tests/ui/traits/question-mark-result-err-mismatch.stderr @@ -11,7 +11,7 @@ LL | | e; LL | | }) | |__________- this can't be annotated with `?` because it has type `Result<_, ()>` LL | .map(|()| "")?; - | ^ the trait `From<()>` is not implemented for `String` + | ^ the trait `From<()>` is not implemented for `String`, which is required by `Result: FromResidual>` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = note: required for `Result` to implement `FromResidual>` @@ -25,7 +25,7 @@ LL | let x = foo(); | ----- this has type `Result<_, String>` ... LL | .map_err(|_| ())?; - | ---------------^ the trait `From<()>` is not implemented for `String` + | ---------------^ the trait `From<()>` is not implemented for `String`, which is required by `Result<(), String>: FromResidual>` | | | this can't be annotated with `?` because it has type `Result<_, ()>` | @@ -50,7 +50,7 @@ LL | .ok_or_else(|| { LL | | "Couldn't split the test string"; | | - help: remove this semicolon LL | | })?; - | | -^ the trait `From<()>` is not implemented for `String` + | | -^ the trait `From<()>` is not implemented for `String`, which is required by `Result: FromResidual>` | |__________| | this can't be annotated with `?` because it has type `Result<_, ()>` | diff --git a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr index 8024ad28d5ae6..28a0646a86bfc 100644 --- a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr +++ b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr @@ -6,7 +6,7 @@ LL | use_iterator(i); | | | required by a bound introduced by this call | - = help: the trait `Iterator` is not implemented for `&dyn IntoIterator` + = help: the trait `Iterator` is not implemented for `&dyn IntoIterator`, which is required by `&dyn IntoIterator: IntoIterator` = note: required for `&dyn IntoIterator` to implement `IntoIterator` note: required by a bound in `use_iterator` --> $DIR/dont-suggest-unsize-deref.rs:3:8 diff --git a/tests/ui/traits/suggest-dereferences/issue-39029.stderr b/tests/ui/traits/suggest-dereferences/issue-39029.stderr index fd45fa3cf74d0..0eea6cbcc5a62 100644 --- a/tests/ui/traits/suggest-dereferences/issue-39029.stderr +++ b/tests/ui/traits/suggest-dereferences/issue-39029.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied --> $DIR/issue-39029.rs:16:38 | LL | let _errors = TcpListener::bind(&bad); - | ----------------- ^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs` + | ----------------- ^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`, which is required by `&NoToSocketAddrs: ToSocketAddrs` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr index 62500866c49b9..a41330373be1a 100644 --- a/tests/ui/traits/suggest-dereferences/root-obligation.stderr +++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr @@ -6,7 +6,7 @@ LL | .filter(|c| "aeiou".contains(c)) | | | required by a bound introduced by this call | - = help: the trait `Fn<(char,)>` is not implemented for `char` + = help: the trait `Fn<(char,)>` is not implemented for `char`, which is required by `&char: Pattern<'_>` = note: required for `&char` to implement `FnOnce<(char,)>` = note: required for `&char` to implement `Pattern<'_>` note: required by a bound in `core::str::::contains` diff --git a/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr index d6033bc6baa0f..d1d75625abaaa 100644 --- a/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr +++ b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `TargetStruct: From<&{integer}>` is not satisfied --> $DIR/suggest-dereferencing-receiver-argument.rs:13:30 | LL | let _b: TargetStruct = a.into(); - | ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct` + | ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct`, which is required by `&{integer}: Into<_>` | = note: required for `&{integer}` to implement `Into` help: consider dereferencing here diff --git a/tests/ui/traits/unsend-future.stderr b/tests/ui/traits/unsend-future.stderr index 25df34197947b..4462208cb4956 100644 --- a/tests/ui/traits/unsend-future.stderr +++ b/tests/ui/traits/unsend-future.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | require_handler(handler) | ^^^^^^^ future returned by `handler` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `*const i32` + = help: within `impl Future`, the trait `Send` is not implemented for `*const i32`, which is required by `fn() -> impl Future {handler}: Handler` note: future is not `Send` as this value is used across an await --> $DIR/unsend-future.rs:15:14 | diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr index d58a011ff5501..6c41b42dc643f 100644 --- a/tests/ui/try-block/try-block-bad-type.stderr +++ b/tests/ui/try-block/try-block-bad-type.stderr @@ -2,7 +2,7 @@ error[E0277]: `?` couldn't convert the error to `TryFromSliceError` --> $DIR/try-block-bad-type.rs:7:16 | LL | Err("")?; - | -------^ the trait `From<&str>` is not implemented for `TryFromSliceError` + | -------^ the trait `From<&str>` is not implemented for `TryFromSliceError`, which is required by `Result: FromResidual>` | | | this can't be annotated with `?` because it has type `Result<_, &str>` | diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index 7e5b68353fb2d..80471c0ab1a40 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -4,7 +4,7 @@ error[E0277]: `?` couldn't convert the error to `u8` LL | fn result_to_result() -> Result { | --------------- expected `u8` because of this LL | Ok(Err(123_i32)?) - | ------------^ the trait `From` is not implemented for `u8` + | ------------^ the trait `From` is not implemented for `u8`, which is required by `Result: FromResidual>` | | | this can't be annotated with `?` because it has type `Result<_, i32>` | diff --git a/tests/ui/try-trait/issue-32709.stderr b/tests/ui/try-trait/issue-32709.stderr index b155b3ff66313..34618de78cd0f 100644 --- a/tests/ui/try-trait/issue-32709.stderr +++ b/tests/ui/try-trait/issue-32709.stderr @@ -4,7 +4,7 @@ error[E0277]: `?` couldn't convert the error to `()` LL | fn a() -> Result { | --------------- expected `()` because of this LL | Err(5)?; - | ------^ the trait `From<{integer}>` is not implemented for `()` + | ------^ the trait `From<{integer}>` is not implemented for `()`, which is required by `Result: FromResidual>` | | | this can't be annotated with `?` because it has type `Result<_, {integer}>` | diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr index 2ed918eca1714..5c5506fb8532d 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr @@ -9,7 +9,7 @@ LL | is_send(m::foo()); | | | required by a bound introduced by this call | - = help: within `Foo`, the trait `Send` is not implemented for `Rc` + = help: within `Foo`, the trait `Send` is not implemented for `Rc`, which is required by `Foo: Send` note: required because it appears within the type `Foo` --> $DIR/auto-trait-leakage2.rs:7:16 | diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr index 37abb3fe021bb..5e978e97d6b50 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `B: Bar` is not satisfied --> $DIR/issue-90400-2.rs:25:9 | LL | MyBaz(bar) - | ^^^^^^^^^^ the trait `Bar` is not implemented for `B` + | ^^^^^^^^^^ the trait `Bar` is not implemented for `B`, which is required by `MyBaz: Baz` | note: required for `MyBaz` to implement `Baz` --> $DIR/issue-90400-2.rs:30:14 diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr index b5f38074632ee..a7840e0a5bf24 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied --> $DIR/multiple-def-uses-in-one-fn.rs:9:45 | LL | fn f(a: &'static A, b: B) -> (X, X) { - | ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B` + | ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B`, which is required by `&A: Into<&'static B>` | = note: required for `&A` to implement `Into<&'static B>` help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr index e4de9245951cf..913a35eb9fb0e 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr +++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied --> $DIR/underconstrained_generic.rs:22:5 | LL | () - | ^^ the trait `Trait` is not implemented for `T` + | ^^ the trait `Trait` is not implemented for `T`, which is required by `(): ProofForConversion` | note: required for `()` to implement `ProofForConversion` --> $DIR/underconstrained_generic.rs:13:16 diff --git a/tests/ui/type/issue-58355.stderr b/tests/ui/type/issue-58355.stderr index b6056f0fd65ad..cd8e353880241 100644 --- a/tests/ui/type/issue-58355.stderr +++ b/tests/ui/type/issue-58355.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `dyn ToString` cannot be known at comp LL | x = Some(Box::new(callback)); | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn ToString`, the trait `Sized` is not implemented for `dyn ToString` + = help: within `fn() -> dyn ToString`, the trait `Sized` is not implemented for `dyn ToString`, which is required by `fn() -> dyn ToString: Fn()` = note: required because it appears within the type `fn() -> dyn ToString` = note: required for the cast from `Box dyn ToString>` to `Box (dyn ToString + 'static)>` diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.stderr index bd7fd0392c378..137c7b0639667 100644 --- a/tests/ui/typeck/bad-index-due-to-nested.stderr +++ b/tests/ui/typeck/bad-index-due-to-nested.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `K: Hash` is not satisfied --> $DIR/bad-index-due-to-nested.rs:20:5 | LL | map[k] - | ^^^ the trait `Hash` is not implemented for `K` + | ^^^ the trait `Hash` is not implemented for `K`, which is required by `HashMap<_, _>: Index<&_>` | note: required for `HashMap` to implement `Index<&K>` --> $DIR/bad-index-due-to-nested.rs:7:12 @@ -21,7 +21,7 @@ error[E0277]: the trait bound `V: Copy` is not satisfied --> $DIR/bad-index-due-to-nested.rs:20:5 | LL | map[k] - | ^^^ the trait `Copy` is not implemented for `V` + | ^^^ the trait `Copy` is not implemented for `V`, which is required by `HashMap<_, _>: Index<&_>` | note: required for `HashMap` to implement `Index<&K>` --> $DIR/bad-index-due-to-nested.rs:7:12 diff --git a/tests/ui/typeck/issue-90101.stderr b/tests/ui/typeck/issue-90101.stderr index a24f9cb540fc8..d5ba157974d93 100644 --- a/tests/ui/typeck/issue-90101.stderr +++ b/tests/ui/typeck/issue-90101.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `PathBuf: From>` is not satisfied --> $DIR/issue-90101.rs:6:10 | LL | func(Path::new("hello").to_path_buf().to_string_lossy(), "world") - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `PathBuf` + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `PathBuf`, which is required by `Cow<'_, str>: Into` | | | required by a bound introduced by this call | diff --git a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr index b9fca1a1b54b8..f5311b6e8ed7f 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr @@ -17,7 +17,7 @@ error[E0277]: `UnsafeCell` cannot be shared between threads safely LL | is_sync::(); | ^^^^^^^^^^^^^ `UnsafeCell` cannot be shared between threads safely | - = help: within `MyTypeWUnsafe`, the trait `Sync` is not implemented for `UnsafeCell` + = help: within `MyTypeWUnsafe`, the trait `Sync` is not implemented for `UnsafeCell`, which is required by `MyTypeWUnsafe: Sync` note: required because it appears within the type `MyTypeWUnsafe` --> $DIR/typeck-default-trait-impl-negation-sync.rs:21:8 | @@ -35,7 +35,7 @@ error[E0277]: `Managed` cannot be shared between threads safely LL | is_sync::(); | ^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely | - = help: within `MyTypeManaged`, the trait `Sync` is not implemented for `Managed` + = help: within `MyTypeManaged`, the trait `Sync` is not implemented for `Managed`, which is required by `MyTypeManaged: Sync` note: required because it appears within the type `MyTypeManaged` --> $DIR/typeck-default-trait-impl-negation-sync.rs:25:8 | diff --git a/tests/ui/typeck/typeck-unsafe-always-share.stderr b/tests/ui/typeck/typeck-unsafe-always-share.stderr index 154e504996bc4..3eb792b82e0f4 100644 --- a/tests/ui/typeck/typeck-unsafe-always-share.stderr +++ b/tests/ui/typeck/typeck-unsafe-always-share.stderr @@ -36,7 +36,7 @@ LL | test(ms); | | | required by a bound introduced by this call | - = help: within `MySync`, the trait `Sync` is not implemented for `UnsafeCell` + = help: within `MySync`, the trait `Sync` is not implemented for `UnsafeCell`, which is required by `MySync: Sync` note: required because it appears within the type `MySync` --> $DIR/typeck-unsafe-always-share.rs:8:8 | diff --git a/tests/ui/union/projection-as-union-type-error-2.stderr b/tests/ui/union/projection-as-union-type-error-2.stderr index 3b073ca1fb4e0..39cdf30d8605a 100644 --- a/tests/ui/union/projection-as-union-type-error-2.stderr +++ b/tests/ui/union/projection-as-union-type-error-2.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `u8: NotImplemented` is not satisfied --> $DIR/projection-as-union-type-error-2.rs:18:8 | LL | a: ::Identity, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotImplemented` is not implemented for `u8` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotImplemented` is not implemented for `u8`, which is required by `u8: Identity` | help: this trait has no implementations, consider adding one --> $DIR/projection-as-union-type-error-2.rs:9:1 diff --git a/tests/ui/unsized-locals/issue-50940-with-feature.stderr b/tests/ui/unsized-locals/issue-50940-with-feature.stderr index b39eb2e70bbae..4c06566709ede 100644 --- a/tests/ui/unsized-locals/issue-50940-with-feature.stderr +++ b/tests/ui/unsized-locals/issue-50940-with-feature.stderr @@ -13,7 +13,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | A as fn(str) -> A; | ^ doesn't have a size known at compile-time | - = help: within `A`, the trait `Sized` is not implemented for `str` + = help: within `A`, the trait `Sized` is not implemented for `str`, which is required by `A: Sized` note: required because it appears within the type `A` --> $DIR/issue-50940-with-feature.rs:5:12 | diff --git a/tests/ui/unsized-locals/rust-call.stderr b/tests/ui/unsized-locals/rust-call.stderr index 9eb0f3dabcca1..b2e13b553e921 100644 --- a/tests/ui/unsized-locals/rust-call.stderr +++ b/tests/ui/unsized-locals/rust-call.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | f(*slice); | ^^^^^^ doesn't have a size known at compile-time | - = help: within `([u8],)`, the trait `Sized` is not implemented for `[u8]` + = help: within `([u8],)`, the trait `Sized` is not implemented for `[u8]`, which is required by `([u8],): Sized` = note: required because it appears within the type `([u8],)` = note: argument required to be sized due to `extern "rust-call"` ABI diff --git a/tests/ui/unsized-locals/unsized-exprs.stderr b/tests/ui/unsized-locals/unsized-exprs.stderr index 8a2ecf0f6c331..6da37749facbb 100644 --- a/tests/ui/unsized-locals/unsized-exprs.stderr +++ b/tests/ui/unsized-locals/unsized-exprs.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | udrop::<(i32, [u8])>((42, *foo())); | ^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `({integer}, [u8])`, the trait `Sized` is not implemented for `[u8]` + = help: within `({integer}, [u8])`, the trait `Sized` is not implemented for `[u8]`, which is required by `({integer}, [u8]): Sized` = note: required because it appears within the type `({integer}, [u8])` = note: tuples must have a statically known size to be initialized @@ -14,7 +14,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | udrop::>(A { 0: *foo() }); | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` + = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`, which is required by `A<[u8]>: Sized` note: required because it appears within the type `A<[u8]>` --> $DIR/unsized-exprs.rs:3:8 | @@ -28,7 +28,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | udrop::>(A(*foo())); | ^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` + = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`, which is required by `A<[u8]>: Sized` note: required because it appears within the type `A<[u8]>` --> $DIR/unsized-exprs.rs:3:8 | diff --git a/tests/ui/unsized/unsized-enum2.stderr b/tests/ui/unsized/unsized-enum2.stderr index 71cf782120e57..48cca6eb4bd06 100644 --- a/tests/ui/unsized/unsized-enum2.stderr +++ b/tests/ui/unsized/unsized-enum2.stderr @@ -320,7 +320,7 @@ error[E0277]: the size for values of type `(dyn PathHelper1 + 'static)` cannot b LL | VI(Path1), | ^^^^^ doesn't have a size known at compile-time | - = help: within `Path1`, the trait `Sized` is not implemented for `(dyn PathHelper1 + 'static)` + = help: within `Path1`, the trait `Sized` is not implemented for `(dyn PathHelper1 + 'static)`, which is required by `Path1: Sized` note: required because it appears within the type `Path1` --> $DIR/unsized-enum2.rs:16:8 | @@ -343,7 +343,7 @@ error[E0277]: the size for values of type `(dyn PathHelper2 + 'static)` cannot b LL | VJ{x: Path2}, | ^^^^^ doesn't have a size known at compile-time | - = help: within `Path2`, the trait `Sized` is not implemented for `(dyn PathHelper2 + 'static)` + = help: within `Path2`, the trait `Sized` is not implemented for `(dyn PathHelper2 + 'static)`, which is required by `Path2: Sized` note: required because it appears within the type `Path2` --> $DIR/unsized-enum2.rs:17:8 | @@ -366,7 +366,7 @@ error[E0277]: the size for values of type `(dyn PathHelper3 + 'static)` cannot b LL | VK(isize, Path3), | ^^^^^ doesn't have a size known at compile-time | - = help: within `Path3`, the trait `Sized` is not implemented for `(dyn PathHelper3 + 'static)` + = help: within `Path3`, the trait `Sized` is not implemented for `(dyn PathHelper3 + 'static)`, which is required by `Path3: Sized` note: required because it appears within the type `Path3` --> $DIR/unsized-enum2.rs:18:8 | @@ -389,7 +389,7 @@ error[E0277]: the size for values of type `(dyn PathHelper4 + 'static)` cannot b LL | VL{u: isize, x: Path4}, | ^^^^^ doesn't have a size known at compile-time | - = help: within `Path4`, the trait `Sized` is not implemented for `(dyn PathHelper4 + 'static)` + = help: within `Path4`, the trait `Sized` is not implemented for `(dyn PathHelper4 + 'static)`, which is required by `Path4: Sized` note: required because it appears within the type `Path4` --> $DIR/unsized-enum2.rs:19:8 | diff --git a/tests/ui/wf/hir-wf-check-erase-regions.stderr b/tests/ui/wf/hir-wf-check-erase-regions.stderr index 4b696dc1d1dfe..93449d60e9d0d 100644 --- a/tests/ui/wf/hir-wf-check-erase-regions.stderr +++ b/tests/ui/wf/hir-wf-check-erase-regions.stderr @@ -4,7 +4,7 @@ error[E0277]: `&'a T` is not an iterator LL | type IntoIter = std::iter::Flatten>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'a T` is not an iterator | - = help: the trait `Iterator` is not implemented for `&'a T` + = help: the trait `Iterator` is not implemented for `&'a T`, which is required by `Flatten>: Iterator` = help: the trait `Iterator` is implemented for `&mut I` = note: required for `Flatten>` to implement `Iterator` note: required by a bound in `std::iter::IntoIterator::IntoIter` @@ -16,7 +16,7 @@ error[E0277]: `&'a T` is not an iterator LL | type IntoIter = std::iter::Flatten>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'a T` is not an iterator | - = help: the trait `Iterator` is not implemented for `&'a T` + = help: the trait `Iterator` is not implemented for `&'a T`, which is required by `&'a T: IntoIterator` = help: the trait `Iterator` is implemented for `&mut I` = note: required for `&'a T` to implement `IntoIterator` note: required by a bound in `Flatten` @@ -28,7 +28,7 @@ error[E0277]: `&'a T` is not an iterator LL | fn into_iter(self) -> Self::IntoIter { | ^^^^^^^^^^^^^^ `&'a T` is not an iterator | - = help: the trait `Iterator` is not implemented for `&'a T` + = help: the trait `Iterator` is not implemented for `&'a T`, which is required by `&'a T: IntoIterator` = help: the trait `Iterator` is implemented for `&mut I` = note: required for `&'a T` to implement `IntoIterator` note: required by a bound in `Flatten` diff --git a/tests/ui/wf/wf-const-type.stderr b/tests/ui/wf/wf-const-type.stderr index 039e907705ee6..d5e0f7672a6f3 100644 --- a/tests/ui/wf/wf-const-type.stderr +++ b/tests/ui/wf/wf-const-type.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-const-type.rs:10:12 | LL | const FOO: IsCopy> = IsCopy { t: None }; - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` note: required by a bound in `IsCopy` @@ -20,7 +20,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-const-type.rs:10:50 | LL | const FOO: IsCopy> = IsCopy { t: None }; - | ^^^^ the trait `Copy` is not implemented for `NotCopy` + | ^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` note: required by a bound in `IsCopy` diff --git a/tests/ui/wf/wf-static-type.stderr b/tests/ui/wf/wf-static-type.stderr index 65dae26014375..481173b8a269c 100644 --- a/tests/ui/wf/wf-static-type.stderr +++ b/tests/ui/wf/wf-static-type.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-static-type.rs:10:13 | LL | static FOO: IsCopy> = IsCopy { t: None }; - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` note: required by a bound in `IsCopy` @@ -20,7 +20,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-static-type.rs:10:51 | LL | static FOO: IsCopy> = IsCopy { t: None }; - | ^^^^ the trait `Copy` is not implemented for `NotCopy` + | ^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` note: required by a bound in `IsCopy` From c780fe6b277aea25a8889e292492c4519715c48e Mon Sep 17 00:00:00 2001 From: The 8472 Date: Fri, 26 Jan 2024 00:33:02 +0100 Subject: [PATCH 139/246] document `FromIterator for Vec` allocation behaviors --- library/alloc/src/vec/mod.rs | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index a360c43094666..7c2c7898ce6b1 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2784,6 +2784,51 @@ impl, A: Allocator> IndexMut for Vec { } } +/// Collects an iterator into a Vec, commonly called via [`Iterator::collect()`] +/// +/// # Allocation behavior +/// +/// In general `Vec` does not guarantee any particular grow/allocation stategy. +/// That also applies to this trait impl. +/// +/// **Note:** This section covers implementation details and is therefore exempt from +/// stability guarantees. +/// +/// Vec may use any or none of the following strategies, +/// depending on the supplied iterator: +/// +/// * preallocate based on [`Iterator::size_hint()`] +/// * and panic if the number of items is not outside the provided lower/upper bounds +/// * use an amortized growth strategy similar to `pushing` one item at a time +/// * perform the iteration in-place on the original allocation backing the iterator +/// +/// The last case warrants some attention. It is an optimization that in many cases reduces peak memory +/// consumption and improves cache locality. But when a large number of big, short-lived +/// allocations are created, only a small fraction of their items gets collected, no further use +/// is made of the spare capacity and the resulting `Vec` is moved into a longer-lived structure +/// this can lead to the large allocations having their lifetimes unnecessarily extended which +/// can result in increased memory footprint. +/// +/// In cases where this is an issue the excess capacity can be discard with [`Vec::shrink_to()`], +/// [`Vec::shrink_to_fit()`] or by collecting into [`Box<[T]>`][owned slice] instead which additionally reduces +/// the size of the longlived struct. +/// +/// [owned slice]: Box +/// +/// ```rust +/// # use std::sync::Mutex; +/// static LONG_LIVED: Mutex>> = Mutex::new(Vec::new()); +/// +/// // many short-lived allocations +/// for i in 0..100 { +/// let big_temporary: Vec = (0..1024).collect(); +/// // discard most items +/// let mut result: Vec<_> = big_temporary.into_iter().filter(|i| i % 100 == 0).collect(); +/// // without this a lot of unused capacity might be moved into the global +/// result.shrink_to_fit(); +/// LONG_LIVED.lock().unwrap().push(result); +/// } +/// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for Vec { From 39dc3153c52dc244207e02323584f94e63003281 Mon Sep 17 00:00:00 2001 From: the8472 Date: Sat, 27 Jan 2024 00:12:13 +0100 Subject: [PATCH 140/246] Apply suggestions from code review Co-authored-by: Josh Stone --- library/alloc/src/vec/mod.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 7c2c7898ce6b1..b3e5ecc924071 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2788,7 +2788,7 @@ impl, A: Allocator> IndexMut for Vec { /// /// # Allocation behavior /// -/// In general `Vec` does not guarantee any particular grow/allocation stategy. +/// In general `Vec` does not guarantee any particular growth or allocation strategy. /// That also applies to this trait impl. /// /// **Note:** This section covers implementation details and is therefore exempt from @@ -2798,20 +2798,20 @@ impl, A: Allocator> IndexMut for Vec { /// depending on the supplied iterator: /// /// * preallocate based on [`Iterator::size_hint()`] -/// * and panic if the number of items is not outside the provided lower/upper bounds +/// * and panic if the number of items is outside the provided lower/upper bounds /// * use an amortized growth strategy similar to `pushing` one item at a time /// * perform the iteration in-place on the original allocation backing the iterator /// /// The last case warrants some attention. It is an optimization that in many cases reduces peak memory -/// consumption and improves cache locality. But when a large number of big, short-lived -/// allocations are created, only a small fraction of their items gets collected, no further use -/// is made of the spare capacity and the resulting `Vec` is moved into a longer-lived structure -/// this can lead to the large allocations having their lifetimes unnecessarily extended which -/// can result in increased memory footprint. +/// consumption and improves cache locality. But when big, short-lived allocations are created, +/// only a small fraction of their items get collected, no further use is made of the spare capacity +/// and the resulting `Vec` is moved into a longer-lived structure, then this can lead to the large +/// allocations having their lifetimes unnecessarily extended which can result in increased memory +/// footprint. /// -/// In cases where this is an issue the excess capacity can be discard with [`Vec::shrink_to()`], -/// [`Vec::shrink_to_fit()`] or by collecting into [`Box<[T]>`][owned slice] instead which additionally reduces -/// the size of the longlived struct. +/// In cases where this is an issue, the excess capacity can be discarded with [`Vec::shrink_to()`], +/// [`Vec::shrink_to_fit()`] or by collecting into [`Box<[T]>`][owned slice] instead, which additionally reduces +/// the size of the long-lived struct. /// /// [owned slice]: Box /// @@ -2819,8 +2819,7 @@ impl, A: Allocator> IndexMut for Vec { /// # use std::sync::Mutex; /// static LONG_LIVED: Mutex>> = Mutex::new(Vec::new()); /// -/// // many short-lived allocations -/// for i in 0..100 { +/// for i in 0..10 { /// let big_temporary: Vec = (0..1024).collect(); /// // discard most items /// let mut result: Vec<_> = big_temporary.into_iter().filter(|i| i % 100 == 0).collect(); From 15b473451cce5237ccff6cad85836ecf203475e8 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 31 Jan 2024 00:58:22 +0100 Subject: [PATCH 141/246] Remove unused `Constructor: PartialEq` impl --- .../rustc_pattern_analysis/src/constructor.rs | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 4996015f86345..3211d6a4cfeaa 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -151,7 +151,6 @@ use std::cmp::{self, max, min, Ordering}; use std::fmt; use std::iter::once; -use std::mem; use smallvec::SmallVec; @@ -745,47 +744,6 @@ impl fmt::Debug for Constructor { } } -impl PartialEq for Constructor { - fn eq(&self, other: &Self) -> bool { - (mem::discriminant(self) == mem::discriminant(other)) - && match (self, other) { - (Constructor::Struct, Constructor::Struct) => true, - (Constructor::Variant(self_variant), Constructor::Variant(other_variant)) => { - self_variant == other_variant - } - (Constructor::Ref, Constructor::Ref) => true, - (Constructor::Slice(self_slice), Constructor::Slice(other_slice)) => { - self_slice == other_slice - } - (Constructor::UnionField, Constructor::UnionField) => true, - (Constructor::Bool(self_b), Constructor::Bool(other_b)) => self_b == other_b, - (Constructor::IntRange(self_range), Constructor::IntRange(other_range)) => { - self_range == other_range - } - ( - Constructor::F32Range(self_lo, self_hi, self_end), - Constructor::F32Range(other_lo, other_hi, other_end), - ) => self_lo == other_lo && self_hi == other_hi && self_end == other_end, - ( - Constructor::F64Range(self_lo, self_hi, self_end), - Constructor::F64Range(other_lo, other_hi, other_end), - ) => self_lo == other_lo && self_hi == other_hi && self_end == other_end, - (Constructor::Str(self_value), Constructor::Str(other_value)) => { - self_value == other_value - } - (Constructor::Opaque(self_inner), Constructor::Opaque(other_inner)) => { - self_inner == other_inner - } - (Constructor::Or, Constructor::Or) => true, - (Constructor::Wildcard, Constructor::Wildcard) => true, - (Constructor::NonExhaustive, Constructor::NonExhaustive) => true, - (Constructor::Hidden, Constructor::Hidden) => true, - (Constructor::Missing, Constructor::Missing) => true, - _ => unreachable!(), - } - } -} - impl Constructor { pub(crate) fn is_non_exhaustive(&self) -> bool { matches!(self, NonExhaustive) From 40402cbadad4f7df9ab7e2f3089a5b038d19f586 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 31 Jan 2024 01:29:21 +0100 Subject: [PATCH 142/246] Manual `Debug` impls are not needed since `TypeCx: Debug` --- .../rustc_pattern_analysis/src/constructor.rs | 28 +------------------ compiler/rustc_pattern_analysis/src/pat.rs | 11 +------- .../rustc_pattern_analysis/src/usefulness.rs | 14 ++-------- 3 files changed, 4 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 3211d6a4cfeaa..8fc826f403e47 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -648,6 +648,7 @@ impl OpaqueId { /// `specialize_constructor` returns the list of fields corresponding to a pattern, given a /// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and /// `Fields`. +#[derive(Debug)] pub enum Constructor { /// Tuples and structs. Struct, @@ -717,33 +718,6 @@ impl Clone for Constructor { } } -impl fmt::Debug for Constructor { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Constructor::Struct => f.debug_tuple("Struct").finish(), - Constructor::Variant(idx) => f.debug_tuple("Variant").field(idx).finish(), - Constructor::Ref => f.debug_tuple("Ref").finish(), - Constructor::Slice(slice) => f.debug_tuple("Slice").field(slice).finish(), - Constructor::UnionField => f.debug_tuple("UnionField").finish(), - Constructor::Bool(b) => f.debug_tuple("Bool").field(b).finish(), - Constructor::IntRange(range) => f.debug_tuple("IntRange").field(range).finish(), - Constructor::F32Range(lo, hi, end) => { - f.debug_tuple("F32Range").field(lo).field(hi).field(end).finish() - } - Constructor::F64Range(lo, hi, end) => { - f.debug_tuple("F64Range").field(lo).field(hi).field(end).finish() - } - Constructor::Str(value) => f.debug_tuple("Str").field(value).finish(), - Constructor::Opaque(inner) => f.debug_tuple("Opaque").field(inner).finish(), - Constructor::Or => f.debug_tuple("Or").finish(), - Constructor::Wildcard => f.debug_tuple("Wildcard").finish(), - Constructor::NonExhaustive => f.debug_tuple("NonExhaustive").finish(), - Constructor::Hidden => f.debug_tuple("Hidden").finish(), - Constructor::Missing => f.debug_tuple("Missing").finish(), - } - } -} - impl Constructor { pub(crate) fn is_non_exhaustive(&self) -> bool { matches!(self, NonExhaustive) diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index d476766d466f2..3d9da16344762 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -298,6 +298,7 @@ impl<'p, Cx: TypeCx> fmt::Debug for PatOrWild<'p, Cx> { /// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics /// purposes. As such they don't use interning and can be cloned. +#[derive(Debug)] pub struct WitnessPat { ctor: Constructor, pub(crate) fields: Vec>, @@ -310,16 +311,6 @@ impl Clone for WitnessPat { } } -impl fmt::Debug for WitnessPat { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("WitnessPat") - .field("ctor", &self.ctor) - .field("fields", &self.fields) - .field("ty", &self.ty) - .finish() - } -} - impl WitnessPat { pub(crate) fn new(ctor: Constructor, fields: Vec, ty: Cx::Ty) -> Self { Self { ctor, fields, ty } diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index b15de1c0ca9d7..a8d0c2e67df8b 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1198,6 +1198,7 @@ impl<'p, Cx: TypeCx> fmt::Debug for Matrix<'p, Cx> { /// The final `Pair(Some(_), true)` is then the resulting witness. /// /// See the top of the file for more detailed explanations and examples. +#[derive(Debug)] struct WitnessStack(Vec>); impl Clone for WitnessStack { @@ -1206,12 +1207,6 @@ impl Clone for WitnessStack { } } -impl fmt::Debug for WitnessStack { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_tuple("WitnessStack").field(&self.0).finish() - } -} - impl WitnessStack { /// Asserts that the witness contains a single pattern, and returns it. fn single_pattern(self) -> WitnessPat { @@ -1256,6 +1251,7 @@ impl WitnessStack { /// /// Just as the `Matrix` starts with a single column, by the end of the algorithm, this has a single /// column, which contains the patterns that are missing for the match to be exhaustive. +#[derive(Debug)] struct WitnessMatrix(Vec>); impl Clone for WitnessMatrix { @@ -1264,12 +1260,6 @@ impl Clone for WitnessMatrix { } } -impl fmt::Debug for WitnessMatrix { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_tuple("WitnessMatrix").field(&self.0).finish() - } -} - impl WitnessMatrix { /// New matrix with no witnesses. fn empty() -> Self { From ee2cddd8f2232aaac044c07b1a8ea1ceec083107 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 31 Jan 2024 01:23:35 +0100 Subject: [PATCH 143/246] It is correct to lower `!` to `_`. --- compiler/rustc_pattern_analysis/src/rustc.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 223d6cefc83fe..bef03ef30d8d6 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -680,8 +680,9 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { cx.pattern_arena.alloc_from_iter(pats.into_iter().map(|p| self.lower_pat(p))) } PatKind::Never => { - // FIXME(never_patterns): handle `!` in exhaustiveness. This is a sane default - // in the meantime. + // A never pattern matches all the values of its type (namely none). Moreover it + // must be compatible with other constructors, since we can use `!` on a type like + // `Result` which has other constructors. Hence we lower it as a wildcard. ctor = Wildcard; fields = &[]; } From 471af8c5a382229e57656798900406e1ec82c5c8 Mon Sep 17 00:00:00 2001 From: kxxt Date: Wed, 31 Jan 2024 09:02:18 +0800 Subject: [PATCH 144/246] riscv only supports split_debuginfo=off for now Disable packed/unpacked options for riscv linux/android. Other riscv targets already only have the off option. The packed/unpacked options might be supported in the future. See upstream issue for more details: https://github.com/llvm/llvm-project/issues/56642 Fixes #110224 --- .../src/spec/targets/riscv32gc_unknown_linux_gnu.rs | 5 ++++- .../src/spec/targets/riscv32gc_unknown_linux_musl.rs | 5 ++++- .../rustc_target/src/spec/targets/riscv64_linux_android.rs | 5 ++++- .../src/spec/targets/riscv64gc_unknown_linux_gnu.rs | 5 ++++- .../src/spec/targets/riscv64gc_unknown_linux_musl.rs | 5 ++++- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs index 06e8f1837637f..0be32cbd77165 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs @@ -1,4 +1,6 @@ -use crate::spec::{base, CodeModel, Target, TargetOptions}; +use std::borrow::Cow; + +use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,6 +14,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "ilp32d".into(), max_atomic_width: Some(32), + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..base::linux_gnu::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs index 722703d2384fe..cfa9990dac9bd 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs @@ -1,4 +1,6 @@ -use crate::spec::{base, CodeModel, Target, TargetOptions}; +use std::borrow::Cow; + +use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,6 +14,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "ilp32d".into(), max_atomic_width: Some(32), + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs index 40e447dbb8362..762197d7217c7 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs @@ -1,4 +1,6 @@ -use crate::spec::{base, CodeModel, SanitizerSet, Target, TargetOptions}; +use std::borrow::Cow; + +use crate::spec::{base, CodeModel, SanitizerSet, SplitDebuginfo, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,6 +15,7 @@ pub fn target() -> Target { llvm_abiname: "lp64d".into(), supported_sanitizers: SanitizerSet::ADDRESS, max_atomic_width: Some(64), + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..base::android::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs index c0969d4e11eb9..e71929a190479 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs @@ -1,4 +1,6 @@ -use crate::spec::{base, CodeModel, Target, TargetOptions}; +use std::borrow::Cow; + +use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,6 +14,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..base::linux_gnu::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs index 656e260d094d8..8ea28d6b162cc 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs @@ -1,4 +1,6 @@ -use crate::spec::{base, CodeModel, Target, TargetOptions}; +use std::borrow::Cow; + +use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,6 +14,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..base::linux_musl::opts() }, } From 604479c3734e2e6d44f668c69963e8d73879e0d8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 31 Jan 2024 09:16:30 +0100 Subject: [PATCH 145/246] internal: Use improved adjusted_display_range for all diagnostics --- .../src/handlers/mismatched_arg_count.rs | 4 +- .../handlers/trait_impl_incorrect_safety.rs | 2 +- .../handlers/trait_impl_missing_assoc_item.rs | 2 +- .../src/handlers/type_mismatch.rs | 46 ++++++++----------- .../src/handlers/unresolved_field.rs | 4 +- .../src/handlers/unresolved_method.rs | 4 +- crates/ide-diagnostics/src/lib.rs | 19 -------- 7 files changed, 27 insertions(+), 54 deletions(-) diff --git a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index e75d89737281c..66ebf593505d2 100644 --- a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -6,7 +6,7 @@ use syntax::{ AstNode, AstPtr, }; -use crate::{adjusted_display_range_new, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; // Diagnostic: mismatched-tuple-struct-pat-arg-count // @@ -50,7 +50,7 @@ fn invalid_args_range( expected: usize, found: usize, ) -> FileRange { - adjusted_display_range_new(ctx, source, &|expr| { + adjusted_display_range(ctx, source, &|expr| { let (text_range, r_paren_token, expected_arg) = match expr { Either::Left(ast::Expr::CallExpr(call)) => { let arg_list = call.arg_list()?; diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs b/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs index 251a645292ed5..6be2c54e6030e 100644 --- a/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs +++ b/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs @@ -19,7 +19,7 @@ pub(crate) fn trait_impl_incorrect_safety( }, adjusted_display_range::( ctx, - InFile { file_id: d.file_id, value: d.impl_.syntax_node_ptr() }, + InFile { file_id: d.file_id, value: d.impl_ }, &|impl_| { if d.should_be_safe { Some(match (impl_.unsafe_token(), impl_.impl_token()) { diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs index 56188cddf0b2e..58d1b7f31d2fe 100644 --- a/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs +++ b/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs @@ -25,7 +25,7 @@ pub(crate) fn trait_impl_missing_assoc_item( format!("not all trait items implemented, missing: {missing}"), adjusted_display_range::( ctx, - InFile { file_id: d.file_id, value: d.impl_.syntax_node_ptr() }, + InFile { file_id: d.file_id, value: d.impl_ }, &|impl_| impl_.trait_().map(|t| t.syntax().text_range()), ), ) diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 23042e222b584..750189beecb1d 100644 --- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -1,3 +1,4 @@ +use either::Either; use hir::{db::ExpandDatabase, ClosureStyle, HirDisplay, HirFileIdExt, InFile, Type}; use ide_db::{famous_defs::FamousDefs, source_change::SourceChange}; use syntax::{ @@ -13,33 +14,24 @@ use crate::{adjusted_display_range, fix, Assist, Diagnostic, DiagnosticCode, Dia // This diagnostic is triggered when the type of an expression or pattern does not match // the expected type. pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Diagnostic { - let display_range = match &d.expr_or_pat.value { - expr if ast::Expr::can_cast(expr.kind()) => adjusted_display_range::( - ctx, - InFile { file_id: d.expr_or_pat.file_id, value: expr.syntax_node_ptr() }, - &|expr| { - let salient_token_range = match expr { - ast::Expr::IfExpr(it) => it.if_token()?.text_range(), - ast::Expr::LoopExpr(it) => it.loop_token()?.text_range(), - ast::Expr::ForExpr(it) => it.for_token()?.text_range(), - ast::Expr::WhileExpr(it) => it.while_token()?.text_range(), - ast::Expr::BlockExpr(it) => it.stmt_list()?.r_curly_token()?.text_range(), - ast::Expr::MatchExpr(it) => it.match_token()?.text_range(), - ast::Expr::MethodCallExpr(it) => it.name_ref()?.ident_token()?.text_range(), - ast::Expr::FieldExpr(it) => it.name_ref()?.ident_token()?.text_range(), - ast::Expr::AwaitExpr(it) => it.await_token()?.text_range(), - _ => return None, - }; - - cov_mark::hit!(type_mismatch_range_adjustment); - Some(salient_token_range) - }, - ), - pat => ctx.sema.diagnostics_display_range(InFile { - file_id: d.expr_or_pat.file_id, - value: pat.syntax_node_ptr(), - }), - }; + let display_range = adjusted_display_range(ctx, d.expr_or_pat, &|node| { + let Either::Left(expr) = node else { return None }; + let salient_token_range = match expr { + ast::Expr::IfExpr(it) => it.if_token()?.text_range(), + ast::Expr::LoopExpr(it) => it.loop_token()?.text_range(), + ast::Expr::ForExpr(it) => it.for_token()?.text_range(), + ast::Expr::WhileExpr(it) => it.while_token()?.text_range(), + ast::Expr::BlockExpr(it) => it.stmt_list()?.r_curly_token()?.text_range(), + ast::Expr::MatchExpr(it) => it.match_token()?.text_range(), + ast::Expr::MethodCallExpr(it) => it.name_ref()?.ident_token()?.text_range(), + ast::Expr::FieldExpr(it) => it.name_ref()?.ident_token()?.text_range(), + ast::Expr::AwaitExpr(it) => it.await_token()?.text_range(), + _ => return None, + }; + + cov_mark::hit!(type_mismatch_range_adjustment); + Some(salient_token_range) + }); let mut diag = Diagnostic::new( DiagnosticCode::RustcHardError("E0308"), format!( diff --git a/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/crates/ide-diagnostics/src/handlers/unresolved_field.rs index 321459412182f..0e7a5720d4d25 100644 --- a/crates/ide-diagnostics/src/handlers/unresolved_field.rs +++ b/crates/ide-diagnostics/src/handlers/unresolved_field.rs @@ -8,7 +8,7 @@ use ide_db::{ use syntax::{ast, AstNode, AstPtr}; use text_edit::TextEdit; -use crate::{adjusted_display_range_new, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; // Diagnostic: unresolved-field // @@ -29,7 +29,7 @@ pub(crate) fn unresolved_field( d.name.display(ctx.sema.db), d.receiver.display(ctx.sema.db) ), - adjusted_display_range_new(ctx, d.expr, &|expr| { + adjusted_display_range(ctx, d.expr, &|expr| { Some( match expr { ast::Expr::MethodCallExpr(it) => it.name_ref(), diff --git a/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/crates/ide-diagnostics/src/handlers/unresolved_method.rs index 41fb67290852c..9f8fee67f31c1 100644 --- a/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -11,7 +11,7 @@ use syntax::{ }; use text_edit::TextEdit; -use crate::{adjusted_display_range_new, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; // Diagnostic: unresolved-method // @@ -34,7 +34,7 @@ pub(crate) fn unresolved_method( d.name.display(ctx.sema.db), d.receiver.display(ctx.sema.db) ), - adjusted_display_range_new(ctx, d.expr, &|expr| { + adjusted_display_range(ctx, d.expr, &|expr| { Some( match expr { ast::Expr::MethodCallExpr(it) => it.name_ref(), diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 535fb45cd68c0..5ad7069e317a9 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -89,7 +89,6 @@ use ide_db::{ use once_cell::sync::Lazy; use stdx::never; use syntax::{ - algo::find_node_at_range, ast::{self, AstNode}, AstPtr, SyntaxNode, SyntaxNodePtr, TextRange, }; @@ -571,24 +570,6 @@ fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist { } fn adjusted_display_range( - ctx: &DiagnosticsContext<'_>, - diag_ptr: InFile, - adj: &dyn Fn(N) -> Option, -) -> FileRange { - let FileRange { file_id, range } = ctx.sema.diagnostics_display_range(diag_ptr); - - let source_file = ctx.sema.db.parse(file_id); - FileRange { - file_id, - range: find_node_at_range::(&source_file.syntax_node(), range) - .filter(|it| it.syntax().text_range() == range) - .and_then(adj) - .unwrap_or(range), - } -} - -// FIXME Replace the one above with this one? -fn adjusted_display_range_new( ctx: &DiagnosticsContext<'_>, diag_ptr: InFile>, adj: &dyn Fn(N) -> Option, From d252247ab760e63c440faeb0bad8c06c6a1f9bfc Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 31 Jan 2024 09:57:17 +0100 Subject: [PATCH 146/246] internal: Remove unnecessary usages of ExpansionInfo --- crates/hir-expand/src/db.rs | 3 + crates/hir-expand/src/files.rs | 44 ++++++++----- crates/hir-expand/src/lib.rs | 75 +++++++++++++-------- crates/hir-expand/src/span_map.rs | 9 ++- crates/hir/src/semantics.rs | 106 ++++++++++++++---------------- crates/ide-db/src/search.rs | 12 +++- crates/ide/src/goto_definition.rs | 32 ++++++++- 7 files changed, 175 insertions(+), 106 deletions(-) diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 19dda651d7a30..f220284fae7c8 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -80,6 +80,9 @@ pub trait ExpandDatabase: SourceDatabase { #[salsa::invoke(SpanMap::new)] fn span_map(&self, file_id: HirFileId) -> SpanMap; + #[salsa::transparent] + #[salsa::invoke(crate::span_map::expansion_span_map)] + fn expansion_span_map(&self, file_id: MacroFileId) -> Arc; #[salsa::invoke(crate::span_map::real_span_map)] fn real_span_map(&self, file_id: FileId) -> Arc; diff --git a/crates/hir-expand/src/files.rs b/crates/hir-expand/src/files.rs index d0a1bef11c3b7..707daf040242d 100644 --- a/crates/hir-expand/src/files.rs +++ b/crates/hir-expand/src/files.rs @@ -5,7 +5,7 @@ use either::Either; use span::{FileId, FileRange, HirFileId, HirFileIdRepr, MacroFileId, SyntaxContextId}; use syntax::{AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize}; -use crate::{db, ExpansionInfo, MacroFileIdExt}; +use crate::{db, map_node_range_up, span_for_offset, MacroFileIdExt}; /// `InFile` stores a value of `T` inside a particular file/syntax tree. /// @@ -147,7 +147,7 @@ impl InFile<&SyntaxNode> { HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() }, HirFileIdRepr::MacroFile(mac_file) => { if let Some((res, ctxt)) = - ExpansionInfo::new(db, mac_file).map_node_range_up(db, self.value.text_range()) + map_node_range_up(db, &db.expansion_span_map(mac_file), self.value.text_range()) { // FIXME: Figure out an API that makes proper use of ctx, this only exists to // keep pre-token map rewrite behaviour. @@ -163,12 +163,15 @@ impl InFile<&SyntaxNode> { } /// Falls back to the macro call range if the node cannot be mapped up fully. - pub fn original_file_range_full(self, db: &dyn db::ExpandDatabase) -> FileRange { + pub fn original_file_range_with_macro_call_body( + self, + db: &dyn db::ExpandDatabase, + ) -> FileRange { match self.file_id.repr() { HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() }, HirFileIdRepr::MacroFile(mac_file) => { if let Some((res, ctxt)) = - ExpansionInfo::new(db, mac_file).map_node_range_up(db, self.value.text_range()) + map_node_range_up(db, &db.expansion_span_map(mac_file), self.value.text_range()) { // FIXME: Figure out an API that makes proper use of ctx, this only exists to // keep pre-token map rewrite behaviour. @@ -193,7 +196,7 @@ impl InFile<&SyntaxNode> { Some((FileRange { file_id, range: self.value.text_range() }, SyntaxContextId::ROOT)) } HirFileIdRepr::MacroFile(mac_file) => { - ExpansionInfo::new(db, mac_file).map_node_range_up(db, self.value.text_range()) + map_node_range_up(db, &db.expansion_span_map(mac_file), self.value.text_range()) } } } @@ -215,7 +218,7 @@ impl InFile<&SyntaxNode> { } let (FileRange { file_id, range }, ctx) = - ExpansionInfo::new(db, file_id).map_node_range_up(db, self.value.text_range())?; + map_node_range_up(db, &db.expansion_span_map(file_id), self.value.text_range())?; // FIXME: Figure out an API that makes proper use of ctx, this only exists to // keep pre-token map rewrite behaviour. @@ -246,8 +249,11 @@ impl InFile { match self.file_id.repr() { HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() }, HirFileIdRepr::MacroFile(mac_file) => { - let (range, ctxt) = ExpansionInfo::new(db, mac_file) - .span_for_offset(db, self.value.text_range().start()); + let (range, ctxt) = span_for_offset( + db, + &db.expansion_span_map(mac_file), + self.value.text_range().start(), + ); // FIXME: Figure out an API that makes proper use of ctx, this only exists to // keep pre-token map rewrite behaviour. @@ -269,8 +275,11 @@ impl InFile { Some(FileRange { file_id, range: self.value.text_range() }) } HirFileIdRepr::MacroFile(mac_file) => { - let (range, ctxt) = ExpansionInfo::new(db, mac_file) - .span_for_offset(db, self.value.text_range().start()); + let (range, ctxt) = span_for_offset( + db, + &db.expansion_span_map(mac_file), + self.value.text_range().start(), + ); // FIXME: Figure out an API that makes proper use of ctx, this only exists to // keep pre-token map rewrite behaviour. @@ -286,7 +295,7 @@ impl InFile { impl InMacroFile { pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> (FileRange, SyntaxContextId) { - ExpansionInfo::new(db, self.file_id).span_for_offset(db, self.value) + span_for_offset(db, &db.expansion_span_map(self.file_id), self.value) } } @@ -300,7 +309,7 @@ impl InFile { (FileRange { file_id, range: self.value }, SyntaxContextId::ROOT) } HirFileIdRepr::MacroFile(mac_file) => { - match ExpansionInfo::new(db, mac_file).map_node_range_up(db, self.value) { + 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); @@ -315,7 +324,7 @@ impl InFile { match self.file_id.repr() { HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value }, HirFileIdRepr::MacroFile(mac_file) => { - match ExpansionInfo::new(db, mac_file).map_node_range_up(db, self.value) { + match map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) { Some((it, SyntaxContextId::ROOT)) => it, _ => { let loc = db.lookup_intern_macro_call(mac_file.macro_call_id); @@ -335,7 +344,7 @@ impl InFile { Some((FileRange { file_id, range: self.value }, SyntaxContextId::ROOT)) } HirFileIdRepr::MacroFile(mac_file) => { - ExpansionInfo::new(db, mac_file).map_node_range_up(db, self.value) + map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) } } } @@ -355,8 +364,11 @@ impl InFile { return None; } - let (FileRange { file_id, range }, ctx) = ExpansionInfo::new(db, file_id) - .map_node_range_up(db, self.value.syntax().text_range())?; + let (FileRange { file_id, range }, ctx) = map_node_range_up( + db, + &db.expansion_span_map(file_id), + self.value.syntax().text_range(), + )?; // FIXME: Figure out an API that makes proper use of ctx, this only exists to // keep pre-token map rewrite behaviour. diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index 6cc654f03334b..bd25052490360 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -677,6 +677,10 @@ impl ExpansionInfo { Some(self.arg.with_value(self.arg.value.as_ref()?.parent()?)) } + pub fn call_file(&self) -> HirFileId { + self.arg.file_id + } + /// Maps the passed in file range down into a macro expansion if it is the input to a macro call. pub fn map_range_down( &self, @@ -697,13 +701,7 @@ impl ExpansionInfo { offset: TextSize, ) -> (FileRange, SyntaxContextId) { debug_assert!(self.expanded.value.text_range().contains(offset)); - let span = self.exp_map.span_at(offset); - let anchor_offset = db - .ast_id_map(span.anchor.file_id.into()) - .get_erased(span.anchor.ast_id) - .text_range() - .start(); - (FileRange { file_id: span.anchor.file_id, range: span.range + anchor_offset }, span.ctx) + span_for_offset(db, &self.exp_map, offset) } /// Maps up the text range out of the expansion hierarchy back into the original file its from. @@ -713,27 +711,7 @@ impl ExpansionInfo { range: TextRange, ) -> Option<(FileRange, SyntaxContextId)> { debug_assert!(self.expanded.value.text_range().contains_range(range)); - let mut spans = self.exp_map.spans_for_range(range); - let Span { range, anchor, ctx } = spans.next()?; - let mut start = range.start(); - let mut end = range.end(); - - for span in spans { - if span.anchor != anchor || span.ctx != ctx { - return None; - } - start = start.min(span.range.start()); - end = end.max(span.range.end()); - } - let anchor_offset = - db.ast_id_map(anchor.file_id.into()).get_erased(anchor.ast_id).text_range().start(); - Some(( - FileRange { - file_id: anchor.file_id, - range: TextRange::new(start, end) + anchor_offset, - }, - ctx, - )) + map_node_range_up(db, &self.exp_map, range) } /// Maps up the text range out of the expansion into is macro call. @@ -822,6 +800,47 @@ impl ExpansionInfo { } } +/// Maps up the text range out of the expansion hierarchy back into the original file its from. +pub fn map_node_range_up( + db: &dyn ExpandDatabase, + exp_map: &ExpansionSpanMap, + range: TextRange, +) -> Option<(FileRange, SyntaxContextId)> { + let mut spans = exp_map.spans_for_range(range); + let Span { range, anchor, ctx } = spans.next()?; + let mut start = range.start(); + let mut end = range.end(); + + for span in spans { + if span.anchor != anchor || span.ctx != ctx { + return None; + } + start = start.min(span.range.start()); + end = end.max(span.range.end()); + } + let anchor_offset = + db.ast_id_map(anchor.file_id.into()).get_erased(anchor.ast_id).text_range().start(); + Some(( + FileRange { file_id: anchor.file_id, range: TextRange::new(start, end) + anchor_offset }, + ctx, + )) +} + +/// Looks up the span at the given offset. +pub fn span_for_offset( + db: &dyn ExpandDatabase, + exp_map: &ExpansionSpanMap, + offset: TextSize, +) -> (FileRange, SyntaxContextId) { + let span = exp_map.span_at(offset); + let anchor_offset = db + .ast_id_map(span.anchor.file_id.into()) + .get_erased(span.anchor.ast_id) + .text_range() + .start(); + (FileRange { file_id: span.anchor.file_id, range: span.range + anchor_offset }, span.ctx) +} + /// In Rust, macros expand token trees to token trees. When we want to turn a /// token tree into an AST node, we need to figure out what kind of AST node we /// want: something like `foo` can be a type, an expression, or a pattern. diff --git a/crates/hir-expand/src/span_map.rs b/crates/hir-expand/src/span_map.rs index 8e624f5585d48..4a60a9485608a 100644 --- a/crates/hir-expand/src/span_map.rs +++ b/crates/hir-expand/src/span_map.rs @@ -1,5 +1,5 @@ //! Span maps for real files and macro expansions. -use span::{FileId, HirFileId, HirFileIdRepr, Span}; +use span::{FileId, HirFileId, HirFileIdRepr, MacroFileId, Span}; use syntax::{AstNode, TextRange}; use triomphe::Arc; @@ -94,3 +94,10 @@ pub(crate) fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> Arc Arc { + db.parse_macro_expansion(file_id).value.1 +} diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 7dc84a0353025..a869029d09663 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -20,12 +20,12 @@ use hir_def::{ }; use hir_expand::{ attrs::collect_attrs, db::ExpandDatabase, files::InRealFile, name::AsName, ExpansionInfo, - HirFileIdExt, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, + InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, }; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; use smallvec::{smallvec, SmallVec}; -use span::Span; +use span::{Span, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; use stdx::TupleExt; use syntax::{ algo::skip_trivia_token, @@ -132,6 +132,7 @@ pub struct SemanticsImpl<'db> { /// Rootnode to HirFileId cache cache: RefCell>, // These 2 caches are mainly useful for semantic highlighting as nothing else descends a lot of tokens + // So we might wanna move them out into something specific for semantic highlighting expansion_info_cache: RefCell>, /// MacroCall to its expansion's MacroFileId cache macro_call_cache: RefCell, MacroFileId>>, @@ -620,47 +621,47 @@ impl<'db> SemanticsImpl<'db> { let parent = token.parent()?; let file_id = self.find_file(&parent).file_id.file_id()?; + let mut cache = self.expansion_info_cache.borrow_mut(); + // iterate related crates and find all include! invocations that include_file_id matches for (invoc, _) in self .db .relevant_crates(file_id) .iter() .flat_map(|krate| self.db.include_macro_invoc(*krate)) - .filter(|(_, include_file_id)| *include_file_id == file_id) + .filter(|&(_, include_file_id)| include_file_id == file_id) { - // find file_id which original calls include! - let Some(callnode) = invoc.as_file().original_call_node(self.db.upcast()) else { - continue; - }; - - // call .parse to avoid panic in .find_file - let _ = self.parse(callnode.file_id); - let Some(sa) = self.analyze_no_infer(&callnode.value) else { continue }; - - let expinfo = invoc.as_macro_file().expansion_info(self.db.upcast()); - { - let InMacroFile { file_id, value } = expinfo.expanded(); - self.cache(value, file_id.into()); - } + let macro_file = invoc.as_macro_file(); + let expansion_info = cache + .entry(macro_file) + .or_insert_with(|| macro_file.expansion_info(self.db.upcast())); - // map token to the corresponding span in include! macro file - let Some((_, span)) = - expinfo.exp_map.iter().find(|(_, x)| x.range == token.text_range()) + // Create the source analyzer for the macro call scope + let Some(sa) = self.analyze_no_infer(&self.parse_or_expand(expansion_info.call_file())) else { continue; }; + { + let InMacroFile { file_id: macro_file, value } = expansion_info.expanded(); + self.cache(value, macro_file.into()); + } // get mapped token in the include! macro file - let Some(InMacroFile { file_id: _, value: mapped_tokens }) = - expinfo.map_range_down(span) + let span = span::SpanData { + range: token.text_range(), + anchor: span::SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID }, + ctx: SyntaxContextId::ROOT, + }; + let Some(InMacroFile { file_id, value: mut mapped_tokens }) = + expansion_info.map_range_down(span) else { continue; }; // if we find one, then return - if let Some(t) = mapped_tokens.into_iter().next() { - return Some((sa, invoc.as_file(), t, span)); - }; + if let Some(t) = mapped_tokens.next() { + return Some((sa, file_id.into(), t, span)); + } } None @@ -672,44 +673,37 @@ impl<'db> SemanticsImpl<'db> { f: &mut dyn FnMut(InFile) -> ControlFlow<()>, ) { let _p = tracing::span!(tracing::Level::INFO, "descend_into_macros"); - let mut include_macro_file_id_and_span = None; - let sa = match token.parent().and_then(|parent| self.analyze_no_infer(&parent)) { - Some(it) => it, - None => { - // if we cannot find a source analyzer for this token, then we try to find out whether this file is included from other file - let Some((it, macro_file_id, mapped_token, s)) = self.is_from_include_file(token) - else { - return; - }; - - include_macro_file_id_and_span = Some((macro_file_id, s)); - token = mapped_token; - it - } - }; - - let span = if let Some((_, s)) = include_macro_file_id_and_span { - s - } else { - match sa.file_id.file_id() { - Some(file_id) => self.db.real_span_map(file_id).span_for_range(token.text_range()), + let (sa, span, file_id) = + match token.parent().and_then(|parent| self.analyze_no_infer(&parent)) { + Some(sa) => match sa.file_id.file_id() { + Some(file_id) => ( + sa, + self.db.real_span_map(file_id).span_for_range(token.text_range()), + file_id.into(), + ), + None => { + stdx::never!(); + return; + } + }, None => { - stdx::never!(); - return; + // if we cannot find a source analyzer for this token, then we try to find out + // whether this file is an included file and treat that as the include input + let Some((it, macro_file_id, mapped_token, s)) = + self.is_from_include_file(token) + else { + return; + }; + token = mapped_token; + (it, s, macro_file_id) } - } - }; + }; let mut cache = self.expansion_info_cache.borrow_mut(); let mut mcache = self.macro_call_cache.borrow_mut(); let def_map = sa.resolver.def_map(); - let mut stack: Vec<(_, SmallVec<[_; 2]>)> = - if let Some((macro_file_id, _)) = include_macro_file_id_and_span { - vec![(macro_file_id, smallvec![token])] - } else { - vec![(sa.file_id, smallvec![token])] - }; + let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![(file_id, smallvec![token])]; let mut process_expansion_for_token = |stack: &mut Vec<_>, macro_file| { let expansion_info = cache diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index a596134178a75..f27eae931f03d 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -303,14 +303,18 @@ impl Definition { DefWithBody::InTypeConst(_) => return SearchScope::empty(), }; return match def { - Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)), + Some(def) => SearchScope::file_range( + def.as_ref().original_file_range_with_macro_call_body(db), + ), None => SearchScope::single_file(file_id), }; } if let Definition::SelfType(impl_) = self { return match impl_.source(db).map(|src| src.syntax().cloned()) { - Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)), + Some(def) => SearchScope::file_range( + def.as_ref().original_file_range_with_macro_call_body(db), + ), None => SearchScope::single_file(file_id), }; } @@ -327,7 +331,9 @@ impl Definition { hir::GenericDef::Const(it) => it.source(db).map(|src| src.syntax().cloned()), }; return match def { - Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)), + Some(def) => SearchScope::file_range( + def.as_ref().original_file_range_with_macro_call_body(db), + ), None => SearchScope::single_file(file_id), }; } diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 073e0036182c5..4fed1f9158ce2 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -241,9 +241,8 @@ mod tests { fn goto_def_in_included_file() { check( r#" +//- minicore:include //- /main.rs -#[rustc_builtin_macro] -macro_rules! include {} include!("a.rs"); @@ -256,6 +255,35 @@ fn func_in_include() { //^^^^^^^^^^^^^^^ } +fn foo() { + func_in_include$0(); +} +"#, + ); + } + + #[test] + fn goto_def_in_included_file_nested() { + check( + r#" +//- minicore:include +//- /main.rs + +macro_rules! passthrough { + ($($tt:tt)*) => { $($tt)* } +} + +passthrough!(include!("a.rs")); + +fn main() { + foo(); +} + +//- /a.rs +fn func_in_include() { + //^^^^^^^^^^^^^^^ +} + fn foo() { func_in_include$0(); } From a158fb33effaee88bfce664a4dd201c61ff4bb10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Wed, 31 Jan 2024 11:05:41 +0100 Subject: [PATCH 147/246] Improve `io::Read::read_buf_exact` error case - Use `const_io_error` instead of `Error::new` - Use the same message as `read_exact` --- library/std/src/io/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 8fca66fa17c5e..ee79d47ddd9f1 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -994,7 +994,10 @@ pub trait Read { } if cursor.written() == prev_written { - return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill buffer")); + return Err(error::const_io_error!( + ErrorKind::UnexpectedEof, + "failed to fill whole buffer" + )); } } From 62ff8f33d4afae2f701d2f342a5dd4752f405faa Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Wed, 31 Jan 2024 21:26:30 +0800 Subject: [PATCH 148/246] minor: correct `close` to `closure` --- crates/hir-ty/src/mir/eval.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 26d0229698aa4..f441b7636bcde 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -359,8 +359,8 @@ impl MirEvalError { func )?; } - Either::Right(close) => { - writeln!(f, "In {:?}", close)?; + Either::Right(closure) => { + writeln!(f, "In {:?}", closure)?; } } let source_map = db.body_with_source_map(*def).1; From 7ea4dbbadbec741358b282ee44ebcd62805ecc41 Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Wed, 31 Jan 2024 13:58:52 +0000 Subject: [PATCH 149/246] Store SHOULD_CAPTURE as AtomicU8 --- library/std/src/panic.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 7f6b563d72959..3728d5b64b865 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -5,7 +5,7 @@ use crate::any::Any; use crate::collections; use crate::panicking; -use crate::sync::atomic::{AtomicUsize, Ordering}; +use crate::sync::atomic::{AtomicU8, Ordering}; use crate::sync::{Mutex, RwLock}; use crate::thread::Result; @@ -228,7 +228,7 @@ impl BacktraceStyle { if cfg!(feature = "backtrace") { Some(BacktraceStyle::Full) } else { None } } - fn as_usize(self) -> usize { + fn as_u8(self) -> u8 { match self { BacktraceStyle::Short => 1, BacktraceStyle::Full => 2, @@ -236,7 +236,7 @@ impl BacktraceStyle { } } - fn from_usize(s: usize) -> Option { + fn from_u8(s: u8) -> Option { Some(match s { 0 => return None, 1 => BacktraceStyle::Short, @@ -251,7 +251,7 @@ impl BacktraceStyle { // that backtrace. // // Internally stores equivalent of an Option. -static SHOULD_CAPTURE: AtomicUsize = AtomicUsize::new(0); +static SHOULD_CAPTURE: AtomicU8 = AtomicU8::new(0); /// Configure whether the default panic hook will capture and display a /// backtrace. @@ -264,7 +264,7 @@ pub fn set_backtrace_style(style: BacktraceStyle) { // If the `backtrace` feature of this crate isn't enabled, skip setting. return; } - SHOULD_CAPTURE.store(style.as_usize(), Ordering::Release); + SHOULD_CAPTURE.store(style.as_u8(), Ordering::Release); } /// Checks whether the standard library's panic hook will capture and print a @@ -296,7 +296,7 @@ pub fn get_backtrace_style() -> Option { // to optimize away callers. return None; } - if let Some(style) = BacktraceStyle::from_usize(SHOULD_CAPTURE.load(Ordering::Acquire)) { + if let Some(style) = BacktraceStyle::from_u8(SHOULD_CAPTURE.load(Ordering::Acquire)) { return Some(style); } From 8eb48b4f4c6e3d48f2600159a75184ec4d74b249 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 31 Jan 2024 15:08:08 +0100 Subject: [PATCH 150/246] Update data layouts in custom target tests for LLVM 18 Fixes https://github.com/rust-lang/rust/issues/120492. --- tests/run-make/rust-lld-custom-target/custom-target.json | 2 +- tests/run-make/rustdoc-target-spec-json-path/target.json | 2 +- tests/run-make/target-specs/my-awesome-platform.json | 2 +- .../target-specs/my-x86_64-unknown-linux-gnu-platform.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/run-make/rust-lld-custom-target/custom-target.json b/tests/run-make/rust-lld-custom-target/custom-target.json index 7828a99f235c1..e2c64cbdb43c2 100644 --- a/tests/run-make/rust-lld-custom-target/custom-target.json +++ b/tests/run-make/rust-lld-custom-target/custom-target.json @@ -2,7 +2,7 @@ "arch": "x86_64", "cpu": "x86-64", "crt-static-respected": true, - "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "gnu", "has-rpath": true, diff --git a/tests/run-make/rustdoc-target-spec-json-path/target.json b/tests/run-make/rustdoc-target-spec-json-path/target.json index 34357182c205e..c478f1196fae0 100644 --- a/tests/run-make/rustdoc-target-spec-json-path/target.json +++ b/tests/run-make/rustdoc-target-spec-json-path/target.json @@ -2,7 +2,7 @@ "arch": "x86_64", "cpu": "x86-64", "crt-static-respected": true, - "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "gnu", "executables": true, diff --git a/tests/run-make/target-specs/my-awesome-platform.json b/tests/run-make/target-specs/my-awesome-platform.json index 00de3de05f07a..1673ef7bd54d1 100644 --- a/tests/run-make/target-specs/my-awesome-platform.json +++ b/tests/run-make/target-specs/my-awesome-platform.json @@ -1,5 +1,5 @@ { - "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128", + "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", "linker-flavor": "gcc", "llvm-target": "i686-unknown-linux-gnu", "target-endian": "little", diff --git a/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json b/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json index 6d5e964ed4fee..0cafce15a9fef 100644 --- a/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json +++ b/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json @@ -1,6 +1,6 @@ { "pre-link-args": {"gcc": ["-m64"]}, - "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", "linker-flavor": "gcc", "llvm-target": "x86_64-unknown-linux-gnu", "target-endian": "little", From f7531f18b8279141d1afc20d016c82e6c627eab0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 31 Jan 2024 16:16:11 +0000 Subject: [PATCH 151/246] Remove has_errors check that has no effect --- .../src/traits/error_reporting/type_err_ctxt_ext.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index dee3e14f3c918..4f372eff8232c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -448,8 +448,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // FIXME(effects) let predicate_is_const = false; - if let Some(guar) = self.dcx().has_errors() - && trait_predicate.references_error() + if let Err(guar) = trait_predicate.error_reported() { return guar; } From a6b1e433dad909d24c931a289b2daa493804769d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 31 Jan 2024 16:24:07 +0000 Subject: [PATCH 152/246] Remove a has_errors check that only hides errors after unrelated items have errored. --- .../traits/error_reporting/type_err_ctxt_ext.rs | 3 --- tests/ui/closures/issue-78720.rs | 1 + tests/ui/closures/issue-78720.stderr | 16 +++++++++++----- .../defaults/rp_impl_trait_fail.rs | 2 +- .../defaults/rp_impl_trait_fail.stderr | 16 ++++++++++++++-- .../generic_const_exprs/issue-62504.full.stderr | 16 ++++++++++++++-- .../generic_const_exprs/issue-62504.min.stderr | 16 ++++++++++++++-- .../generic_const_exprs/issue-62504.rs | 1 + tests/ui/consts/issue-104609.rs | 1 + tests/ui/consts/issue-104609.stderr | 11 +++++++++-- tests/ui/inference/need_type_info/type-alias.rs | 2 +- .../inference/need_type_info/type-alias.stderr | 8 +++++++- tests/ui/typeck/issue-104510-ice.rs | 2 +- tests/ui/typeck/issue-104510-ice.stderr | 16 ++++++++++++++-- 14 files changed, 89 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 4f372eff8232c..c437b97b03eee 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2624,9 +2624,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Some(e) = self.tainted_by_errors() { return e; } - if let Some(e) = self.dcx().has_errors() { - return e; - } self.emit_inference_failure_err( obligation.cause.body_id, diff --git a/tests/ui/closures/issue-78720.rs b/tests/ui/closures/issue-78720.rs index 4cdb9f491130c..0e1f78ae3c69b 100644 --- a/tests/ui/closures/issue-78720.rs +++ b/tests/ui/closures/issue-78720.rs @@ -1,6 +1,7 @@ fn server() -> impl { //~^ ERROR at least one trait must be specified ().map2(|| "") + //~^ ERROR type annotations needed } trait FilterBase2 { diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr index 5d65c87b0fd61..d8d3811af5a74 100644 --- a/tests/ui/closures/issue-78720.stderr +++ b/tests/ui/closures/issue-78720.stderr @@ -5,7 +5,7 @@ LL | fn server() -> impl { | ^^^^ error[E0412]: cannot find type `F` in this scope - --> $DIR/issue-78720.rs:13:12 + --> $DIR/issue-78720.rs:14:12 | LL | _func: F, | ^ @@ -22,8 +22,14 @@ help: you might be missing a type parameter LL | struct Map2 { | +++ +error[E0282]: type annotations needed + --> $DIR/issue-78720.rs:3:5 + | +LL | ().map2(|| "") + | ^^^^^^^^^^^^^^ cannot infer type + error[E0308]: mismatched types - --> $DIR/issue-78720.rs:7:39 + --> $DIR/issue-78720.rs:8:39 | LL | fn map2(self, f: F) -> Map2 {} | ^^ expected `Map2`, found `()` @@ -32,7 +38,7 @@ LL | fn map2(self, f: F) -> Map2 {} found unit type `()` error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/issue-78720.rs:7:16 + --> $DIR/issue-78720.rs:8:16 | LL | fn map2(self, f: F) -> Map2 {} | ^^^^ doesn't have a size known at compile-time @@ -47,7 +53,7 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn map2(&self, f: F) -> Map2 {} | + -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0277, E0308, E0412. +Some errors have detailed explanations: E0277, E0282, E0308, E0412. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs b/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs index 80013e7b4b230..ba41bf38a3379 100644 --- a/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs +++ b/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs @@ -25,6 +25,6 @@ fn owo() -> impl Traitor { fn main() { rawr(); - uwu(); + uwu(); //~ ERROR: type annotations needed owo(); } diff --git a/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr index a46bd53520b53..4ed1c0ded9f86 100644 --- a/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -31,6 +31,18 @@ LL | 1_u64 | = help: the trait `Traitor<1, 2>` is implemented for `u64` -error: aborting due to 3 previous errors +error[E0282]: type annotations needed + --> $DIR/rp_impl_trait_fail.rs:28:5 + | +LL | uwu(); + | ^^^ cannot infer the value of the const parameter `N` declared on the function `uwu` + | +help: consider specifying the generic argument + | +LL | uwu::(); + | +++++ + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0282. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr index 0742db398c9c4..87e26ce85dcfd 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr @@ -15,6 +15,18 @@ LL | ArrayHolder([0; Self::SIZE]) | = help: try adding a `where` bound using this expression: `where [(); Self::SIZE]:` -error: aborting due to 2 previous errors +error[E0282]: type annotations needed for `ArrayHolder` + --> $DIR/issue-62504.rs:26:9 + | +LL | let mut array = ArrayHolder::new(); + | ^^^^^^^^^ + | +help: consider giving `array` an explicit type, where the value of const parameter `X` is specified + | +LL | let mut array: ArrayHolder = ArrayHolder::new(); + | ++++++++++++++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr index 65822856e1d7c..1664669eee05a 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr @@ -22,6 +22,18 @@ note: tuple struct defined here LL | struct ArrayHolder([u32; X]); | ^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0282]: type annotations needed for `ArrayHolder` + --> $DIR/issue-62504.rs:26:9 + | +LL | let mut array = ArrayHolder::new(); + | ^^^^^^^^^ + | +help: consider giving `array` an explicit type, where the value of const parameter `X` is specified + | +LL | let mut array: ArrayHolder = ArrayHolder::new(); + | ++++++++++++++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.rs b/tests/ui/const-generics/generic_const_exprs/issue-62504.rs index a97f4b8ff3131..6f40a9abfa796 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-62504.rs +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.rs @@ -24,4 +24,5 @@ impl ArrayHolder { fn main() { let mut array = ArrayHolder::new(); + //~^ ERROR: type annotations needed } diff --git a/tests/ui/consts/issue-104609.rs b/tests/ui/consts/issue-104609.rs index 01fd1c48cf803..9ee83b409c16f 100644 --- a/tests/ui/consts/issue-104609.rs +++ b/tests/ui/consts/issue-104609.rs @@ -5,6 +5,7 @@ fn foo() { unsafe fn bar() { std::mem::transmute::<_, *mut _>(1_u8); + //~^ ERROR: type annotations needed } fn main() {} diff --git a/tests/ui/consts/issue-104609.stderr b/tests/ui/consts/issue-104609.stderr index 8d0526978ed9e..fe84d83725fd2 100644 --- a/tests/ui/consts/issue-104609.stderr +++ b/tests/ui/consts/issue-104609.stderr @@ -4,6 +4,13 @@ error[E0425]: cannot find value `oops` in this scope LL | oops; | ^^^^ not found in this scope -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/issue-104609.rs:7:5 + | +LL | std::mem::transmute::<_, *mut _>(1_u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Dst` declared on the function `transmute` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0425`. +Some errors have detailed explanations: E0282, E0425. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/type-alias.rs b/tests/ui/inference/need_type_info/type-alias.rs index f921b046b6cac..b24af2d484954 100644 --- a/tests/ui/inference/need_type_info/type-alias.rs +++ b/tests/ui/inference/need_type_info/type-alias.rs @@ -15,7 +15,7 @@ fn direct_alias() { type IndirectAlias = Ty>; fn indirect_alias() { - IndirectAlias::new(); + IndirectAlias::new(); //~ ERROR: type annotations needed // FIXME: This should also emit an error. // // Added it separately as `type-alias-indirect.rs` diff --git a/tests/ui/inference/need_type_info/type-alias.stderr b/tests/ui/inference/need_type_info/type-alias.stderr index cc7053bf385ff..2c39a3f56466f 100644 --- a/tests/ui/inference/need_type_info/type-alias.stderr +++ b/tests/ui/inference/need_type_info/type-alias.stderr @@ -4,12 +4,18 @@ error[E0282]: type annotations needed LL | DirectAlias::new() | ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` +error[E0282]: type annotations needed + --> $DIR/type-alias.rs:18:5 + | +LL | IndirectAlias::new(); + | ^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias` + error[E0282]: type annotations needed --> $DIR/type-alias.rs:32:5 | LL | DirectButWithDefaultAlias::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/typeck/issue-104510-ice.rs b/tests/ui/typeck/issue-104510-ice.rs index 157bdf07e3826..635cc8fad66f1 100644 --- a/tests/ui/typeck/issue-104510-ice.rs +++ b/tests/ui/typeck/issue-104510-ice.rs @@ -6,7 +6,7 @@ struct W(Oops); unsafe fn test() { let j = W(()); - let pointer = &j as *const _; + let pointer = &j as *const _; //~ ERROR type annotations needed core::arch::asm!( "nop", in("eax") pointer, diff --git a/tests/ui/typeck/issue-104510-ice.stderr b/tests/ui/typeck/issue-104510-ice.stderr index 143139b2c089c..774e52681849f 100644 --- a/tests/ui/typeck/issue-104510-ice.stderr +++ b/tests/ui/typeck/issue-104510-ice.stderr @@ -4,6 +4,18 @@ error[E0412]: cannot find type `Oops` in this scope LL | struct W(Oops); | ^^^^ not found in this scope -error: aborting due to 1 previous error +error[E0282]: type annotations needed for `*const W` + --> $DIR/issue-104510-ice.rs:9:9 + | +LL | let pointer = &j as *const _; + | ^^^^^^^ + | +help: consider giving `pointer` an explicit type, where the type for type parameter `T` is specified + | +LL | let pointer: *const W = &j as *const _; + | +++++++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0412`. +Some errors have detailed explanations: E0282, E0412. +For more information about an error, try `rustc --explain E0282`. From 28f250d6a66d307b79c7c47a57b04c3ea6a453a5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 31 Jan 2024 16:27:58 +0000 Subject: [PATCH 153/246] Remove a has_errors check that does not prevent follow up error noise --- .../traits/error_reporting/type_err_ctxt_ext.rs | 4 ---- .../parameter-defaults.stderr | 2 +- tests/ui/parser/issues/issue-89574.rs | 2 ++ tests/ui/parser/issues/issue-89574.stderr | 17 ++++++++++++++++- ...g-closing-angle-bracket-eq-constraint.stderr | 4 ++-- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index c437b97b03eee..93e137061c814 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2641,10 +2641,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Some(e) = self.tainted_by_errors() { return e; } - if let Some(e) = self.dcx().has_errors() { - // no need to overload user in such cases - return e; - } let SubtypePredicate { a_is_expected: _, a, b } = data; // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); diff --git a/tests/ui/generic-const-items/parameter-defaults.stderr b/tests/ui/generic-const-items/parameter-defaults.stderr index 697423e8dc399..b8220af5d0e93 100644 --- a/tests/ui/generic-const-items/parameter-defaults.stderr +++ b/tests/ui/generic-const-items/parameter-defaults.stderr @@ -8,7 +8,7 @@ error[E0282]: type annotations needed for `Option` --> $DIR/parameter-defaults.rs:13:9 | LL | let _ = NONE; - | ^ + | ^ ---- type must be known at this point | help: consider giving this pattern a type, where the type for type parameter `T` is specified | diff --git a/tests/ui/parser/issues/issue-89574.rs b/tests/ui/parser/issues/issue-89574.rs index 0a477f1aa5fb6..bafb0ce5e6680 100644 --- a/tests/ui/parser/issues/issue-89574.rs +++ b/tests/ui/parser/issues/issue-89574.rs @@ -1,4 +1,6 @@ fn main() { const EMPTY_ARRAY = []; //~^ missing type for `const` item + //~| ERROR type annotations needed + //~| ERROR type annotations needed } diff --git a/tests/ui/parser/issues/issue-89574.stderr b/tests/ui/parser/issues/issue-89574.stderr index 5f8f6f9396938..a0586d41e2e59 100644 --- a/tests/ui/parser/issues/issue-89574.stderr +++ b/tests/ui/parser/issues/issue-89574.stderr @@ -1,8 +1,23 @@ +error[E0282]: type annotations needed + --> $DIR/issue-89574.rs:2:25 + | +LL | const EMPTY_ARRAY = []; + | ^^ cannot infer type + error: missing type for `const` item --> $DIR/issue-89574.rs:2:22 | LL | const EMPTY_ARRAY = []; | ^ help: provide a type for the item: `: ` -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/issue-89574.rs:2:25 + | +LL | const EMPTY_ARRAY = []; + | ^^ cannot infer type + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr index e40d985826282..b21e788aa7300 100644 --- a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr +++ b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr @@ -41,7 +41,7 @@ error[E0282]: type annotations needed for `Vec<_>` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:7 | LL | let v : Vec<(u32,_) = vec![]; - | ^ + | ^ ------ type must be known at this point | help: consider giving `v` an explicit type, where the placeholders `_` are specified | @@ -52,7 +52,7 @@ error[E0282]: type annotations needed for `Vec<_>` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:7 | LL | let v : Vec<'a = vec![]; - | ^ + | ^ ------ type must be known at this point | help: consider giving `v` an explicit type, where the placeholders `_` are specified | From 0eb2adb7e877ceaa7d4919f7b881508ee507ec3b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 26 Jan 2024 17:00:28 +0000 Subject: [PATCH 154/246] Add async bound modifier to enable async Fn bounds --- compiler/rustc_ast/src/ast.rs | 29 ++++++- compiler/rustc_ast_lowering/src/expr.rs | 2 + compiler/rustc_ast_lowering/src/item.rs | 13 ++- compiler/rustc_ast_lowering/src/lib.rs | 19 ++-- compiler/rustc_ast_lowering/src/path.rs | 87 +++++++++++++++++-- compiler/rustc_ast_pretty/src/pprust/state.rs | 21 +++-- compiler/rustc_expand/src/build.rs | 1 + compiler/rustc_parse/src/parser/ty.rs | 16 ++-- compiler/rustc_span/src/hygiene.rs | 3 + compiler/rustc_span/src/symbol.rs | 1 + tests/ui/async-await/async-fn/sugar.rs | 14 +++ tests/ui/stats/hir-stats.stderr | 52 +++++------ 12 files changed, 199 insertions(+), 59 deletions(-) create mode 100644 tests/ui/async-await/async-fn/sugar.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4eb8169d0c37c..296a570de6b33 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -291,12 +291,16 @@ pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID}; #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] pub struct TraitBoundModifiers { pub constness: BoundConstness, + pub asyncness: BoundAsyncness, pub polarity: BoundPolarity, } impl TraitBoundModifiers { - pub const NONE: Self = - Self { constness: BoundConstness::Never, polarity: BoundPolarity::Positive }; + pub const NONE: Self = Self { + constness: BoundConstness::Never, + asyncness: BoundAsyncness::Normal, + polarity: BoundPolarity::Positive, + }; } /// The AST represents all type param bounds as types. @@ -2562,6 +2566,25 @@ impl BoundConstness { } } +/// The asyncness of a trait bound. +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] +#[derive(HashStable_Generic)] +pub enum BoundAsyncness { + /// `Type: Trait` + Normal, + /// `Type: async Trait` + Async(Span), +} + +impl BoundAsyncness { + pub fn as_str(self) -> &'static str { + match self { + Self::Normal => "", + Self::Async(_) => "async", + } + } +} + #[derive(Clone, Encodable, Decodable, Debug)] pub enum FnRetTy { /// Returns type is not specified. @@ -3300,7 +3323,7 @@ mod size_asserts { static_assert_size!(ForeignItem, 96); static_assert_size!(ForeignItemKind, 24); static_assert_size!(GenericArg, 24); - static_assert_size!(GenericBound, 72); + static_assert_size!(GenericBound, 88); static_assert_size!(Generics, 40); static_assert_size!(Impl, 136); static_assert_size!(Item, 136); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 0ad4a59c17eb1..3b00a84e67e9f 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -100,6 +100,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ParenthesizedGenericArgs::Err, &ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, + // Method calls can't have bound modifiers + None, )); let receiver = self.lower_expr(receiver); let args = diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index dd3f7289a60b2..0ff5d96cec252 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -343,14 +343,19 @@ impl<'hir> LoweringContext<'_, 'hir> { let itctx = ImplTraitContext::Universal; let (generics, (trait_ref, lowered_ty)) = self.lower_generics(ast_generics, *constness, id, &itctx, |this| { - let constness = match *constness { - Const::Yes(span) => BoundConstness::Maybe(span), - Const::No => BoundConstness::Never, + let modifiers = TraitBoundModifiers { + constness: match *constness { + Const::Yes(span) => BoundConstness::Maybe(span), + Const::No => BoundConstness::Never, + }, + asyncness: BoundAsyncness::Normal, + // we don't use this in bound lowering + polarity: BoundPolarity::Positive, }; let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref( - constness, + modifiers, trait_ref, &ImplTraitContext::Disallowed(ImplTraitPosition::Trait), ) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3621844efc8d2..7dfef9c07c594 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -131,6 +131,7 @@ struct LoweringContext<'a, 'hir> { allow_gen_future: Lrc<[Symbol]>, allow_async_iterator: Lrc<[Symbol]>, allow_for_await: Lrc<[Symbol]>, + allow_async_fn_traits: Lrc<[Symbol]>, /// Mapping from generics `def_id`s to TAIT generics `def_id`s. /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic @@ -176,6 +177,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { [sym::gen_future].into() }, allow_for_await: [sym::async_iterator].into(), + allow_async_fn_traits: [sym::async_fn_traits].into(), // FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller` // interact with `gen`/`async gen` blocks allow_async_iterator: [sym::gen_future, sym::async_iterator].into(), @@ -1311,7 +1313,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: t.span, }, itctx, - ast::BoundConstness::Never, + TraitBoundModifiers::NONE, ); let bounds = this.arena.alloc_from_iter([bound]); let lifetime_bound = this.elided_dyn_bound(t.span); @@ -1426,7 +1428,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx, // Still, don't pass along the constness here; we don't want to // synthesize any host effect args, it'd only cause problems. - ast::BoundConstness::Never, + TraitBoundModifiers { + constness: BoundConstness::Never, + ..*modifiers + }, )) } BoundPolarity::Maybe(_) => None, @@ -2019,7 +2024,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> hir::GenericBound<'hir> { match tpb { GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait( - self.lower_poly_trait_ref(p, itctx, modifiers.constness.into()), + self.lower_poly_trait_ref(p, itctx, *modifiers), self.lower_trait_bound_modifiers(*modifiers), ), GenericBound::Outlives(lifetime) => { @@ -2192,7 +2197,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_trait_ref( &mut self, - constness: ast::BoundConstness, + modifiers: ast::TraitBoundModifiers, p: &TraitRef, itctx: &ImplTraitContext, ) -> hir::TraitRef<'hir> { @@ -2202,7 +2207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &p.path, ParamMode::Explicit, itctx, - Some(constness), + Some(modifiers), ) { hir::QPath::Resolved(None, path) => path, qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"), @@ -2215,11 +2220,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, p: &PolyTraitRef, itctx: &ImplTraitContext, - constness: ast::BoundConstness, + modifiers: ast::TraitBoundModifiers, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); - let trait_ref = self.lower_trait_ref(constness, &p.trait_ref, itctx); + let trait_ref = self.lower_trait_ref(modifiers, &p.trait_ref, itctx); hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index c679ee56fcd8b..b4f1d7ce8c27a 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -6,12 +6,14 @@ use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs}; use super::{ImplTraitContext, LoweringContext, ParamMode}; use rustc_ast::{self as ast, *}; +use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; +use rustc_hir::def_id::DefId; use rustc_hir::GenericArg; use rustc_middle::span_bug; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; @@ -24,8 +26,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &Path, param_mode: ParamMode, itctx: &ImplTraitContext, - // constness of the impl/bound if this is a trait path - constness: Option, + // modifiers of the impl/bound if this is a trait path + modifiers: Option, ) -> hir::QPath<'hir> { let qself_position = qself.as_ref().map(|q| q.position); let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); @@ -35,10 +37,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let base_res = partial_res.base_res(); let unresolved_segments = partial_res.unresolved_segments(); + let mut res = self.lower_res(base_res); + + // When we have an `async` kw on a bound, map the trait it resolves to. + let mut bound_modifier_allowed_features = None; + if let Some(TraitBoundModifiers { asyncness: BoundAsyncness::Async(_), .. }) = modifiers { + if let Res::Def(DefKind::Trait, def_id) = res { + if let Some((async_def_id, features)) = self.map_trait_to_async_trait(def_id) { + res = Res::Def(DefKind::Trait, async_def_id); + bound_modifier_allowed_features = Some(features); + } else { + panic!(); + } + } else { + panic!(); + } + } + let path_span_lo = p.span.shrink_to_lo(); let proj_start = p.segments.len() - unresolved_segments; let path = self.arena.alloc(hir::Path { - res: self.lower_res(base_res), + res, segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map( |(i, segment)| { let param_mode = match (qself_position, param_mode) { @@ -77,7 +96,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { parenthesized_generic_args, itctx, // if this is the last segment, add constness to the trait path - if i == proj_start - 1 { constness } else { None }, + if i == proj_start - 1 { modifiers.map(|m| m.constness) } else { None }, + bound_modifier_allowed_features.clone(), ) }, )), @@ -88,6 +108,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ), }); + if let Some(bound_modifier_allowed_features) = bound_modifier_allowed_features { + path.span = self.mark_span_with_reason( + DesugaringKind::BoundModifier, + path.span, + Some(bound_modifier_allowed_features), + ); + } + // Simple case, either no projections, or only fully-qualified. // E.g., `std::mem::size_of` or `::Item`. if unresolved_segments == 0 { @@ -125,6 +153,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ParenthesizedGenericArgs::Err, itctx, None, + None, )); let qpath = hir::QPath::TypeRelative(ty, hir_segment); @@ -166,6 +195,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ParenthesizedGenericArgs::Err, &ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, + None, ) })), span: self.lower_span(p.span), @@ -180,6 +210,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { parenthesized_generic_args: ParenthesizedGenericArgs, itctx: &ImplTraitContext, constness: Option, + // Additional features ungated with a bound modifier like `async`. + // This is passed down to the implicit associated type binding in + // parenthesized bounds. + bound_modifier_allowed_features: Option>, ) -> hir::PathSegment<'hir> { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment); let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() { @@ -188,9 +222,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) } GenericArgs::Parenthesized(data) => match parenthesized_generic_args { - ParenthesizedGenericArgs::ParenSugar => { - self.lower_parenthesized_parameter_data(data, itctx) - } + ParenthesizedGenericArgs::ParenSugar => self + .lower_parenthesized_parameter_data( + data, + itctx, + bound_modifier_allowed_features, + ), ParenthesizedGenericArgs::Err => { // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait` let sub = if !data.inputs.is_empty() { @@ -357,6 +394,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, data: &ParenthesizedArgs, itctx: &ImplTraitContext, + bound_modifier_allowed_features: Option>, ) -> (GenericArgsCtor<'hir>, bool) { // Switch to `PassThrough` mode for anonymous lifetimes; this // means that we permit things like `&Ref`, where `Ref` has @@ -392,7 +430,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))]; - let binding = self.assoc_ty_binding(sym::Output, output_ty.span, output_ty); + + // If we have a bound like `async Fn() -> T`, make sure that we mark the + // `Output = T` associated type bound with the right feature gates. + let mut output_span = output_ty.span; + if let Some(bound_modifier_allowed_features) = bound_modifier_allowed_features { + output_span = self.mark_span_with_reason( + DesugaringKind::BoundModifier, + output_span, + Some(bound_modifier_allowed_features), + ); + } + let binding = self.assoc_ty_binding(sym::Output, output_span, output_ty); + ( GenericArgsCtor { args, @@ -429,4 +479,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { kind, } } + + /// When a bound is annotated with `async`, it signals to lowering that the trait + /// that the bound refers to should be mapped to the "async" flavor of the trait. + /// + /// This only needs to be done until we unify `AsyncFn` and `Fn` traits into one + /// that is generic over `async`ness, if that's ever possible, or modify the + /// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`. + fn map_trait_to_async_trait(&self, def_id: DefId) -> Option<(DefId, Lrc<[Symbol]>)> { + let lang_items = self.tcx.lang_items(); + if Some(def_id) == lang_items.fn_trait() { + Some((lang_items.async_fn_trait()?, self.allow_async_fn_traits.clone())) + } else if Some(def_id) == lang_items.fn_mut_trait() { + Some((lang_items.async_fn_mut_trait()?, self.allow_async_fn_traits.clone())) + } else if Some(def_id) == lang_items.fn_once_trait() { + Some((lang_items.async_fn_once_trait()?, self.allow_async_fn_traits.clone())) + } else { + None + } + } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index a6f6f0b29a040..731232bce65cb 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -8,6 +8,7 @@ mod item; use crate::pp::Breaks::{Consistent, Inconsistent}; use crate::pp::{self, Breaks}; use crate::pprust::state::expr::FixupContext; +use ast::TraitBoundModifiers; use rustc_ast::attr::AttrIdGenerator; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind}; @@ -1590,18 +1591,28 @@ impl<'a> State<'a> { } match bound { - GenericBound::Trait(tref, modifier) => { - match modifier.constness { + GenericBound::Trait( + tref, + TraitBoundModifiers { constness, asyncness, polarity }, + ) => { + match constness { ast::BoundConstness::Never => {} ast::BoundConstness::Always(_) | ast::BoundConstness::Maybe(_) => { - self.word_space(modifier.constness.as_str()); + self.word_space(constness.as_str()); } } - match modifier.polarity { + match asyncness { + ast::BoundAsyncness::Normal => {} + ast::BoundAsyncness::Async(_) => { + self.word_space(asyncness.as_str()); + } + } + + match polarity { ast::BoundPolarity::Positive => {} ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => { - self.word(modifier.polarity.as_str()); + self.word(polarity.as_str()); } } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index f9bfebee12e92..5879e025e7dbd 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -141,6 +141,7 @@ impl<'a> ExtCtxt<'a> { } else { ast::BoundConstness::Never }, + asyncness: ast::BoundAsyncness::Normal, }, ) } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a4fb92c67ac68..72089dc2a9129 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -8,14 +8,13 @@ use crate::errors::{ }; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; -use ast::DUMMY_NODE_ID; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, BareFnTy, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds, - GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, - TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, + self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound, + GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, + TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID, }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{kw, sym, Ident}; @@ -880,6 +879,13 @@ impl<'a> Parser<'a> { BoundConstness::Never }; + let asyncness = if self.token.span.at_least_rust_2018() && self.eat_keyword(kw::Async) { + self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span); + BoundAsyncness::Async(self.prev_token.span) + } else { + BoundAsyncness::Normal + }; + let polarity = if self.eat(&token::Question) { BoundPolarity::Maybe(self.prev_token.span) } else if self.eat(&token::Not) { @@ -889,7 +895,7 @@ impl<'a> Parser<'a> { BoundPolarity::Positive }; - Ok(TraitBoundModifiers { constness, polarity }) + Ok(TraitBoundModifiers { constness, asyncness, polarity }) } /// Parses a type bound according to: diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 3d26efec5a654..527938daae410 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1154,6 +1154,8 @@ pub enum DesugaringKind { Await, ForLoop, WhileLoop, + /// `async Fn()` bound modifier + BoundModifier, } impl DesugaringKind { @@ -1169,6 +1171,7 @@ impl DesugaringKind { DesugaringKind::OpaqueTy => "`impl Trait`", DesugaringKind::ForLoop => "`for` loop", DesugaringKind::WhileLoop => "`while` loop", + DesugaringKind::BoundModifier => "trait bound modifier", } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index dbfc89c2d496e..2dca9808ada85 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -423,6 +423,7 @@ symbols! { async_fn_mut, async_fn_once, async_fn_track_caller, + async_fn_traits, async_for_loop, async_iterator, async_iterator_poll_next, diff --git a/tests/ui/async-await/async-fn/sugar.rs b/tests/ui/async-await/async-fn/sugar.rs new file mode 100644 index 0000000000000..868fb799ae4f9 --- /dev/null +++ b/tests/ui/async-await/async-fn/sugar.rs @@ -0,0 +1,14 @@ +// edition: 2021 +// check-pass + +#![feature(async_closure)] + +async fn foo() {} + +async fn call_asyncly(f: impl async Fn(i32) -> i32) -> i32 { + f(1).await +} + +fn main() { + let fut = call_asyncly(|x| async move { x + 1 }); +} diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index 8b9ec30db63f4..2c21c25d7c77e 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -5,8 +5,8 @@ ast-stats-1 GenericArgs 40 ( 0.6%) 1 40 ast-stats-1 - AngleBracketed 40 ( 0.6%) 1 ast-stats-1 Crate 40 ( 0.6%) 1 40 ast-stats-1 ExprField 48 ( 0.7%) 1 48 -ast-stats-1 WherePredicate 56 ( 0.9%) 1 56 -ast-stats-1 - BoundPredicate 56 ( 0.9%) 1 +ast-stats-1 WherePredicate 56 ( 0.8%) 1 56 +ast-stats-1 - BoundPredicate 56 ( 0.8%) 1 ast-stats-1 Attribute 64 ( 1.0%) 2 32 ast-stats-1 - Normal 32 ( 0.5%) 1 ast-stats-1 - DocComment 32 ( 0.5%) 1 @@ -22,38 +22,38 @@ ast-stats-1 - MacCall 32 ( 0.5%) 1 ast-stats-1 - Expr 96 ( 1.5%) 3 ast-stats-1 Param 160 ( 2.4%) 4 40 ast-stats-1 Block 192 ( 2.9%) 6 32 -ast-stats-1 Variant 208 ( 3.2%) 2 104 -ast-stats-1 GenericBound 288 ( 4.4%) 4 72 -ast-stats-1 - Trait 288 ( 4.4%) 4 -ast-stats-1 AssocItem 352 ( 5.4%) 4 88 +ast-stats-1 Variant 208 ( 3.1%) 2 104 +ast-stats-1 GenericBound 352 ( 5.3%) 4 88 +ast-stats-1 - Trait 352 ( 5.3%) 4 +ast-stats-1 AssocItem 352 ( 5.3%) 4 88 ast-stats-1 - Type 176 ( 2.7%) 2 ast-stats-1 - Fn 176 ( 2.7%) 2 ast-stats-1 GenericParam 480 ( 7.3%) 5 96 -ast-stats-1 Pat 504 ( 7.7%) 7 72 +ast-stats-1 Pat 504 ( 7.6%) 7 72 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Wild 72 ( 1.1%) 1 -ast-stats-1 - Ident 360 ( 5.5%) 5 -ast-stats-1 Expr 576 ( 8.8%) 8 72 +ast-stats-1 - Ident 360 ( 5.4%) 5 +ast-stats-1 Expr 576 ( 8.7%) 8 72 ast-stats-1 - Path 72 ( 1.1%) 1 ast-stats-1 - Match 72 ( 1.1%) 1 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Lit 144 ( 2.2%) 2 ast-stats-1 - Block 216 ( 3.3%) 3 -ast-stats-1 PathSegment 720 (11.0%) 30 24 -ast-stats-1 Ty 896 (13.7%) 14 64 +ast-stats-1 PathSegment 720 (10.9%) 30 24 +ast-stats-1 Ty 896 (13.5%) 14 64 ast-stats-1 - Ptr 64 ( 1.0%) 1 ast-stats-1 - Ref 64 ( 1.0%) 1 -ast-stats-1 - ImplicitSelf 128 ( 2.0%) 2 -ast-stats-1 - Path 640 ( 9.8%) 10 -ast-stats-1 Item 1_224 (18.7%) 9 136 +ast-stats-1 - ImplicitSelf 128 ( 1.9%) 2 +ast-stats-1 - Path 640 ( 9.7%) 10 +ast-stats-1 Item 1_224 (18.5%) 9 136 ast-stats-1 - Trait 136 ( 2.1%) 1 ast-stats-1 - Enum 136 ( 2.1%) 1 ast-stats-1 - ForeignMod 136 ( 2.1%) 1 ast-stats-1 - Impl 136 ( 2.1%) 1 -ast-stats-1 - Fn 272 ( 4.2%) 2 +ast-stats-1 - Fn 272 ( 4.1%) 2 ast-stats-1 - Use 408 ( 6.2%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_552 +ast-stats-1 Total 6_616 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -81,39 +81,39 @@ ast-stats-2 - Expr 96 ( 1.3%) 3 ast-stats-2 Param 160 ( 2.2%) 4 40 ast-stats-2 Block 192 ( 2.7%) 6 32 ast-stats-2 Variant 208 ( 2.9%) 2 104 -ast-stats-2 GenericBound 288 ( 4.0%) 4 72 -ast-stats-2 - Trait 288 ( 4.0%) 4 +ast-stats-2 GenericBound 352 ( 4.9%) 4 88 +ast-stats-2 - Trait 352 ( 4.9%) 4 ast-stats-2 AssocItem 352 ( 4.9%) 4 88 -ast-stats-2 - Type 176 ( 2.5%) 2 -ast-stats-2 - Fn 176 ( 2.5%) 2 +ast-stats-2 - Type 176 ( 2.4%) 2 +ast-stats-2 - Fn 176 ( 2.4%) 2 ast-stats-2 GenericParam 480 ( 6.7%) 5 96 ast-stats-2 Pat 504 ( 7.0%) 7 72 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - Wild 72 ( 1.0%) 1 ast-stats-2 - Ident 360 ( 5.0%) 5 -ast-stats-2 Expr 648 ( 9.1%) 9 72 +ast-stats-2 Expr 648 ( 9.0%) 9 72 ast-stats-2 - Path 72 ( 1.0%) 1 ast-stats-2 - Match 72 ( 1.0%) 1 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - InlineAsm 72 ( 1.0%) 1 ast-stats-2 - Lit 144 ( 2.0%) 2 ast-stats-2 - Block 216 ( 3.0%) 3 -ast-stats-2 PathSegment 792 (11.1%) 33 24 -ast-stats-2 Ty 896 (12.5%) 14 64 +ast-stats-2 PathSegment 792 (11.0%) 33 24 +ast-stats-2 Ty 896 (12.4%) 14 64 ast-stats-2 - Ptr 64 ( 0.9%) 1 ast-stats-2 - Ref 64 ( 0.9%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.8%) 2 ast-stats-2 - Path 640 ( 8.9%) 10 -ast-stats-2 Item 1_496 (20.9%) 11 136 +ast-stats-2 Item 1_496 (20.7%) 11 136 ast-stats-2 - Trait 136 ( 1.9%) 1 ast-stats-2 - Enum 136 ( 1.9%) 1 ast-stats-2 - ExternCrate 136 ( 1.9%) 1 ast-stats-2 - ForeignMod 136 ( 1.9%) 1 ast-stats-2 - Impl 136 ( 1.9%) 1 ast-stats-2 - Fn 272 ( 3.8%) 2 -ast-stats-2 - Use 544 ( 7.6%) 4 +ast-stats-2 - Use 544 ( 7.5%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_152 +ast-stats-2 Total 7_216 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size From cd2fd34ca68f701ade233a980093ee4444f7da3a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 26 Jan 2024 17:00:34 +0000 Subject: [PATCH 155/246] Add tests --- tests/ui/async-await/async-fn/dyn-pos.rs | 14 +++ tests/ui/async-await/async-fn/dyn-pos.stderr | 87 +++++++++++++++++++ tests/ui/async-await/async-fn/edition-2015.rs | 8 ++ .../async-await/async-fn/edition-2015.stderr | 22 +++++ tests/ui/async-await/async-fn/impl-header.rs | 8 ++ .../async-await/async-fn/impl-header.stderr | 8 ++ tests/ui/async-await/async-fn/impl-trait.rs | 15 ++++ .../async-await/async-fn/method-call-pos.rs | 7 ++ .../async-fn/method-call-pos.stderr | 14 +++ 9 files changed, 183 insertions(+) create mode 100644 tests/ui/async-await/async-fn/dyn-pos.rs create mode 100644 tests/ui/async-await/async-fn/dyn-pos.stderr create mode 100644 tests/ui/async-await/async-fn/edition-2015.rs create mode 100644 tests/ui/async-await/async-fn/edition-2015.stderr create mode 100644 tests/ui/async-await/async-fn/impl-header.rs create mode 100644 tests/ui/async-await/async-fn/impl-header.stderr create mode 100644 tests/ui/async-await/async-fn/impl-trait.rs create mode 100644 tests/ui/async-await/async-fn/method-call-pos.rs create mode 100644 tests/ui/async-await/async-fn/method-call-pos.stderr diff --git a/tests/ui/async-await/async-fn/dyn-pos.rs b/tests/ui/async-await/async-fn/dyn-pos.rs new file mode 100644 index 0000000000000..3201fb8dbf309 --- /dev/null +++ b/tests/ui/async-await/async-fn/dyn-pos.rs @@ -0,0 +1,14 @@ +// edition:2018 + +#![feature(async_closure)] + +fn foo(x: &dyn async Fn()) {} +//~^ ERROR the trait `AsyncFn` cannot be made into an object +//~| ERROR the trait `AsyncFn` cannot be made into an object +//~| ERROR the trait `AsyncFn` cannot be made into an object +//~| ERROR the trait `AsyncFn` cannot be made into an object +//~| ERROR the trait `AsyncFnMut` cannot be made into an object +//~| ERROR the trait `AsyncFnMut` cannot be made into an object +//~| ERROR the trait `AsyncFnMut` cannot be made into an object + +fn main() {} diff --git a/tests/ui/async-await/async-fn/dyn-pos.stderr b/tests/ui/async-await/async-fn/dyn-pos.stderr new file mode 100644 index 0000000000000..c93235265160b --- /dev/null +++ b/tests/ui/async-await/async-fn/dyn-pos.stderr @@ -0,0 +1,87 @@ +error[E0038]: the trait `AsyncFn` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFn` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture` + +error[E0038]: the trait `AsyncFnMut` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture` + +error[E0038]: the trait `AsyncFn` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFn` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0038]: the trait `AsyncFnMut` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0038]: the trait `AsyncFn` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFn` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0038]: the trait `AsyncFnMut` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0038]: the trait `AsyncFn` cannot be made into an object + --> $DIR/dyn-pos.rs:5:12 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^^^^^ `AsyncFn` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture` + ::: $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs new file mode 100644 index 0000000000000..287d05ecacb71 --- /dev/null +++ b/tests/ui/async-await/async-fn/edition-2015.rs @@ -0,0 +1,8 @@ +// FIXME(async_closures): This error message could be made better. + +fn foo(x: impl async Fn()) -> impl async Fn() {} +//~^ ERROR expected +//~| ERROR expected +//~| ERROR expected + +fn main() {} diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr new file mode 100644 index 0000000000000..e79b92ccf9f3d --- /dev/null +++ b/tests/ui/async-await/async-fn/edition-2015.stderr @@ -0,0 +1,22 @@ +error: expected one of `:` or `|`, found `)` + --> $DIR/edition-2015.rs:3:26 + | +LL | fn foo(x: impl async Fn()) -> impl async Fn() {} + | ^ expected one of `:` or `|` + +error: expected one of `(`, `)`, `+`, `,`, `::`, or `<`, found `Fn` + --> $DIR/edition-2015.rs:3:22 + | +LL | fn foo(x: impl async Fn()) -> impl async Fn() {} + | -^^ expected one of `(`, `)`, `+`, `,`, `::`, or `<` + | | + | help: missing `,` + +error: expected one of `(`, `+`, `::`, `<`, `where`, or `{`, found `Fn` + --> $DIR/edition-2015.rs:3:42 + | +LL | fn foo(x: impl async Fn()) -> impl async Fn() {} + | ^^ expected one of `(`, `+`, `::`, `<`, `where`, or `{` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/async-await/async-fn/impl-header.rs b/tests/ui/async-await/async-fn/impl-header.rs new file mode 100644 index 0000000000000..fb1844384ae08 --- /dev/null +++ b/tests/ui/async-await/async-fn/impl-header.rs @@ -0,0 +1,8 @@ +// edition:2018 + +struct F; + +impl async Fn<()> for F {} +//~^ ERROR expected type, found keyword `async` + +fn main() {} diff --git a/tests/ui/async-await/async-fn/impl-header.stderr b/tests/ui/async-await/async-fn/impl-header.stderr new file mode 100644 index 0000000000000..02cb432624274 --- /dev/null +++ b/tests/ui/async-await/async-fn/impl-header.stderr @@ -0,0 +1,8 @@ +error: expected type, found keyword `async` + --> $DIR/impl-header.rs:5:6 + | +LL | impl async Fn<()> for F {} + | ^^^^^ expected type + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/async-fn/impl-trait.rs b/tests/ui/async-await/async-fn/impl-trait.rs new file mode 100644 index 0000000000000..97f6696fe1434 --- /dev/null +++ b/tests/ui/async-await/async-fn/impl-trait.rs @@ -0,0 +1,15 @@ +// edition:2018 +// check-pass + +#![feature(async_closure, type_alias_impl_trait)] + +type Tait = impl async Fn(); +fn tait() -> Tait { + || async {} +} + +fn foo(x: impl async Fn()) -> impl async Fn() { x } + +fn param() {} + +fn main() {} diff --git a/tests/ui/async-await/async-fn/method-call-pos.rs b/tests/ui/async-await/async-fn/method-call-pos.rs new file mode 100644 index 0000000000000..aaa0245b9868f --- /dev/null +++ b/tests/ui/async-await/async-fn/method-call-pos.rs @@ -0,0 +1,7 @@ +// edition:2018 + +fn main() { + <_ as async Fn()>(|| async {}); + //~^ ERROR expected identifier, found keyword `async` + //~| ERROR expected one of +} diff --git a/tests/ui/async-await/async-fn/method-call-pos.stderr b/tests/ui/async-await/async-fn/method-call-pos.stderr new file mode 100644 index 0000000000000..527515a1b44cc --- /dev/null +++ b/tests/ui/async-await/async-fn/method-call-pos.stderr @@ -0,0 +1,14 @@ +error: expected identifier, found keyword `async` + --> $DIR/method-call-pos.rs:4:11 + | +LL | <_ as async Fn()>(|| async {}); + | ^^^^^ expected identifier, found keyword + +error: expected one of `(`, `::`, `<`, or `>`, found `Fn` + --> $DIR/method-call-pos.rs:4:17 + | +LL | <_ as async Fn()>(|| async {}); + | ^^ expected one of `(`, `::`, `<`, or `>` + +error: aborting due to 2 previous errors + From 54db272cc972f232cc50a7c6dff30140f904738a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 26 Jan 2024 17:15:43 +0000 Subject: [PATCH 156/246] Better error message in ed 2015 --- compiler/rustc_parse/messages.ftl | 2 + compiler/rustc_parse/src/errors.rs | 9 ++++ compiler/rustc_parse/src/parser/ty.rs | 15 +++++- .../async-fn/edition-2015-not-async-bound.rs | 10 ++++ tests/ui/async-await/async-fn/edition-2015.rs | 11 ++-- .../async-await/async-fn/edition-2015.stderr | 51 +++++++++++++------ 6 files changed, 75 insertions(+), 23 deletions(-) create mode 100644 tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index aac8c0b310320..7c2ecf34c1754 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -22,6 +22,8 @@ parse_associated_static_item_not_allowed = associated `static` items are not all parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later +parse_async_bound_modifier_in_2015 = `async` trait bounds are only allowed in Rust 2018 or later + parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015 .label = to use `async fn`, switch to Rust 2018 or later diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 4e4bf9bdad98a..86a64d90deb20 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1588,6 +1588,15 @@ pub(crate) struct AsyncMoveBlockIn2015 { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parse_async_bound_modifier_in_2015)] +pub(crate) struct AsyncBoundModifierIn2015 { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub help: HelpUseLatestEdition, +} + #[derive(Diagnostic)] #[diag(parse_self_argument_pointer)] pub(crate) struct SelfArgumentPointer { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 72089dc2a9129..5fe54a536a7f1 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -3,8 +3,8 @@ use super::{Parser, PathStyle, TokenType}; use crate::errors::{ self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType, FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg, - InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, - ReturnTypesUseThinArrow, + HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, + NestedCVariadicType, ReturnTypesUseThinArrow, }; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; @@ -882,6 +882,17 @@ impl<'a> Parser<'a> { let asyncness = if self.token.span.at_least_rust_2018() && self.eat_keyword(kw::Async) { self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span); BoundAsyncness::Async(self.prev_token.span) + } else if self.may_recover() + && self.token.span.is_rust_2015() + && self.is_kw_followed_by_ident(kw::Async) + { + self.bump(); // eat `async` + self.dcx().emit_err(errors::AsyncBoundModifierIn2015 { + span: self.prev_token.span, + help: HelpUseLatestEdition::new(), + }); + self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span); + BoundAsyncness::Async(self.prev_token.span) } else { BoundAsyncness::Normal }; diff --git a/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs b/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs new file mode 100644 index 0000000000000..6436787b665d7 --- /dev/null +++ b/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs @@ -0,0 +1,10 @@ +// check-pass +// Make sure that we don't eagerly recover `async ::Bound` in edition 2015. + +mod async { + pub trait Foo {} +} + +fn test(x: impl async ::Foo) {} + +fn main() {} diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs index 287d05ecacb71..83b9d415ddab4 100644 --- a/tests/ui/async-await/async-fn/edition-2015.rs +++ b/tests/ui/async-await/async-fn/edition-2015.rs @@ -1,8 +1,7 @@ -// FIXME(async_closures): This error message could be made better. - -fn foo(x: impl async Fn()) -> impl async Fn() {} -//~^ ERROR expected -//~| ERROR expected -//~| ERROR expected +fn foo(x: impl async Fn()) -> impl async Fn() { x } +//~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later +//~| ERROR `async` trait bounds are only allowed in Rust 2018 or later +//~| ERROR async closures are unstable +//~| ERROR async closures are unstable fn main() {} diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr index e79b92ccf9f3d..0029d53868d4f 100644 --- a/tests/ui/async-await/async-fn/edition-2015.stderr +++ b/tests/ui/async-await/async-fn/edition-2015.stderr @@ -1,22 +1,43 @@ -error: expected one of `:` or `|`, found `)` - --> $DIR/edition-2015.rs:3:26 +error: `async` trait bounds are only allowed in Rust 2018 or later + --> $DIR/edition-2015.rs:1:16 | -LL | fn foo(x: impl async Fn()) -> impl async Fn() {} - | ^ expected one of `:` or `|` +LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } + | ^^^^^ + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error: `async` trait bounds are only allowed in Rust 2018 or later + --> $DIR/edition-2015.rs:1:36 + | +LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } + | ^^^^^ + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide -error: expected one of `(`, `)`, `+`, `,`, `::`, or `<`, found `Fn` - --> $DIR/edition-2015.rs:3:22 +error[E0658]: async closures are unstable + --> $DIR/edition-2015.rs:1:16 + | +LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } + | ^^^^^ | -LL | fn foo(x: impl async Fn()) -> impl async Fn() {} - | -^^ expected one of `(`, `)`, `+`, `,`, `::`, or `<` - | | - | help: missing `,` + = note: see issue #62290 for more information + = help: add `#![feature(async_closure)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: to use an async block, remove the `||`: `async {` -error: expected one of `(`, `+`, `::`, `<`, `where`, or `{`, found `Fn` - --> $DIR/edition-2015.rs:3:42 +error[E0658]: async closures are unstable + --> $DIR/edition-2015.rs:1:36 + | +LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } + | ^^^^^ | -LL | fn foo(x: impl async Fn()) -> impl async Fn() {} - | ^^ expected one of `(`, `+`, `::`, `<`, `where`, or `{` + = note: see issue #62290 for more information + = help: add `#![feature(async_closure)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: to use an async block, remove the `||`: `async {` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0658`. From 3913c9a0cacf4bacb4ca1c6255271d54ec995f02 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 26 Jan 2024 17:33:42 +0000 Subject: [PATCH 157/246] Error on incorrect item kind in async bound --- compiler/rustc_ast_lowering/messages.ftl | 6 ++++ compiler/rustc_ast_lowering/src/errors.rs | 15 ++++++++++ compiler/rustc_ast_lowering/src/path.rs | 29 +++++++++++++------ tests/ui/async-await/async-fn/not-a-trait.rs | 13 +++++++++ .../async-await/async-fn/not-a-trait.stderr | 16 ++++++++++ tests/ui/async-await/async-fn/wrong-trait.rs | 10 +++++++ .../async-await/async-fn/wrong-trait.stderr | 8 +++++ 7 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 tests/ui/async-await/async-fn/not-a-trait.rs create mode 100644 tests/ui/async-await/async-fn/not-a-trait.stderr create mode 100644 tests/ui/async-await/async-fn/wrong-trait.rs create mode 100644 tests/ui/async-await/async-fn/wrong-trait.stderr diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 8615016cda599..e0dc227ca4c01 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -11,6 +11,12 @@ ast_lowering_argument = argument ast_lowering_assoc_ty_parentheses = parenthesized generic arguments cannot be used in associated type constraints +ast_lowering_async_bound_not_on_trait = + `async` bound modifier only allowed on trait, not `{$descr}` + +ast_lowering_async_bound_only_for_fn_traits = + `async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits + ast_lowering_async_coroutines_not_supported = `async` coroutines are not yet supported diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 51bb8a96fad26..7658dfa5d5f63 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -395,3 +395,18 @@ pub(crate) struct GenericParamDefaultInBinder { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(ast_lowering_async_bound_not_on_trait)] +pub(crate) struct AsyncBoundNotOnTrait { + #[primary_span] + pub span: Span, + pub descr: &'static str, +} + +#[derive(Diagnostic)] +#[diag(ast_lowering_async_bound_only_for_fn_traits)] +pub(crate) struct AsyncBoundOnlyForFnTraits { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index b4f1d7ce8c27a..b58ac5c3dae43 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -1,6 +1,8 @@ use crate::ImplTraitPosition; -use super::errors::{GenericTypeWithParentheses, UseAngleBrackets}; +use super::errors::{ + AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, GenericTypeWithParentheses, UseAngleBrackets, +}; use super::ResolverAstLoweringExt; use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs}; use super::{ImplTraitContext, LoweringContext, ParamMode}; @@ -42,15 +44,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // When we have an `async` kw on a bound, map the trait it resolves to. let mut bound_modifier_allowed_features = None; if let Some(TraitBoundModifiers { asyncness: BoundAsyncness::Async(_), .. }) = modifiers { - if let Res::Def(DefKind::Trait, def_id) = res { - if let Some((async_def_id, features)) = self.map_trait_to_async_trait(def_id) { - res = Res::Def(DefKind::Trait, async_def_id); - bound_modifier_allowed_features = Some(features); - } else { - panic!(); + match res { + Res::Def(DefKind::Trait, def_id) => { + if let Some((async_def_id, features)) = self.map_trait_to_async_trait(def_id) { + res = Res::Def(DefKind::Trait, async_def_id); + bound_modifier_allowed_features = Some(features); + } else { + self.dcx().emit_err(AsyncBoundOnlyForFnTraits { span: p.span }); + } + } + Res::Err => { + // No additional error. + } + _ => { + // This error isn't actually emitted AFAICT, but it's best to keep + // it around in case the resolver doesn't always check the defkind + // of an item or something. + self.dcx().emit_err(AsyncBoundNotOnTrait { span: p.span, descr: res.descr() }); } - } else { - panic!(); } } diff --git a/tests/ui/async-await/async-fn/not-a-trait.rs b/tests/ui/async-await/async-fn/not-a-trait.rs new file mode 100644 index 0000000000000..a8fa21e556888 --- /dev/null +++ b/tests/ui/async-await/async-fn/not-a-trait.rs @@ -0,0 +1,13 @@ +// edition:2018 + +#![feature(async_closure)] + +struct S; + +fn test(x: impl async S) {} +//~^ ERROR expected trait, found struct `S` + +fn missing(x: impl async Missing) {} +//~^ ERROR cannot find trait `Missing` in this scope + +fn main() {} diff --git a/tests/ui/async-await/async-fn/not-a-trait.stderr b/tests/ui/async-await/async-fn/not-a-trait.stderr new file mode 100644 index 0000000000000..d49f7d7d2fc16 --- /dev/null +++ b/tests/ui/async-await/async-fn/not-a-trait.stderr @@ -0,0 +1,16 @@ +error[E0404]: expected trait, found struct `S` + --> $DIR/not-a-trait.rs:7:23 + | +LL | fn test(x: impl async S) {} + | ^ not a trait + +error[E0405]: cannot find trait `Missing` in this scope + --> $DIR/not-a-trait.rs:10:26 + | +LL | fn missing(x: impl async Missing) {} + | ^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0404, E0405. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/async-await/async-fn/wrong-trait.rs b/tests/ui/async-await/async-fn/wrong-trait.rs new file mode 100644 index 0000000000000..c431a362b1ea9 --- /dev/null +++ b/tests/ui/async-await/async-fn/wrong-trait.rs @@ -0,0 +1,10 @@ +// edition:2018 + +#![feature(async_closure)] + +trait Foo {} + +fn test(x: impl async Foo) {} +//~^ ERROR `async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits + +fn main() {} diff --git a/tests/ui/async-await/async-fn/wrong-trait.stderr b/tests/ui/async-await/async-fn/wrong-trait.stderr new file mode 100644 index 0000000000000..b39f5aa623c10 --- /dev/null +++ b/tests/ui/async-await/async-fn/wrong-trait.stderr @@ -0,0 +1,8 @@ +error: `async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits + --> $DIR/wrong-trait.rs:7:23 + | +LL | fn test(x: impl async Foo) {} + | ^^^ + +error: aborting due to 1 previous error + From d31905c904ce1cdecd4f3d32a29a0b224e8f0c58 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 31 Jan 2024 16:34:10 +0000 Subject: [PATCH 158/246] Remove a has_errors check that doesn't actually prevent noisy follow up errors --- .../src/traits/error_reporting/type_err_ctxt_ext.rs | 4 ---- .../ui/traits/next-solver/specialization-transmute.rs | 1 + .../next-solver/specialization-transmute.stderr | 11 +++++++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 93e137061c814..bfe6392177530 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2720,10 +2720,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Some(e) = self.tainted_by_errors() { return e; } - if let Some(e) = self.dcx().has_errors() { - // no need to overload user in such cases - return e; - } struct_span_code_err!( self.dcx(), span, diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs index e7de564877d09..6f93a1d3f40dc 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.rs +++ b/tests/ui/traits/next-solver/specialization-transmute.rs @@ -14,6 +14,7 @@ impl Default for T { default type Id = T; //~ ERROR type annotations needed // This will be fixed by #111994 fn intu(&self) -> &Self::Id { + //~^ ERROR type annotations needed self } } diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index a1cf5b761e34f..946a7cbaa808f 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -10,12 +10,19 @@ LL | #![feature(specialization)] error: cannot normalize `::Id` +error[E0284]: type annotations needed: cannot satisfy `::Id == _` + --> $DIR/specialization-transmute.rs:16:23 + | +LL | fn intu(&self) -> &Self::Id { + | ^^^^^^^^^ cannot satisfy `::Id == _` + error[E0282]: type annotations needed --> $DIR/specialization-transmute.rs:14:23 | LL | default type Id = T; | ^ cannot infer type for associated type `::Id` -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0282`. +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. From 647a4536572ed51e15989ab82504df99aa9cc3bc Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 31 Jan 2024 09:43:33 -0800 Subject: [PATCH 159/246] Correct paths for hexagon-unknown-none-elf platform doc Update the library paths to correctly refer to libdemo{1,2}_hexagon and switch to the release build instead. Update references to libstandalone to the specific G0/PIC archive instead. --- .../hexagon-unknown-none-elf.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md b/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md index 06423f0f8fa53..3ac1d2c24603c 100644 --- a/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md +++ b/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md @@ -128,7 +128,8 @@ q6_arch=v65 g0_lib_path=${sdk_libs}/${q6_arch}/G0 pic_lib_path=${sdk_libs}/${q6_arch}/G0/pic -cargo build --target=hexagon-unknown-none-elf -Zbuild-std +build_cfg=release +cargo build --target=hexagon-unknown-none-elf -Zbuild-std --release # Builds an executable against "hexagon standalone OS" suitable for emulation: ${cc} --target=hexagon-unknown-none-elf -o testit \ @@ -142,12 +143,12 @@ ${cc} --target=hexagon-unknown-none-elf -o testit \ -L${sdk_libs}/${q6_arch}/ \ -L${sdk_libs}/ \ testit.c \ - target/hexagon-unknown-none-elf/debug/libmin_ex_lib_lin.rlib \ - target/hexagon-unknown-none-elf/debug/deps/libcore-*.rlib \ - target/hexagon-unknown-none-elf/debug/deps/libcompiler_builtins-*.rlib \ + target/hexagon-unknown-none-elf/${build_cfg}/libdemo1_hexagon.rlib \ + target/hexagon-unknown-none-elf/${build_cfg}/deps/libcore-*.rlib \ + target/hexagon-unknown-none-elf/${build_cfg}/deps/libcompiler_builtins-*.rlib \ -Wl,--start-group \ -Wl,--defsym,_SDA_BASE_=0,--defsym,__sbss_start=0,--defsym,__sbss_end=0 \ - -lstandalone \ + ${g0_lib_path}/libstandalone.a \ ${g0_lib_path}/libc.a \ -lgcc \ -lc_eh \ @@ -248,9 +249,9 @@ ${cc} --target=hexagon-unknown-none-elf -o testit.so \ -Wl,--wrap=memalign \ -m${q6_arch} \ testit.c \ - target/hexagon-unknown-none-elf/debug/libmin_ex_lib_lin.rlib \ - target/hexagon-unknown-none-elf/debug/deps/libcore-*.rlib \ - target/hexagon-unknown-none-elf/debug/deps/libcompiler_builtins-*.rlib \ + target/hexagon-unknown-none-elf/${build_cfg}/libdemo2_hexagon.rlib \ + target/hexagon-unknown-none-elf/${build_cfg}/deps/libcore-*.rlib \ + target/hexagon-unknown-none-elf/${build_cfg}/deps/libcompiler_builtins-*.rlib \ -Wl,-soname=testit \ ${pic_lib_path}/libc.so From 251b14f2c58202d11c03c98ad72133beb28570ca Mon Sep 17 00:00:00 2001 From: David Barsky Date: Tue, 30 Jan 2024 18:07:29 -0500 Subject: [PATCH 160/246] internal: don't panic in `debug_pat` --- crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index e2d8c97cd97fc..0b595042cd567 100644 --- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -460,7 +460,8 @@ impl<'p> TypeCx for MatchCheckCtx<'p> { _f: &mut fmt::Formatter<'_>, _pat: &rustc_pattern_analysis::pat::DeconstructedPat<'_, Self>, ) -> fmt::Result { - unimplemented!() + // FIXME: implement this, as using `unimplemented!()` causes panics in `tracing`. + Ok(()) } fn bug(&self, fmt: fmt::Arguments<'_>) -> ! { From 579e98c4c5235def0f190f2c2a56590d51709975 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Tue, 30 Jan 2024 18:08:34 -0500 Subject: [PATCH 161/246] internal: record Event kind in `handle_event` --- crates/rust-analyzer/src/main_loop.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 3c86414d025c1..f3ead6d04f7d7 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -60,6 +60,17 @@ enum Event { Flycheck(flycheck::Message), } +impl fmt::Display for Event { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Event::Lsp(_) => write!(f, "Event::Lsp"), + Event::Task(_) => write!(f, "Event::Task"), + Event::Vfs(_) => write!(f, "Event::Vfs"), + Event::Flycheck(_) => write!(f, "Event::Flycheck"), + } + } +} + #[derive(Debug)] pub(crate) enum Task { Response(lsp_server::Response), @@ -196,7 +207,8 @@ impl GlobalState { fn handle_event(&mut self, event: Event) -> anyhow::Result<()> { let loop_start = Instant::now(); // NOTE: don't count blocking select! call as a loop-turn time - let _p = tracing::span!(tracing::Level::INFO, "GlobalState::handle_event").entered(); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::handle_event", event = %event) + .entered(); let event_dbg_msg = format!("{event:?}"); tracing::debug!("{:?} handle_event({})", loop_start, event_dbg_msg); From 386d438e173f4c505798361d46f901c7a56567fb Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 00:42:46 +0100 Subject: [PATCH 162/246] skip_while_next --- Cargo.toml | 1 - crates/ide-completion/src/context/analysis.rs | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d5f9740c6deaf..099ac296e4d3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -179,7 +179,6 @@ new_without_default = "allow" non_canonical_clone_impl = "allow" non_canonical_partial_ord_impl = "allow" self_named_constructors = "allow" -skip_while_next = "allow" too_many_arguments = "allow" toplevel_ref_arg = "allow" type_complexity = "allow" diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 65ecaf6bac531..c06b64df1c525 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -1267,8 +1267,7 @@ fn pattern_context_for( pat .syntax() .ancestors() - .skip_while(|it| ast::Pat::can_cast(it.kind())) - .next() + .find(|it| !ast::Pat::can_cast(it.kind())) .map_or((PatternRefutability::Irrefutable, false), |node| { let refutability = match_ast! { match node { From daa20725c5e651d2e63f7fbd7d2a8654e9afb6d7 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 01:00:13 +0100 Subject: [PATCH 163/246] toplevel_ref_arg --- Cargo.toml | 1 - crates/hir-def/src/import_map.rs | 4 ++-- crates/hir/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 099ac296e4d3b..f49593db5fff0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -180,7 +180,6 @@ non_canonical_clone_impl = "allow" non_canonical_partial_ord_impl = "allow" self_named_constructors = "allow" too_many_arguments = "allow" -toplevel_ref_arg = "allow" type_complexity = "allow" unnecessary_cast = "allow" unnecessary_filter_map = "allow" diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index 66d9cf54daa76..5d096c7a5e240 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -396,7 +396,7 @@ impl Query { pub fn search_dependencies( db: &dyn DefDatabase, krate: CrateId, - ref query: Query, + query: &Query, ) -> FxHashSet { let _p = tracing::span!(tracing::Level::INFO, "search_dependencies", ?query).entered(); @@ -516,7 +516,7 @@ mod tests { }) .expect("could not find crate"); - let actual = search_dependencies(db.upcast(), krate, query) + let actual = search_dependencies(db.upcast(), krate, &query) .into_iter() .filter_map(|dependency| { let dependency_krate = dependency.krate(db.upcast())?; diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 28decd4ce710a..2c5474c5c8889 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -236,7 +236,7 @@ impl Crate { query: import_map::Query, ) -> impl Iterator> { let _p = tracing::span!(tracing::Level::INFO, "query_external_importables"); - import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| { + 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), From de6f9561f2822b87aede9f5edc6e14951da570ba Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 01:00:50 +0100 Subject: [PATCH 164/246] unnecessary_cast --- Cargo.toml | 1 - crates/hir-def/src/import_map.rs | 4 ++-- crates/hir/src/lib.rs | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f49593db5fff0..8d861f2a18af5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,7 +181,6 @@ non_canonical_partial_ord_impl = "allow" self_named_constructors = "allow" too_many_arguments = "allow" type_complexity = "allow" -unnecessary_cast = "allow" unnecessary_filter_map = "allow" unnecessary_lazy_evaluations = "allow" unnecessary_mut_passed = "allow" diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index 5d096c7a5e240..c698510ca99b4 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -297,7 +297,7 @@ impl SearchMode { SearchMode::Exact => candidate.eq_ignore_ascii_case(query), SearchMode::Prefix => { query.len() <= candidate.len() && { - let prefix = &candidate[..query.len() as usize]; + let prefix = &candidate[..query.len()]; if case_sensitive { prefix == query } else { @@ -446,7 +446,7 @@ fn search_maps( let end = (value & 0xFFFF_FFFF) as usize; let start = (value >> 32) as usize; let ImportMap { item_to_info_map, importables, .. } = &*import_maps[import_map_idx]; - let importables = &importables[start as usize..end]; + let importables = &importables[start..end]; let iter = importables .iter() diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 2c5474c5c8889..1e21045e9818b 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -903,7 +903,7 @@ fn emit_def_diagnostic_( } DefDiagnosticKind::InvalidDeriveTarget { ast, id } => { let node = ast.to_node(db.upcast()); - let derive = node.attrs().nth(*id as usize); + let derive = node.attrs().nth(*id); match derive { Some(derive) => { acc.push( @@ -918,7 +918,7 @@ fn emit_def_diagnostic_( } DefDiagnosticKind::MalformedDerive { ast, id } => { let node = ast.to_node(db.upcast()); - let derive = node.attrs().nth(*id as usize); + let derive = node.attrs().nth(*id); match derive { Some(derive) => { acc.push( From f15ee8a380c18cf7d9d53a91c2b4a6d6161e9877 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 01:11:59 +0100 Subject: [PATCH 165/246] unnecessary_filter_map --- Cargo.toml | 1 - crates/ide-completion/src/tests.rs | 25 ++++++++---------------- crates/rust-analyzer/src/lsp/to_proto.rs | 12 +++++------- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8d861f2a18af5..b8f273af4710b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,7 +181,6 @@ non_canonical_partial_ord_impl = "allow" self_named_constructors = "allow" too_many_arguments = "allow" type_complexity = "allow" -unnecessary_filter_map = "allow" unnecessary_lazy_evaluations = "allow" unnecessary_mut_passed = "allow" useless_conversion = "allow" diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs index c421be51a0d07..154b69875aea8 100644 --- a/crates/ide-completion/src/tests.rs +++ b/crates/ide-completion/src/tests.rs @@ -210,23 +210,14 @@ pub(crate) fn check_edit_with_config( let mut combined_edit = completion.text_edit.clone(); - resolve_completion_edits( - &db, - &config, - position, - completion - .import_to_add - .iter() - .cloned() - .filter_map(|(import_path, import_name)| Some((import_path, import_name))), - ) - .into_iter() - .flatten() - .for_each(|text_edit| { - combined_edit.union(text_edit).expect( - "Failed to apply completion resolve changes: change ranges overlap, but should not", - ) - }); + resolve_completion_edits(&db, &config, position, completion.import_to_add.iter().cloned()) + .into_iter() + .flatten() + .for_each(|text_edit| { + combined_edit.union(text_edit).expect( + "Failed to apply completion resolve changes: change ranges overlap, but should not", + ) + }); combined_edit.apply(&mut actual); assert_eq_text!(&ra_fixture_after, &actual) diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index f221863aff0ee..d363ac69fdc33 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -312,16 +312,14 @@ fn completion_item( set_score(&mut lsp_item, max_relevance, item.relevance); if config.completion().enable_imports_on_the_fly && !item.import_to_add.is_empty() { - let imports: Vec<_> = item + let imports = item .import_to_add .into_iter() - .filter_map(|(import_path, import_name)| { - Some(lsp_ext::CompletionImport { - full_import_path: import_path, - imported_name: import_name, - }) + .map(|(import_path, import_name)| lsp_ext::CompletionImport { + full_import_path: import_path, + imported_name: import_name, }) - .collect(); + .collect::>(); if !imports.is_empty() { let data = lsp_ext::CompletionResolveData { position: tdpp.clone(), imports }; lsp_item.data = Some(to_value(data).unwrap()); From c4302eaa566eb74083c4233a56788d32f147a88d Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 01:19:28 +0100 Subject: [PATCH 166/246] unnecessary_lazy_evaluations --- Cargo.toml | 1 - crates/hir-def/src/hir/format_args.rs | 1 + crates/hir-expand/src/attrs.rs | 2 +- crates/hir/src/attrs.rs | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b8f273af4710b..20bd27c63e5c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,7 +181,6 @@ non_canonical_partial_ord_impl = "allow" self_named_constructors = "allow" too_many_arguments = "allow" type_complexity = "allow" -unnecessary_lazy_evaluations = "allow" unnecessary_mut_passed = "allow" useless_conversion = "allow" useless_format = "allow" diff --git a/crates/hir-def/src/hir/format_args.rs b/crates/hir-def/src/hir/format_args.rs index 113f9441a0129..dc09b0ef3ec00 100644 --- a/crates/hir-def/src/hir/format_args.rs +++ b/crates/hir-def/src/hir/format_args.rs @@ -166,6 +166,7 @@ enum PositionUsedAs { } use PositionUsedAs::*; +#[allow(clippy::unnecessary_lazy_evaluations)] pub(crate) fn parse( s: &ast::String, fmt_snippet: Option, diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs index b0b2501ce9d48..c20c1639e1a49 100644 --- a/crates/hir-expand/src/attrs.rs +++ b/crates/hir-expand/src/attrs.rs @@ -230,7 +230,7 @@ impl Attr { ) ) }) - .unwrap_or_else(|| tt.len()); + .unwrap_or(tt.len()); let (path, input) = tt.split_at(path_end); let path = Interned::new(ModPath::from_tt(db, path)?); diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index f2b9db669e0e9..8978be81332bd 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -297,7 +297,7 @@ fn as_module_def_if_namespace_matches( AssocItem::TypeAlias(it) => (ModuleDef::TypeAlias(it), Namespace::Types), }; - (ns.unwrap_or(expected_ns) == expected_ns).then(|| DocLinkDef::ModuleDef(def)) + (ns.unwrap_or(expected_ns) == expected_ns).then_some(DocLinkDef::ModuleDef(def)) } fn modpath_from_str(link: &str) -> Option { From f191b807990cce67a7662254127e9b6adb030d8d Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 01:19:50 +0100 Subject: [PATCH 167/246] Refactor --- crates/hir-def/src/hir/format_args.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/hir-def/src/hir/format_args.rs b/crates/hir-def/src/hir/format_args.rs index dc09b0ef3ec00..22864b32894ab 100644 --- a/crates/hir-def/src/hir/format_args.rs +++ b/crates/hir-def/src/hir/format_args.rs @@ -178,9 +178,9 @@ pub(crate) fn parse( let text = s.text_without_quotes(); let str_style = match s.quote_offsets() { Some(offsets) => { - let raw = u32::from(offsets.quotes.0.len()) - 1; + let raw = usize::from(offsets.quotes.0.len()) - 1; // subtract 1 for the `r` prefix - (raw != 0).then(|| raw as usize - 1) + (raw != 0).then(|| raw - 1) } None => None, }; From e7d0deac538af1d7372608bb02f6caa8bf834de2 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 01:25:39 +0100 Subject: [PATCH 168/246] unnecessary_mut_passed --- Cargo.toml | 1 - crates/hir-ty/src/mir/lower/pattern_matching.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 20bd27c63e5c0..9fb04589e2caa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,7 +181,6 @@ non_canonical_partial_ord_impl = "allow" self_named_constructors = "allow" too_many_arguments = "allow" type_complexity = "allow" -unnecessary_mut_passed = "allow" useless_conversion = "allow" useless_format = "allow" wildcard_in_or_patterns = "allow" diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 65ab12929dd2c..8202bac532f7a 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -114,7 +114,7 @@ impl MirLowerCtx<'_> { index: i as u32, })) }), - &mut cond_place, + &cond_place, mode, )? } From b73ee2f50df1488be42a0fb9b2f7d915a7cae49d Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 01:31:50 +0100 Subject: [PATCH 169/246] useless_conversion --- Cargo.toml | 1 - crates/hir-def/src/body/tests.rs | 4 ++-- crates/hir-def/src/data.rs | 2 +- crates/hir-def/src/nameres/path_resolution.rs | 2 +- crates/hir-def/src/per_ns.rs | 6 ++---- crates/hir/src/attrs.rs | 7 +++---- crates/rust-analyzer/src/config.rs | 2 +- 7 files changed, 10 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9fb04589e2caa..640f478b0c10e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,7 +181,6 @@ non_canonical_partial_ord_impl = "allow" self_named_constructors = "allow" too_many_arguments = "allow" type_complexity = "allow" -useless_conversion = "allow" useless_format = "allow" wildcard_in_or_patterns = "allow" wrong_self_convention = "allow" diff --git a/crates/hir-def/src/body/tests.rs b/crates/hir-def/src/body/tests.rs index a76ddffb41166..a27ffe216750e 100644 --- a/crates/hir-def/src/body/tests.rs +++ b/crates/hir-def/src/body/tests.rs @@ -256,7 +256,7 @@ impl SsrError { "##, ); - assert_eq!(db.body_with_source_map(def.into()).1.diagnostics(), &[]); + assert_eq!(db.body_with_source_map(def).1.diagnostics(), &[]); expect![[r#" fn main() { _ = $crate::error::SsrError::new( @@ -309,7 +309,7 @@ fn f() { "#, ); - let (_, source_map) = db.body_with_source_map(def.into()); + let (_, source_map) = db.body_with_source_map(def); assert_eq!(source_map.diagnostics(), &[]); for (_, def_map) in body.blocks(&db) { diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 73fbad5e67508..7ce05b64d022e 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -782,7 +782,7 @@ impl<'a> AssocItemCollector<'a> { self.diagnostics.push(DefDiagnostic::macro_expansion_parse_error( self.module_id.local_id, error_call_kind(), - errors.into(), + errors, )); } diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 2c7e222791375..70da0ef8e1e1f 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -475,7 +475,7 @@ impl DefMap { let macro_use_prelude = || { self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| { PerNs::macros( - it.into(), + it, Visibility::Public, // FIXME? None, // extern_crate.map(ImportOrExternCrate::ExternCrate), diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs index 6a62ef697017c..23d41cc0d88e0 100644 --- a/crates/hir-def/src/per_ns.rs +++ b/crates/hir-def/src/per_ns.rs @@ -131,13 +131,11 @@ impl PerNs { .into_iter() .chain( self.values - .map(|it| (ItemInNs::Values(it.0), it.2.map(ImportOrExternCrate::Import))) - .into_iter(), + .map(|it| (ItemInNs::Values(it.0), it.2.map(ImportOrExternCrate::Import))), ) .chain( self.macros - .map(|it| (ItemInNs::Macros(it.0), it.2.map(ImportOrExternCrate::Import))) - .into_iter(), + .map(|it| (ItemInNs::Macros(it.0), it.2.map(ImportOrExternCrate::Import))), ) } } diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 8978be81332bd..5c369f42e6e7d 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -239,10 +239,9 @@ fn resolve_impl_trait_item( ) -> Option { let canonical = ty.canonical(); let krate = ty.krate(db); - let environment = resolver.generic_def().map_or_else( - || crate::TraitEnvironment::empty(krate.id).into(), - |d| db.trait_environment(d), - ); + let environment = resolver + .generic_def() + .map_or_else(|| crate::TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); let traits_in_scope = resolver.traits_in_scope(db.upcast()); let mut result = None; diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index eeb28b8fe4263..54d96ab13811c 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -1744,7 +1744,7 @@ impl Config { } pub fn main_loop_num_threads(&self) -> usize { - self.data.numThreads.unwrap_or(num_cpus::get_physical().try_into().unwrap_or(1)) + self.data.numThreads.unwrap_or(num_cpus::get_physical()) } pub fn typing_autoclose_angle(&self) -> bool { From b176cf2478ae9bc7b0c293c8cf0669d6e64e9474 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 01:36:39 +0100 Subject: [PATCH 170/246] useless_format --- Cargo.toml | 1 - crates/hir-def/src/body/pretty.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 640f478b0c10e..8296c91295901 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,7 +181,6 @@ non_canonical_partial_ord_impl = "allow" self_named_constructors = "allow" too_many_arguments = "allow" type_complexity = "allow" -useless_format = "allow" wildcard_in_or_patterns = "allow" wrong_self_convention = "allow" diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs index 0f2b279670c17..b821b91b8959e 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -33,7 +33,7 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo } ) }), - DefWithBodyId::InTypeConstId(_) => format!("In type const = "), + DefWithBodyId::InTypeConstId(_) => "In type const = ".to_string(), DefWithBodyId::VariantId(it) => { let loc = it.lookup(db); let enum_loc = loc.parent.lookup(db); From 0adb4d16856d22ba6a63b659d7dbd37b514b2d0c Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 01:41:42 +0100 Subject: [PATCH 171/246] wildcard_in_or_patterns --- Cargo.toml | 1 - crates/hir-ty/src/inhabitedness.rs | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8296c91295901..0d42f9c655bf6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,7 +181,6 @@ non_canonical_partial_ord_impl = "allow" self_named_constructors = "allow" too_many_arguments = "allow" type_complexity = "allow" -wildcard_in_or_patterns = "allow" wrong_self_convention = "allow" ## warn at following lints diff --git a/crates/hir-ty/src/inhabitedness.rs b/crates/hir-ty/src/inhabitedness.rs index a63556f450dda..532b650e8ff27 100644 --- a/crates/hir-ty/src/inhabitedness.rs +++ b/crates/hir-ty/src/inhabitedness.rs @@ -84,8 +84,7 @@ impl TypeVisitor for UninhabitedFrom<'_> { Some(0) | None => CONTINUE_OPAQUELY_INHABITED, Some(1..) => item_ty.super_visit_with(self, outer_binder), }, - - TyKind::Ref(..) | _ => CONTINUE_OPAQUELY_INHABITED, + _ => CONTINUE_OPAQUELY_INHABITED, }; self.recursive_ty.remove(ty); self.max_depth += 1; From c4688343de3b9a99aa0b0899195abaf037232372 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 01:50:51 +0100 Subject: [PATCH 172/246] derivable_impls --- Cargo.toml | 1 - crates/hir-def/src/per_ns.rs | 8 +------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0d42f9c655bf6..6350027ddb616 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -168,7 +168,6 @@ new_ret_no_self = "allow" ## Following lints should be tackled at some point borrowed_box = "allow" borrow_deref_ref = "allow" -derivable_impls = "allow" derived_hash_with_manual_eq = "allow" field_reassign_with_default = "allow" forget_non_drop = "allow" diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs index 23d41cc0d88e0..36ab62d0f7f1b 100644 --- a/crates/hir-def/src/per_ns.rs +++ b/crates/hir-def/src/per_ns.rs @@ -16,19 +16,13 @@ pub enum Namespace { Macros, } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] pub struct PerNs { pub types: Option<(ModuleDefId, Visibility, Option)>, pub values: Option<(ModuleDefId, Visibility, Option)>, pub macros: Option<(MacroId, Visibility, Option)>, } -impl Default for PerNs { - fn default() -> Self { - PerNs { types: None, values: None, macros: None } - } -} - impl PerNs { pub fn none() -> PerNs { PerNs { types: None, values: None, macros: None } From dd9f27b8d361180d6df350ac95087d739e3e9023 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 01:54:55 +0100 Subject: [PATCH 173/246] borrow_deref_ref --- Cargo.toml | 1 - crates/hir-def/src/nameres/collector.rs | 2 +- crates/hir-def/src/test_db.rs | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6350027ddb616..d29f46ca2b5be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -167,7 +167,6 @@ new_ret_no_self = "allow" ## Following lints should be tackled at some point borrowed_box = "allow" -borrow_deref_ref = "allow" derived_hash_with_manual_eq = "allow" field_reassign_with_default = "allow" forget_non_drop = "allow" diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index bdef9c8a93192..fb6fd867a1618 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -1924,7 +1924,7 @@ impl ModCollector<'_, '_> { item_tree: self.item_tree, mod_dir, } - .collect_in_top_module(&*items); + .collect_in_top_module(items); if is_macro_use { self.import_all_legacy_macros(module_id); } diff --git a/crates/hir-def/src/test_db.rs b/crates/hir-def/src/test_db.rs index c992c3c920486..9edb03c7cab90 100644 --- a/crates/hir-def/src/test_db.rs +++ b/crates/hir-def/src/test_db.rs @@ -41,13 +41,13 @@ impl Default for TestDB { impl Upcast for TestDB { fn upcast(&self) -> &(dyn ExpandDatabase + 'static) { - &*self + self } } impl Upcast for TestDB { fn upcast(&self) -> &(dyn DefDatabase + 'static) { - &*self + self } } From 04ccef80cbe066ab0228fc93ccba159f47a2a5f0 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 02:15:29 +0100 Subject: [PATCH 174/246] field_reassign_with_default --- Cargo.toml | 1 - crates/ide/src/hover.rs | 1 + crates/rust-analyzer/src/cli/analysis_stats.rs | 12 +++++++----- crates/rust-analyzer/src/cli/diagnostics.rs | 4 ++-- crates/rust-analyzer/src/cli/lsif.rs | 4 ++-- crates/rust-analyzer/src/cli/run_tests.rs | 4 ++-- crates/rust-analyzer/src/cli/rustc_tests.rs | 4 ++-- crates/rust-analyzer/src/cli/ssr.rs | 4 ++-- 8 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d29f46ca2b5be..7eb5ab9d61821 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -168,7 +168,6 @@ new_ret_no_self = "allow" ## Following lints should be tackled at some point borrowed_box = "allow" derived_hash_with_manual_eq = "allow" -field_reassign_with_default = "allow" forget_non_drop = "allow" format_collect = "allow" large_enum_variant = "allow" diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 77a06a97e22d2..19b181ae3b61e 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -120,6 +120,7 @@ pub(crate) fn hover( Some(res) } +#[allow(clippy::field_reassign_with_default)] fn hover_simple( sema: &Semantics<'_, RootDatabase>, FilePosition { file_id, offset }: FilePosition, diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index c33fbddceff2e..31bdd2a0e82b1 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -58,12 +58,14 @@ impl flags::AnalysisStats { Rand32::new(seed) }; - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = match self.no_sysroot { - true => None, - false => Some(RustLibSource::Discover), + let cargo_config = CargoConfig { + sysroot: match self.no_sysroot { + true => None, + false => Some(RustLibSource::Discover), + }, + sysroot_query_metadata: self.query_sysroot_metadata, + ..Default::default() }; - cargo_config.sysroot_query_metadata = self.query_sysroot_metadata; let no_progress = &|_| (); let mut db_load_sw = self.stop_watch(); diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs index 0182cf5402e56..6d2e97be20e50 100644 --- a/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/crates/rust-analyzer/src/cli/diagnostics.rs @@ -13,8 +13,8 @@ use crate::cli::flags; impl flags::Diagnostics { pub fn run(self) -> anyhow::Result<()> { - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); + let cargo_config = + CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() }; let with_proc_macro_server = if let Some(p) = &self.proc_macro_srv { let path = vfs::AbsPathBuf::assert(std::env::current_dir()?.join(p)); ProcMacroServerChoice::Explicit(path) diff --git a/crates/rust-analyzer/src/cli/lsif.rs b/crates/rust-analyzer/src/cli/lsif.rs index 2138ecead53f4..64f965e22ac70 100644 --- a/crates/rust-analyzer/src/cli/lsif.rs +++ b/crates/rust-analyzer/src/cli/lsif.rs @@ -287,8 +287,8 @@ impl flags::Lsif { pub fn run(self) -> anyhow::Result<()> { eprintln!("Generating LSIF started..."); let now = Instant::now(); - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); + let cargo_config = + CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() }; let no_progress = &|_| (); let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, diff --git a/crates/rust-analyzer/src/cli/run_tests.rs b/crates/rust-analyzer/src/cli/run_tests.rs index e1704199151a6..d07dcdec25105 100644 --- a/crates/rust-analyzer/src/cli/run_tests.rs +++ b/crates/rust-analyzer/src/cli/run_tests.rs @@ -13,8 +13,8 @@ use crate::cli::{flags, full_name_of_item, Result}; impl flags::RunTests { pub fn run(self) -> Result<()> { - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); + let cargo_config = + CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, diff --git a/crates/rust-analyzer/src/cli/rustc_tests.rs b/crates/rust-analyzer/src/cli/rustc_tests.rs index 522eb53128fb7..be7e434acac25 100644 --- a/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -59,8 +59,8 @@ impl Tester { path.push("ra-rustc-test.rs"); let tmp_file = AbsPathBuf::try_from(path).unwrap(); std::fs::write(&tmp_file, "")?; - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); + let cargo_config = + CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() }; let workspace = ProjectWorkspace::DetachedFiles { files: vec![tmp_file.clone()], sysroot: Ok(Sysroot::discover( diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs index f87dcb889a48b..8f11d82f8fd93 100644 --- a/crates/rust-analyzer/src/cli/ssr.rs +++ b/crates/rust-analyzer/src/cli/ssr.rs @@ -10,8 +10,8 @@ use crate::cli::flags; impl flags::Ssr { pub fn run(self) -> anyhow::Result<()> { use ide_db::base_db::SourceDatabaseExt; - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); + let cargo_config = + CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, From e7e09e775019171a31649ef3256507981e6c085c Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 22 Jan 2024 02:43:28 +0100 Subject: [PATCH 175/246] large_enum_variant --- Cargo.toml | 1 - crates/flycheck/src/lib.rs | 6 ++++-- crates/proc-macro-api/src/lib.rs | 2 +- crates/proc-macro-api/src/msg.rs | 2 +- crates/proc-macro-srv-cli/src/main.rs | 6 ++++-- crates/project-model/src/workspace.rs | 13 +++++++------ 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7eb5ab9d61821..365f7db37493a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -170,7 +170,6 @@ borrowed_box = "allow" derived_hash_with_manual_eq = "allow" forget_non_drop = "allow" format_collect = "allow" -large_enum_variant = "allow" needless_doctest_main = "allow" new_without_default = "allow" non_canonical_clone_impl = "allow" diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 68faca51e8263..22603842a1b6b 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -493,7 +493,9 @@ impl CargoActor { // Skip certain kinds of messages to only spend time on what's useful JsonMessage::Cargo(message) => match message { cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => { - self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap(); + self.sender + .send(CargoMessage::CompilerArtifact(Box::new(artifact))) + .unwrap(); } cargo_metadata::Message::CompilerMessage(msg) => { self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap(); @@ -538,7 +540,7 @@ impl CargoActor { } enum CargoMessage { - CompilerArtifact(cargo_metadata::Artifact), + CompilerArtifact(Box), Diagnostic(Diagnostic), } diff --git a/crates/proc-macro-api/src/lib.rs b/crates/proc-macro-api/src/lib.rs index 345608d3d0c68..379d184dd684e 100644 --- a/crates/proc-macro-api/src/lib.rs +++ b/crates/proc-macro-api/src/lib.rs @@ -184,7 +184,7 @@ impl ProcMacro { .process .lock() .unwrap_or_else(|e| e.into_inner()) - .send_task(msg::Request::ExpandMacro(task))?; + .send_task(msg::Request::ExpandMacro(Box::new(task)))?; match response { msg::Response::ExpandMacro(it) => { diff --git a/crates/proc-macro-api/src/msg.rs b/crates/proc-macro-api/src/msg.rs index 557ddba5c78fe..e28fe387b84bd 100644 --- a/crates/proc-macro-api/src/msg.rs +++ b/crates/proc-macro-api/src/msg.rs @@ -29,7 +29,7 @@ pub enum Request { /// Since [`NO_VERSION_CHECK_VERSION`] ListMacros { dylib_path: PathBuf }, /// Since [`NO_VERSION_CHECK_VERSION`] - ExpandMacro(ExpandMacro), + ExpandMacro(Box), /// Since [`VERSION_CHECK_VERSION`] ApiVersionCheck {}, /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] diff --git a/crates/proc-macro-srv-cli/src/main.rs b/crates/proc-macro-srv-cli/src/main.rs index af9a03826ffc0..a36200cdb4c35 100644 --- a/crates/proc-macro-srv-cli/src/main.rs +++ b/crates/proc-macro-srv-cli/src/main.rs @@ -45,9 +45,11 @@ fn run() -> io::Result<()> { msg::Response::ListMacros(srv.list_macros(&dylib_path)) } msg::Request::ExpandMacro(task) => match srv.span_mode() { - msg::SpanMode::Id => msg::Response::ExpandMacro(srv.expand(task).map(|(it, _)| it)), + msg::SpanMode::Id => { + msg::Response::ExpandMacro(srv.expand(*task).map(|(it, _)| it)) + } msg::SpanMode::RustAnalyzer => msg::Response::ExpandMacroExtended( - srv.expand(task).map(|(tree, span_data_table)| msg::ExpandMacroExtended { + srv.expand(*task).map(|(tree, span_data_table)| msg::ExpandMacroExtended { tree, span_data_table, }), diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index e6e2fa7a97800..8c5ea0619ac7e 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -60,7 +60,7 @@ pub enum ProjectWorkspace { cargo: CargoWorkspace, build_scripts: WorkspaceBuildScripts, sysroot: Result>, - rustc: Result<(CargoWorkspace, WorkspaceBuildScripts), Option>, + rustc: Result, Option>, /// Holds cfg flags for the current target. We get those by running /// `rustc --print cfg`. /// @@ -119,7 +119,7 @@ impl fmt::Debug for ProjectWorkspace { .field("sysroot", &sysroot.is_ok()) .field( "n_rustc_compiler_crates", - &rustc.as_ref().map_or(0, |(rc, _)| rc.packages().len()), + &rustc.as_ref().map(|a| a.as_ref()).map_or(0, |(rc, _)| rc.packages().len()), ) .field("n_rustc_cfg", &rustc_cfg.len()) .field("n_cfg_overrides", &cfg_overrides.len()) @@ -265,7 +265,7 @@ impl ProjectWorkspace { cargo_toml.parent(), &config.extra_env, ); - Ok((workspace, buildscripts)) + Ok(Box::new((workspace, buildscripts))) } Err(e) => { tracing::error!( @@ -603,7 +603,7 @@ impl ProjectWorkspace { PackageRoot { is_local, include, exclude } }) .chain(mk_sysroot(sysroot.as_ref(), Some(cargo.workspace_root()))) - .chain(rustc.iter().flat_map(|(rustc, _)| { + .chain(rustc.iter().map(|a| a.as_ref()).flat_map(|(rustc, _)| { rustc.packages().map(move |krate| PackageRoot { is_local: false, include: vec![rustc[krate].manifest.parent().to_path_buf()], @@ -631,7 +631,8 @@ impl ProjectWorkspace { sysroot_package_len + project.n_crates() } ProjectWorkspace::Cargo { cargo, sysroot, rustc, .. } => { - let rustc_package_len = rustc.as_ref().map_or(0, |(it, _)| it.packages().len()); + let rustc_package_len = + rustc.as_ref().map(|a| a.as_ref()).map_or(0, |(it, _)| it.packages().len()); let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.num_packages()); cargo.packages().len() + sysroot_package_len + rustc_package_len } @@ -672,7 +673,7 @@ impl ProjectWorkspace { target_layout, } => cargo_to_crate_graph( load, - rustc.as_ref().ok(), + rustc.as_ref().map(|a| a.as_ref()).ok(), cargo, sysroot.as_ref().ok(), rustc_cfg.clone(), From d37f4e0d21577753f3be96549e0d4e99ac5ae2e2 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Tue, 30 Jan 2024 12:03:33 +0100 Subject: [PATCH 176/246] new_without_default --- Cargo.toml | 1 - crates/hir-def/src/hir/format_args.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 365f7db37493a..53581c4460d1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -171,7 +171,6 @@ derived_hash_with_manual_eq = "allow" forget_non_drop = "allow" format_collect = "allow" needless_doctest_main = "allow" -new_without_default = "allow" non_canonical_clone_impl = "allow" non_canonical_partial_ord_impl = "allow" self_named_constructors = "allow" diff --git a/crates/hir-def/src/hir/format_args.rs b/crates/hir-def/src/hir/format_args.rs index 22864b32894ab..b097a721c7586 100644 --- a/crates/hir-def/src/hir/format_args.rs +++ b/crates/hir-def/src/hir/format_args.rs @@ -433,7 +433,7 @@ pub(crate) fn parse( } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct FormatArgumentsCollector { arguments: Vec, num_unnamed_args: usize, @@ -452,7 +452,7 @@ impl FormatArgumentsCollector { } pub fn new() -> Self { - Self { arguments: vec![], names: vec![], num_unnamed_args: 0, num_explicit_args: 0 } + Default::default() } pub fn add(&mut self, arg: FormatArgument) -> usize { From 771c6c9271f423ab7d0584b308a6abeb599009bc Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Tue, 30 Jan 2024 14:12:42 +0100 Subject: [PATCH 177/246] format_collect --- Cargo.toml | 1 - .../hir-def/src/macro_expansion_tests/mod.rs | 5 ++- crates/ide-assists/src/tests/sourcegen.rs | 7 ++--- crates/rust-analyzer/src/config.rs | 31 ++++++++++--------- crates/rust-analyzer/tests/slow-tests/main.rs | 7 +++-- crates/stdx/src/macros.rs | 16 ++++++++++ crates/syntax/src/ast/make.rs | 18 +++++------ crates/syntax/src/tests.rs | 8 ++--- 8 files changed, 54 insertions(+), 39 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 53581c4460d1f..5a7486481161a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -169,7 +169,6 @@ new_ret_no_self = "allow" borrowed_box = "allow" derived_hash_with_manual_eq = "allow" forget_non_drop = "allow" -format_collect = "allow" needless_doctest_main = "allow" non_canonical_clone_impl = "allow" non_canonical_partial_ord_impl = "allow" diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs index ec2994053877e..e315414e9bdd6 100644 --- a/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -25,7 +25,7 @@ use hir_expand::{ InFile, MacroFileId, MacroFileIdExt, }; use span::Span; -use stdx::format_to; +use stdx::{format_to, format_to_acc}; use syntax::{ ast::{self, edit::IndentLevel}, AstNode, @@ -149,8 +149,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream if tree { let tree = format!("{:#?}", parse.syntax_node()) .split_inclusive('\n') - .map(|line| format!("// {line}")) - .collect::(); + .fold(String::new(), |mut acc, line| format_to_acc!(acc, "// {line}")); format_to!(expn_text, "\n{}", tree) } let range = call.syntax().text_range(); diff --git a/crates/ide-assists/src/tests/sourcegen.rs b/crates/ide-assists/src/tests/sourcegen.rs index ad5ec83287529..088d93f9a6ba4 100644 --- a/crates/ide-assists/src/tests/sourcegen.rs +++ b/crates/ide-assists/src/tests/sourcegen.rs @@ -2,6 +2,7 @@ use std::{fmt, fs, path::Path}; +use stdx::format_to_acc; use test_utils::project_root; #[test] @@ -172,8 +173,7 @@ impl fmt::Display for Assist { fn hide_hash_comments(text: &str) -> String { text.split('\n') // want final newline .filter(|&it| !(it.starts_with("# ") || it == "#")) - .map(|it| format!("{it}\n")) - .collect() + .fold(String::new(), |mut acc, it| format_to_acc!(acc, "{it}\n")) } fn reveal_hash_comments(text: &str) -> String { @@ -187,6 +187,5 @@ fn reveal_hash_comments(text: &str) -> String { it } }) - .map(|it| format!("{it}\n")) - .collect() + .fold(String::new(), |mut acc, it| format_to_acc!(acc, "{it}\n")) } diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 54d96ab13811c..815f6ea12e86c 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -32,6 +32,7 @@ use project_model::{ }; use rustc_hash::{FxHashMap, FxHashSet}; use serde::{de::DeserializeOwned, Deserialize}; +use stdx::format_to_acc; use vfs::{AbsPath, AbsPathBuf}; use crate::{ @@ -2563,14 +2564,13 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json #[cfg(test)] fn manual(fields: &[(&'static str, &'static str, &[&str], &str)]) -> String { - fields - .iter() - .map(|(field, _ty, doc, default)| { - let name = format!("rust-analyzer.{}", field.replace('_', ".")); - let doc = doc_comment_to_string(doc); - if default.contains('\n') { - format!( - r#"[[{name}]]{name}:: + fields.iter().fold(String::new(), |mut acc, (field, _ty, doc, default)| { + let name = format!("rust-analyzer.{}", field.replace('_', ".")); + let doc = doc_comment_to_string(doc); + if default.contains('\n') { + format_to_acc!( + acc, + r#"[[{name}]]{name}:: + -- Default: @@ -2580,16 +2580,17 @@ Default: {doc} -- "# - ) - } else { - format!("[[{name}]]{name} (default: `{default}`)::\n+\n--\n{doc}--\n") - } - }) - .collect::() + ) + } else { + format_to_acc!(acc, "[[{name}]]{name} (default: `{default}`)::\n+\n--\n{doc}--\n") + } + }) } fn doc_comment_to_string(doc: &[&str]) -> String { - doc.iter().map(|it| it.strip_prefix(' ').unwrap_or(it)).map(|it| format!("{it}\n")).collect() + doc.iter() + .map(|it| it.strip_prefix(' ').unwrap_or(it)) + .fold(String::new(), |mut acc, it| format_to_acc!(acc, "{it}\n")) } #[cfg(test)] diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs index f7f654b890e95..19890110d53db 100644 --- a/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/crates/rust-analyzer/tests/slow-tests/main.rs @@ -31,6 +31,7 @@ use lsp_types::{ }; use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams}; use serde_json::json; +use stdx::format_to_acc; use test_utils::skip_slow_tests; use crate::{ @@ -591,8 +592,10 @@ fn diagnostics_dont_block_typing() { return; } - let librs: String = (0..10).map(|i| format!("mod m{i};")).collect(); - let libs: String = (0..10).map(|i| format!("//- /src/m{i}.rs\nfn foo() {{}}\n\n")).collect(); + let librs: String = (0..10).fold(String::new(), |mut acc, i| format_to_acc!(acc, "mod m{i};")); + let libs: String = (0..10).fold(String::new(), |mut acc, i| { + format_to_acc!(acc, "//- /src/m{i}.rs\nfn foo() {{}}\n\n") + }); let server = Project::with_fixture(&format!( r#" //- /Cargo.toml diff --git a/crates/stdx/src/macros.rs b/crates/stdx/src/macros.rs index d71e418c89bc6..5713abb6fccaf 100644 --- a/crates/stdx/src/macros.rs +++ b/crates/stdx/src/macros.rs @@ -24,6 +24,22 @@ macro_rules! format_to { }; } +/// Appends formatted string to a `String` and returns the `String`. +/// +/// Useful for folding iterators into a `String`. +#[macro_export] +macro_rules! format_to_acc { + ($buf:expr, $lit:literal $($arg:tt)*) => { + { + use ::std::fmt::Write as _; + // We can't do ::std::fmt::Write::write_fmt($buf, format_args!($lit $($arg)*)) + // unfortunately, as that loses out on autoref behavior. + _ = $buf.write_fmt(format_args!($lit $($arg)*)); + $buf + } + }; +} + /// Generates `From` impls for `Enum E { Foo(Foo), Bar(Bar) }` enums /// /// # Example diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 62d64319e3858..d5eda8f15e4a0 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -9,10 +9,11 @@ //! API should require to assemble every node piecewise. The trick of //! `parse(format!())` we use internally is an implementation detail -- long //! term, it will be replaced with direct tree manipulation. + use itertools::Itertools; use parser::T; use rowan::NodeOrToken; -use stdx::{format_to, never}; +use stdx::{format_to, format_to_acc, never}; use crate::{ast, utils::is_raw_identifier, AstNode, SourceFile, SyntaxKind, SyntaxToken}; @@ -759,15 +760,12 @@ pub fn match_arm_with_guard( } pub fn match_arm_list(arms: impl IntoIterator) -> ast::MatchArmList { - let arms_str = arms - .into_iter() - .map(|arm| { - let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like()); - let comma = if needs_comma { "," } else { "" }; - let arm = arm.syntax(); - format!(" {arm}{comma}\n") - }) - .collect::(); + let arms_str = arms.into_iter().fold(String::new(), |mut acc, arm| { + let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like()); + let comma = if needs_comma { "," } else { "" }; + let arm = arm.syntax(); + format_to_acc!(acc, " {arm}{comma}\n") + }); return from_text(&arms_str); fn from_text(text: &str) -> ast::MatchArmList { diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs index 8ae1242cf7fd4..4c0a538f712f5 100644 --- a/crates/syntax/src/tests.rs +++ b/crates/syntax/src/tests.rs @@ -11,6 +11,7 @@ use std::{ use ast::HasName; use expect_test::expect_file; use rayon::prelude::*; +use stdx::format_to_acc; use test_utils::{bench, bench_fixture, project_root}; use crate::{ast, fuzz, AstNode, SourceFile, SyntaxError}; @@ -104,10 +105,9 @@ fn self_hosting_parsing() { .collect::>(); if !errors.is_empty() { - let errors = errors - .into_iter() - .map(|(path, err)| format!("{}: {:?}\n", path.display(), err[0])) - .collect::(); + let errors = errors.into_iter().fold(String::new(), |mut acc, (path, err)| { + format_to_acc!(acc, "{}: {:?}\n", path.display(), err[0]) + }); panic!("Parsing errors:\n{errors}\n"); } } From df2c7a6e4eca35d726795fb4baccc925d8ad7610 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Wed, 31 Jan 2024 16:29:50 +0100 Subject: [PATCH 178/246] `cargo clippy --fix` --- crates/hir-ty/src/utils.rs | 2 +- crates/ide-db/src/imports/merge_imports.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index c6e238ff8be0c..c0ca9d713ca31 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -440,7 +440,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( (db.enum_data(e).variants[index.0].0, layout) } hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => { - let size = tag.size(&*target_data_layout).bytes_usize(); + let size = tag.size(target_data_layout).bytes_usize(); let offset = layout.fields.offset(0).bytes_usize(); // The only field on enum variants is the tag field let tag = i128::from_le_bytes(pad16(&b[offset..offset + size], false)); match tag_encoding { diff --git a/crates/ide-db/src/imports/merge_imports.rs b/crates/ide-db/src/imports/merge_imports.rs index 77c32fd852eed..b153aafa0e179 100644 --- a/crates/ide-db/src/imports/merge_imports.rs +++ b/crates/ide-db/src/imports/merge_imports.rs @@ -467,8 +467,7 @@ fn recursive_normalize(use_tree: &ast::UseTree, style: NormalizationStyle) -> Op } ted::replace_all(start..=end, elements); } else { - let new_use_tree_list = - make::use_tree_list(subtrees.into_iter()).clone_for_update(); + let new_use_tree_list = make::use_tree_list(subtrees).clone_for_update(); ted::replace(use_tree_list.syntax(), new_use_tree_list.syntax()); } modified = true; From 44494e235a0558c531173fe25ede4f164ea2e4ef Mon Sep 17 00:00:00 2001 From: David Barsky Date: Tue, 30 Jan 2024 18:13:29 -0500 Subject: [PATCH 179/246] internal: teach hprof to record `tracing` fields --- crates/rust-analyzer/src/tracing/hprof.rs | 68 +++++++++++++++++------ 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/crates/rust-analyzer/src/tracing/hprof.rs b/crates/rust-analyzer/src/tracing/hprof.rs index f37262a17aa07..c99b551df8526 100644 --- a/crates/rust-analyzer/src/tracing/hprof.rs +++ b/crates/rust-analyzer/src/tracing/hprof.rs @@ -32,7 +32,8 @@ //! ``` use std::{ - fmt, mem, + fmt::Write, + mem, time::{Duration, Instant}, }; @@ -99,21 +100,37 @@ impl SpanTree { struct Data { start: Instant, children: Vec, + fields: String, } impl Data { fn new(attrs: &Attributes<'_>) -> Self { - let mut span = Self { start: Instant::now(), children: Vec::new() }; - attrs.record(&mut span); - span + let mut data = Self { start: Instant::now(), children: Vec::new(), fields: String::new() }; + + let mut visitor = DataVisitor { string: &mut data.fields }; + attrs.record(&mut visitor); + data } + fn into_node(self, name: &'static str) -> Node { - Node { name, count: 1, duration: self.start.elapsed(), children: self.children } + Node { + name, + fields: self.fields, + count: 1, + duration: self.start.elapsed(), + children: self.children, + } } } -impl Visit for Data { - fn record_debug(&mut self, _field: &Field, _value: &dyn fmt::Debug) {} +pub struct DataVisitor<'a> { + string: &'a mut String, +} + +impl<'a> Visit for DataVisitor<'a> { + fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) { + write!(self.string, "{} = {:?} ", field.name(), value).unwrap(); + } } impl Layer for SpanTree @@ -151,6 +168,7 @@ where #[derive(Default)] struct Node { name: &'static str, + fields: String, count: u32, duration: Duration, children: Vec, @@ -163,16 +181,22 @@ impl Node { fn go(&self, level: usize, filter: &WriteFilter) { if self.duration > filter.longer_than && level < filter.depth { - let duration = format!("{:3.2?}", self.duration); - let count = if self.count > 1 { self.count.to_string() } else { String::new() }; - eprintln!( - "{:width$} {:<9} {:<6} {}", - "", - duration, - count, - self.name, - width = level * 2 - ); + let duration = ms(self.duration); + let current_indent = level * 2; + + let mut out = String::new(); + let _ = write!(out, "{:current_indent$} {duration} {:<6}", "", self.name); + + if !self.fields.is_empty() { + let _ = write!(out, " @ {}", self.fields); + } + + if self.count > 1 { + let _ = write!(out, " ({} calls)", self.count); + } + + eprintln!("{}", out); + for child in &self.children { child.go(level + 1, filter) } @@ -236,3 +260,13 @@ impl WriteFilter { (WriteFilter { depth, longer_than }, allowed) } } + +#[allow(non_camel_case_types)] +struct ms(Duration); + +impl std::fmt::Display for ms { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let n = self.0.as_millis(); + write!(f, "{n:5}ms") + } +} From 400dc46a05f41ba1e1137f11073cec1951442668 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 24 Jan 2024 16:24:52 +0100 Subject: [PATCH 180/246] Gracefully abort on type incompatibility Since the only use of `TypeCx::bug` is in `Constructor::is_covered_by`, it is tempting to return `false` instead of `Err()`, but that would cause "non-exhaustive match" false positives. --- .../rustc_pattern_analysis/src/constructor.rs | 18 +++++++++++------- compiler/rustc_pattern_analysis/src/lib.rs | 2 +- .../rustc_pattern_analysis/src/pat_column.rs | 2 +- compiler/rustc_pattern_analysis/src/rustc.rs | 2 +- .../rustc_pattern_analysis/src/usefulness.rs | 8 ++++---- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 4be564b1d7b1e..7a91e14930961 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -826,10 +826,12 @@ impl Constructor { /// this checks for inclusion. // We inline because this has a single call site in `Matrix::specialize_constructor`. #[inline] - pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> bool { - match (self, other) { + pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> Result { + Ok(match (self, other) { (Wildcard, _) => { - cx.bug(format_args!("Constructor splitting should not have returned `Wildcard`")) + return Err(cx.bug(format_args!( + "Constructor splitting should not have returned `Wildcard`" + ))); } // Wildcards cover anything (_, Wildcard) => true, @@ -871,10 +873,12 @@ impl Constructor { (Opaque(self_id), Opaque(other_id)) => self_id == other_id, (Opaque(..), _) | (_, Opaque(..)) => false, - _ => cx.bug(format_args!( - "trying to compare incompatible constructors {self:?} and {other:?}" - )), - } + _ => { + return Err(cx.bug(format_args!( + "trying to compare incompatible constructors {self:?} and {other:?}" + ))); + } + }) } } diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 3d0eb117d174f..8e16d4d7bf4e2 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -123,7 +123,7 @@ pub trait TypeCx: Sized + fmt::Debug { ) -> fmt::Result; /// Raise a bug. - fn bug(&self, fmt: fmt::Arguments<'_>) -> !; + fn bug(&self, fmt: fmt::Arguments<'_>) -> Self::Error; /// Lint that the range `pat` overlapped with all the ranges in `overlaps_with`, where the range /// they overlapped over is `overlaps_on`. We only detect singleton overlaps. diff --git a/compiler/rustc_pattern_analysis/src/pat_column.rs b/compiler/rustc_pattern_analysis/src/pat_column.rs index 3cacfc491b981..0339818d61d31 100644 --- a/compiler/rustc_pattern_analysis/src/pat_column.rs +++ b/compiler/rustc_pattern_analysis/src/pat_column.rs @@ -78,7 +78,7 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { let mut specialized_columns: Vec<_> = (0..arity).map(|_| Self { patterns: Vec::new() }).collect(); let relevant_patterns = - self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor())); + self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor()).unwrap_or(false)); for pat in relevant_patterns { let specialized = pat.specialize(ctor, arity); for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index ec37e20211860..adcb5f827d5e7 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -900,7 +900,7 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { Ok(()) } - fn bug(&self, fmt: fmt::Arguments<'_>) -> ! { + fn bug(&self, fmt: fmt::Arguments<'_>) -> Self::Error { span_bug!(self.scrut_span, "{}", fmt) } diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 3d45d032a9934..d9da9bbbad079 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1082,7 +1082,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor, ctor_is_relevant: bool, - ) -> Matrix<'p, Cx> { + ) -> Result, Cx::Error> { let ctor_sub_tys = pcx.ctor_sub_tys(ctor); let arity = ctor_sub_tys.len(); let specialized_place_ty = ctor_sub_tys.chain(self.place_ty[1..].iter().cloned()).collect(); @@ -1098,12 +1098,12 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant, }; for (i, row) in self.rows().enumerate() { - if ctor.is_covered_by(pcx.cx, row.head().ctor()) { + if ctor.is_covered_by(pcx.cx, row.head().ctor())? { let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i); matrix.expand_and_push(new_row); } } - matrix + Ok(matrix) } } @@ -1533,7 +1533,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( // strictly fewer rows. In that case we can sometimes skip it. See the top of the file for // details. let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty(); - let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant); + let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant)?; let mut witnesses = ensure_sufficient_stack(|| { compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false) })?; From a1fdb876c34e7ad7ae36cfd49fd939e1fde00aa6 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 31 Jan 2024 19:06:10 +0000 Subject: [PATCH 181/246] Remove `abi_amdgpu_kernel` references --- crates/hir-ty/src/lib.rs | 3 --- crates/ide-completion/src/completions/extern_abi.rs | 1 - crates/ide-db/src/generated/lints.rs | 11 ----------- 3 files changed, 15 deletions(-) diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 54e91e7b29a66..288c42405d6a3 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -363,7 +363,6 @@ has_interner!(CallableSig); pub enum FnAbi { Aapcs, AapcsUnwind, - AmdgpuKernel, AvrInterrupt, AvrNonBlockingInterrupt, C, @@ -422,7 +421,6 @@ impl FnAbi { match s { "aapcs-unwind" => FnAbi::AapcsUnwind, "aapcs" => FnAbi::Aapcs, - "amdgpu-kernel" => FnAbi::AmdgpuKernel, "avr-interrupt" => FnAbi::AvrInterrupt, "avr-non-blocking-interrupt" => FnAbi::AvrNonBlockingInterrupt, "C-cmse-nonsecure-call" => FnAbi::CCmseNonsecureCall, @@ -465,7 +463,6 @@ impl FnAbi { match self { FnAbi::Aapcs => "aapcs", FnAbi::AapcsUnwind => "aapcs-unwind", - FnAbi::AmdgpuKernel => "amdgpu-kernel", FnAbi::AvrInterrupt => "avr-interrupt", FnAbi::AvrNonBlockingInterrupt => "avr-non-blocking-interrupt", FnAbi::C => "C", diff --git a/crates/ide-completion/src/completions/extern_abi.rs b/crates/ide-completion/src/completions/extern_abi.rs index 75017cf66f8db..b5d5604c7519f 100644 --- a/crates/ide-completion/src/completions/extern_abi.rs +++ b/crates/ide-completion/src/completions/extern_abi.rs @@ -26,7 +26,6 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[ "ptx-kernel", "msp430-interrupt", "x86-interrupt", - "amdgpu-kernel", "efiapi", "avr-interrupt", "avr-non-blocking-interrupt", diff --git a/crates/ide-db/src/generated/lints.rs b/crates/ide-db/src/generated/lints.rs index f160def0aff00..be8419686f44f 100644 --- a/crates/ide-db/src/generated/lints.rs +++ b/crates/ide-db/src/generated/lints.rs @@ -963,17 +963,6 @@ The tracking issue for this feature is: [#44839] [#44839]: https://github.com/rust-lang/rust/issues/44839 ------------------------- -"##, - }, - Lint { - label: "abi_amdgpu_kernel", - description: r##"# `abi_amdgpu_kernel` - -The tracking issue for this feature is: [#51575] - -[#51575]: https://github.com/rust-lang/rust/issues/51575 - ------------------------ "##, }, From 23f4b7f45fc588b250b6dc6fd8fe5fc31840ce24 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 31 Jan 2024 22:06:05 +0100 Subject: [PATCH 182/246] Remove stdx::eprintln overwrite --- crates/rust-analyzer/src/lib.rs | 5 ----- crates/stdx/src/macros.rs | 10 ---------- 2 files changed, 15 deletions(-) diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs index b77e1dca29f0d..7f97f84809c32 100644 --- a/crates/rust-analyzer/src/lib.rs +++ b/crates/rust-analyzer/src/lib.rs @@ -13,11 +13,6 @@ pub mod cli; -#[allow(unused)] -macro_rules! eprintln { - ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; -} - mod caps; mod cargo_target_spec; mod diagnostics; diff --git a/crates/stdx/src/macros.rs b/crates/stdx/src/macros.rs index d71e418c89bc6..8fec7229cf149 100644 --- a/crates/stdx/src/macros.rs +++ b/crates/stdx/src/macros.rs @@ -1,15 +1,5 @@ //! Convenience macros. -#[macro_export] -macro_rules! eprintln { - ($($tt:tt)*) => {{ - if $crate::is_ci() { - panic!("Forgot to remove debug-print?") - } - std::eprintln!($($tt)*) - }} -} - /// Appends formatted string to a `String`. #[macro_export] macro_rules! format_to { From 2aebe6c302088dcd75ae18f40b40f6860c505450 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 31 Jan 2024 19:02:58 -0800 Subject: [PATCH 183/246] CI: Use ninja on apple builders --- .github/workflows/ci.yml | 10 +++++----- src/ci/github-actions/ci.yml | 7 +++---- src/ci/scripts/install-ninja.sh | 2 ++ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 346bdd41b0a40..02a2193ad883f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -319,7 +319,7 @@ jobs: - name: dist-x86_64-apple env: SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin" - RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin" + RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 SELECT_XCODE: /Applications/Xcode_13.4.1.app @@ -332,7 +332,7 @@ jobs: - name: dist-apple-various env: SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" - RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" + RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 SELECT_XCODE: /Applications/Xcode_13.4.1.app @@ -343,7 +343,7 @@ jobs: - name: x86_64-apple-1 env: SCRIPT: "./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps" - RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" + RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 @@ -354,7 +354,7 @@ jobs: - name: x86_64-apple-2 env: SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps" - RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" + RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 @@ -365,7 +365,7 @@ jobs: - name: dist-aarch64-apple env: SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2" - RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --host=aarch64-apple-darwin --target=aarch64-apple-darwin --enable-full-tools --enable-sanitizers --enable-profiler --disable-docs --set rust.jemalloc --set llvm.ninja=false" + RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --host=aarch64-apple-darwin --target=aarch64-apple-darwin --enable-full-tools --enable-sanitizers --enable-profiler --disable-docs --set rust.jemalloc" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 SELECT_XCODE: /Applications/Xcode_13.4.1.app USE_XCODE_CLANG: 1 diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index fef2245e672c9..61e0e2c0bc7f5 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -511,7 +511,7 @@ jobs: - name: dist-x86_64-apple env: SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin - RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin + RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 SELECT_XCODE: /Applications/Xcode_13.4.1.app @@ -525,7 +525,7 @@ jobs: - name: dist-apple-various env: SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim - RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false + RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 SELECT_XCODE: /Applications/Xcode_13.4.1.app @@ -537,7 +537,7 @@ jobs: - name: x86_64-apple-1 env: &env-x86_64-apple-tests SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 @@ -565,7 +565,6 @@ jobs: --enable-profiler --disable-docs --set rust.jemalloc - --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 SELECT_XCODE: /Applications/Xcode_13.4.1.app USE_XCODE_CLANG: 1 diff --git a/src/ci/scripts/install-ninja.sh b/src/ci/scripts/install-ninja.sh index b8261d8a6f284..5145a03e353de 100755 --- a/src/ci/scripts/install-ninja.sh +++ b/src/ci/scripts/install-ninja.sh @@ -13,4 +13,6 @@ if isWindows; then rm ninja.zip ciCommandSetEnv "RUST_CONFIGURE_ARGS" "${RUST_CONFIGURE_ARGS} --enable-ninja" ciCommandAddPath "$(pwd)/ninja" +elif isMacOS; then + brew install ninja fi From c4c22b0d52e9699edd02fd3a7a61965f296ba605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 24 Jan 2024 21:29:15 +0000 Subject: [PATCH 184/246] On E0277 be clearer about implicit `Sized` bounds on type params and assoc types ``` error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> f100.rs:2:33 | 2 | let _ = std::mem::size_of::<[i32]>(); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i32]` note: required by an implicit `Sized` bound in `std::mem::size_of` --> /home/gh-estebank/rust/library/core/src/mem/mod.rs:312:22 | 312 | pub const fn size_of() -> usize { | ^ required by the implicit `Sized` requirement on this bound in `size_of` ``` Fix #120178. --- .../rustc_hir_analysis/src/astconv/bounds.rs | 14 +- .../src/traits/error_reporting/suggestions.rs | 159 ++++++++++-------- tests/ui/associated-types/defaults-wf.stderr | 2 +- tests/ui/associated-types/issue-20005.stderr | 4 +- ...with-supertraits-needing-sized-self.stderr | 2 +- tests/ui/closures/issue-111932.stderr | 2 +- tests/ui/coroutine/sized-yield.stderr | 2 +- tests/ui/dst/dst-sized-trait-param.stderr | 4 +- tests/ui/extern/extern-types-unsized.stderr | 16 +- .../issue-88287.stderr | 4 +- ...e-param-can-reference-self-in-trait.stderr | 4 +- tests/ui/impl-trait/in-trait/wf-bounds.stderr | 8 +- tests/ui/issues/issue-10412.stderr | 4 +- tests/ui/issues/issue-18919.stderr | 4 +- tests/ui/issues/issue-20433.stderr | 2 +- tests/ui/issues/issue-23281.stderr | 4 +- tests/ui/issues/issue-87199.stderr | 4 +- tests/ui/iterators/collect-into-slice.rs | 2 +- tests/ui/iterators/collect-into-slice.stderr | 2 +- .../do-not-ice-on-note_and_explain.stderr | 4 +- tests/ui/methods/issues/issue-61525.stderr | 4 +- ...ect-safety-supertrait-mentions-Self.stderr | 4 +- tests/ui/range/range-1.stderr | 2 +- tests/ui/str/str-mut-idx.stderr | 4 +- ...adt-param-with-implicit-sized-bound.stderr | 20 +-- tests/ui/suggestions/bound-suggestions.stderr | 10 +- .../suggestions/issue-84973-blacklist.stderr | 4 +- ...unsized-indirection-in-where-clause.stderr | 4 +- ...re-clause-before-suggesting-unsized.stderr | 4 +- ...ltiline-trait-bound-in-where-clause.stderr | 12 +- tests/ui/trait-bounds/unsized-bound.stderr | 36 ++-- tests/ui/traits/bad-sized.stderr | 4 +- tests/ui/traits/issue-28576.stderr | 8 +- .../traits/issue-85360-eval-obligation-ice.rs | 2 - .../issue-85360-eval-obligation-ice.stderr | 22 +-- .../mutual-recursion-issue-75860.stderr | 2 +- tests/ui/traits/suggest-where-clause.stderr | 8 +- tests/ui/unsized/unsized-bare-typaram.stderr | 4 +- tests/ui/unsized/unsized-enum.stderr | 4 +- .../unsized-inherent-impl-self-type.stderr | 4 +- tests/ui/unsized/unsized-struct.stderr | 8 +- .../unsized-trait-impl-self-type.stderr | 4 +- .../unsized-trait-impl-trait-arg.stderr | 4 +- tests/ui/unsized/unsized3.stderr | 16 +- tests/ui/unsized/unsized7.stderr | 4 +- tests/ui/wf/hir-wf-canonicalized.stderr | 4 +- tests/ui/wf/wf-fn-where-clause.stderr | 4 +- tests/ui/wf/wf-impl-self-type.stderr | 2 +- 48 files changed, 232 insertions(+), 223 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index c22daad334fc5..e37119e7d4dc8 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -28,6 +28,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let tcx = self.tcx(); let sized_def_id = tcx.lang_items().sized_trait(); let mut seen_negative_sized_bound = false; + let mut seen_positive_sized_bound = false; // Try to find an unbound in bounds. let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); @@ -45,6 +46,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { seen_negative_sized_bound = true; } } + hir::TraitBoundModifier::None => { + if let Some(sized_def_id) = sized_def_id + && ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) + { + seen_positive_sized_bound = true; + } + } _ => {} } } @@ -82,11 +90,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { ); } - if seen_sized_unbound || seen_negative_sized_bound { - // There was in fact a `?Sized` or `!Sized` bound; + if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound { + // There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound; // we don't need to do anything. } else if sized_def_id.is_some() { - // There was no `?Sized` or `!Sized` bound; + // There was no `?Sized`, `!Sized` or explicit `Sized` bound; // add `Sized` if it's available. bounds.push_sized(tcx, self_ty, span); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 5bab57ca56cb4..3060f33330e51 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3009,35 +3009,44 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } } - let descr = format!("required by a bound in `{item_name}`"); - if span.is_visible(sm) { - let msg = format!("required by this bound in `{short_item_name}`"); - multispan.push_span_label(span, msg); - err.span_note(multispan, descr); - if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() - && let ty::ClauseKind::Trait(trait_pred) = clause - { - let def_id = trait_pred.def_id(); - let visible_item = if let Some(local) = def_id.as_local() { - // Check for local traits being reachable. - let vis = &tcx.resolutions(()).effective_visibilities; - // Account for non-`pub` traits in the root of the local crate. - let is_locally_reachable = tcx.parent(def_id).is_crate_root(); - vis.is_reachable(local) || is_locally_reachable - } else { - // Check for foreign traits being reachable. - tcx.visible_parent_map(()).get(&def_id).is_some() - }; - if Some(def_id) == tcx.lang_items().sized_trait() - && let Some(hir::Node::TraitItem(hir::TraitItem { - ident, - kind: hir::TraitItemKind::Type(bounds, None), - .. - })) = tcx.hir().get_if_local(item_def_id) - // Do not suggest relaxing if there is an explicit `Sized` obligation. - && !bounds.iter() - .filter_map(|bound| bound.trait_ref()) - .any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait()) + let mut a = "a"; + let mut this = "this"; + let mut note = None; + let mut help = None; + if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() + && let ty::ClauseKind::Trait(trait_pred) = clause + { + let def_id = trait_pred.def_id(); + let visible_item = if let Some(local) = def_id.as_local() { + // Check for local traits being reachable. + let vis = &tcx.resolutions(()).effective_visibilities; + // Account for non-`pub` traits in the root of the local crate. + let is_locally_reachable = tcx.parent(def_id).is_crate_root(); + vis.is_reachable(local) || is_locally_reachable + } else { + // Check for foreign traits being reachable. + tcx.visible_parent_map(()).get(&def_id).is_some() + }; + if Some(def_id) == tcx.lang_items().sized_trait() { + // Check if this is an implicit bound, even in foreign crates. + if tcx + .generics_of(item_def_id) + .params + .iter() + .any(|param| tcx.def_span(param.def_id) == span) + { + a = "an implicit `Sized`"; + this = "the implicit `Sized` requirement on this"; + } + if let Some(hir::Node::TraitItem(hir::TraitItem { + ident, + kind: hir::TraitItemKind::Type(bounds, None), + .. + })) = tcx.hir().get_if_local(item_def_id) + // Do not suggest relaxing if there is an explicit `Sized` obligation. + && !bounds.iter() + .filter_map(|bound| bound.trait_ref()) + .any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait()) { let (span, separator) = if let [.., last] = bounds { (last.span().shrink_to_hi(), " +") @@ -3051,52 +3060,64 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { Applicability::MachineApplicable, ); } - if let DefKind::Trait = tcx.def_kind(item_def_id) - && !visible_item - { - err.note(format!( - "`{short_item_name}` is a \"sealed trait\", because to implement \ - it you also need to implement `{}`, which is not accessible; \ - this is usually done to force you to use one of the provided \ - types that already implement it", - with_no_trimmed_paths!(tcx.def_path_str(def_id)), - )); - let impls_of = tcx.trait_impls_of(def_id); - let impls = impls_of - .non_blanket_impls() - .values() - .flatten() - .chain(impls_of.blanket_impls().iter()) + } + if let DefKind::Trait = tcx.def_kind(item_def_id) + && !visible_item + { + note = Some(format!( + "`{short_item_name}` is a \"sealed trait\", because to implement it \ + you also need to implement `{}`, which is not accessible; this is \ + usually done to force you to use one of the provided types that \ + already implement it", + with_no_trimmed_paths!(tcx.def_path_str(def_id)), + )); + let impls_of = tcx.trait_impls_of(def_id); + let impls = impls_of + .non_blanket_impls() + .values() + .flatten() + .chain(impls_of.blanket_impls().iter()) + .collect::>(); + if !impls.is_empty() { + let len = impls.len(); + let mut types = impls + .iter() + .map(|t| { + with_no_trimmed_paths!(format!( + " {}", + tcx.type_of(*t).instantiate_identity(), + )) + }) .collect::>(); - if !impls.is_empty() { - let len = impls.len(); - let mut types = impls - .iter() - .map(|t| { - with_no_trimmed_paths!(format!( - " {}", - tcx.type_of(*t).instantiate_identity(), - )) - }) - .collect::>(); - let post = if types.len() > 9 { - types.truncate(8); - format!("\nand {} others", len - 8) - } else { - String::new() - }; - err.help(format!( - "the following type{} implement{} the trait:\n{}{post}", - pluralize!(len), - if len == 1 { "s" } else { "" }, - types.join("\n"), - )); - } + let post = if types.len() > 9 { + types.truncate(8); + format!("\nand {} others", len - 8) + } else { + String::new() + }; + help = Some(format!( + "the following type{} implement{} the trait:\n{}{post}", + pluralize!(len), + if len == 1 { "s" } else { "" }, + types.join("\n"), + )); } } + }; + let descr = format!("required by {a} bound in `{item_name}`"); + if span.is_visible(sm) { + let msg = format!("required by {this} bound in `{short_item_name}`"); + multispan.push_span_label(span, msg); + err.span_note(multispan, descr); } else { err.span_note(tcx.def_span(item_def_id), descr); } + if let Some(note) = note { + err.note(note); + } + if let Some(help) = help { + err.help(help); + } } ObligationCauseCode::Coercion { source, target } => { let mut file = None; diff --git a/tests/ui/associated-types/defaults-wf.stderr b/tests/ui/associated-types/defaults-wf.stderr index aeb4e47abcbf7..f0b10189bd8d9 100644 --- a/tests/ui/associated-types/defaults-wf.stderr +++ b/tests/ui/associated-types/defaults-wf.stderr @@ -5,7 +5,7 @@ LL | type Ty = Vec<[u8]>; | ^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/issue-20005.stderr b/tests/ui/associated-types/issue-20005.stderr index 02470a4424919..ce3f556f2d744 100644 --- a/tests/ui/associated-types/issue-20005.stderr +++ b/tests/ui/associated-types/issue-20005.stderr @@ -4,11 +4,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | ) -> >::Result where Dst: From { | ^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `From` +note: required by an implicit `Sized` bound in `From` --> $DIR/issue-20005.rs:1:12 | LL | trait From { - | ^^^ required by this bound in `From` + | ^^^ required by the implicit `Sized` requirement on this bound in `From` help: consider further restricting `Self` | LL | ) -> >::Result where Dst: From, Self: Sized { diff --git a/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr b/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr index 99a46dedcdce6..8154441411323 100644 --- a/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr +++ b/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | trait ArithmeticOps: Add + Sub + Mul + Div {} | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Add` +note: required by an implicit `Sized` bound in `Add` --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: consider further restricting `Self` | diff --git a/tests/ui/closures/issue-111932.stderr b/tests/ui/closures/issue-111932.stderr index 937bdf3bea255..ff46b10d005dc 100644 --- a/tests/ui/closures/issue-111932.stderr +++ b/tests/ui/closures/issue-111932.stderr @@ -17,7 +17,7 @@ LL | println!("{:?}", foo); | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `dyn Foo` -note: required by a bound in `core::fmt::rt::Argument::<'a>::new_debug` +note: required by an implicit `Sized` bound in `core::fmt::rt::Argument::<'a>::new_debug` --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/coroutine/sized-yield.stderr b/tests/ui/coroutine/sized-yield.stderr index bbecaffa95a12..4e8dc13201de3 100644 --- a/tests/ui/coroutine/sized-yield.stderr +++ b/tests/ui/coroutine/sized-yield.stderr @@ -18,7 +18,7 @@ LL | Pin::new(&mut gen).resume(()); | ^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` -note: required by a bound in `CoroutineState` +note: required by an implicit `Sized` bound in `CoroutineState` --> $SRC_DIR/core/src/ops/coroutine.rs:LL:COL error: aborting due to 2 previous errors diff --git a/tests/ui/dst/dst-sized-trait-param.stderr b/tests/ui/dst/dst-sized-trait-param.stderr index 60e9de90332cc..a3a686dced217 100644 --- a/tests/ui/dst/dst-sized-trait-param.stderr +++ b/tests/ui/dst/dst-sized-trait-param.stderr @@ -5,11 +5,11 @@ LL | impl Foo<[isize]> for usize { } | ^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[isize]` -note: required by a bound in `Foo` +note: required by an implicit `Sized` bound in `Foo` --> $DIR/dst-sized-trait-param.rs:5:11 | LL | trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is sized - | ^ required by this bound in `Foo` + | ^ required by the implicit `Sized` requirement on this bound in `Foo` help: consider relaxing the implicit `Sized` restriction | LL | trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is sized diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr index 0ae33e25b811e..6592724a53e70 100644 --- a/tests/ui/extern/extern-types-unsized.stderr +++ b/tests/ui/extern/extern-types-unsized.stderr @@ -5,11 +5,11 @@ LL | assert_sized::(); | ^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `A` -note: required by a bound in `assert_sized` +note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this bound in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} @@ -27,11 +27,11 @@ note: required because it appears within the type `Foo` | LL | struct Foo { | ^^^ -note: required by a bound in `assert_sized` +note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this bound in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} @@ -49,11 +49,11 @@ note: required because it appears within the type `Bar` | LL | struct Bar { | ^^^ -note: required by a bound in `assert_sized` +note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this bound in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} @@ -71,11 +71,11 @@ note: required because it appears within the type `Bar` | LL | struct Bar { | ^^^ -note: required by a bound in `assert_sized` +note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this bound in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} diff --git a/tests/ui/generic-associated-types/issue-88287.stderr b/tests/ui/generic-associated-types/issue-88287.stderr index 79ac6d0f10bd2..6b26223dd5144 100644 --- a/tests/ui/generic-associated-types/issue-88287.stderr +++ b/tests/ui/generic-associated-types/issue-88287.stderr @@ -7,11 +7,11 @@ LL | type SearchFutureTy<'f, A, B: 'f> LL | async move { todo!() } | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `>` +note: required by an implicit `Sized` bound in `>` --> $DIR/issue-88287.rs:24:6 | LL | impl SearchableResourceExt for T - | ^ required by this bound in `>` + | ^ required by the implicit `Sized` requirement on this bound in `>` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - A: SearchableResource + ?Sized + 'f, diff --git a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr index 3f4f50562e252..3739829455bde 100644 --- a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr +++ b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr @@ -6,10 +6,10 @@ LL | impl Tsized for () {} | = help: the trait `Sized` is not implemented for `[()]` note: required by a bound in `Tsized` - --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:17:14 + --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:17:17 | LL | trait Tsized {} - | ^^^^^^^^^^^^^^^^^ required by this bound in `Tsized` + | ^^^^^ required by this bound in `Tsized` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.stderr index c20df9b40edfb..e2e06ba4e5ae8 100644 --- a/tests/ui/impl-trait/in-trait/wf-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/wf-bounds.stderr @@ -5,7 +5,7 @@ LL | fn nya() -> impl Wf>; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: the size for values of type `[u8]` cannot be known at compilation time @@ -15,11 +15,11 @@ LL | fn nya2() -> impl Wf<[u8]>; | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `Wf` +note: required by an implicit `Sized` bound in `Wf` --> $DIR/wf-bounds.rs:7:10 | LL | trait Wf { - | ^ required by this bound in `Wf` + | ^ required by the implicit `Sized` requirement on this bound in `Wf` help: consider relaxing the implicit `Sized` restriction | LL | trait Wf { @@ -32,7 +32,7 @@ LL | fn nya3() -> impl Wf<(), Output = impl Wf>>; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: `T` doesn't implement `std::fmt::Display` diff --git a/tests/ui/issues/issue-10412.stderr b/tests/ui/issues/issue-10412.stderr index 26666782d2abc..dcf7769264b22 100644 --- a/tests/ui/issues/issue-10412.stderr +++ b/tests/ui/issues/issue-10412.stderr @@ -58,11 +58,11 @@ LL | impl<'self> Serializable for &'self str { | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` -note: required by a bound in `Serializable` +note: required by an implicit `Sized` bound in `Serializable` --> $DIR/issue-10412.rs:1:27 | LL | trait Serializable<'self, T> { - | ^ required by this bound in `Serializable` + | ^ required by the implicit `Sized` requirement on this bound in `Serializable` help: consider relaxing the implicit `Sized` restriction | LL | trait Serializable<'self, T: ?Sized> { diff --git a/tests/ui/issues/issue-18919.stderr b/tests/ui/issues/issue-18919.stderr index 6dcd891cedac9..471b5d5bdf12a 100644 --- a/tests/ui/issues/issue-18919.stderr +++ b/tests/ui/issues/issue-18919.stderr @@ -5,11 +5,11 @@ LL | fn ho_func(f: Option) { | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn for<'a> Fn(&'a isize) -> isize` -note: required by a bound in `Option` +note: required by an implicit `Sized` bound in `Option` --> $DIR/issue-18919.rs:7:13 | LL | enum Option { - | ^ required by this bound in `Option` + | ^ required by the implicit `Sized` requirement on this bound in `Option` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/issue-18919.rs:7:13 | diff --git a/tests/ui/issues/issue-20433.stderr b/tests/ui/issues/issue-20433.stderr index 2dd0b3c2f8439..3730a67cc7959 100644 --- a/tests/ui/issues/issue-20433.stderr +++ b/tests/ui/issues/issue-20433.stderr @@ -5,7 +5,7 @@ LL | fn iceman(c: Vec<[i32]>) {} | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i32]` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-23281.stderr b/tests/ui/issues/issue-23281.stderr index e1f4e8a96c825..4c25d1efedd6a 100644 --- a/tests/ui/issues/issue-23281.stderr +++ b/tests/ui/issues/issue-23281.stderr @@ -5,11 +5,11 @@ LL | pub fn function(funs: Vec ()>) {} | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Fn() + 'static)` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $DIR/issue-23281.rs:8:12 | LL | struct Vec { - | ^ required by this bound in `Vec` + | ^ required by the implicit `Sized` requirement on this bound in `Vec` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/issue-23281.rs:8:12 | diff --git a/tests/ui/issues/issue-87199.stderr b/tests/ui/issues/issue-87199.stderr index d81bc3615575e..6c4fbddb04924 100644 --- a/tests/ui/issues/issue-87199.stderr +++ b/tests/ui/issues/issue-87199.stderr @@ -23,11 +23,11 @@ LL | ref_arg::<[i32]>(&[5]); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i32]` -note: required by a bound in `ref_arg` +note: required by an implicit `Sized` bound in `ref_arg` --> $DIR/issue-87199.rs:10:12 | LL | fn ref_arg(_: &T) {} - | ^ required by this bound in `ref_arg` + | ^ required by the implicit `Sized` requirement on this bound in `ref_arg` help: consider relaxing the implicit `Sized` restriction | LL | fn ref_arg(_: &T) {} diff --git a/tests/ui/iterators/collect-into-slice.rs b/tests/ui/iterators/collect-into-slice.rs index 045d40a6f71ae..120e56a6549e4 100644 --- a/tests/ui/iterators/collect-into-slice.rs +++ b/tests/ui/iterators/collect-into-slice.rs @@ -8,7 +8,7 @@ fn main() { //~| ERROR the size for values of type `[i32]` cannot be known at compilation time //~| ERROR a slice of type `[i32]` cannot be built since `[i32]` has no definite size //~| NOTE try explicitly collecting into a `Vec<{integer}>` - //~| NOTE required by a bound in `collect` + //~| NOTE required by an implicit `Sized` bound in `collect` //~| NOTE required by a bound in `collect` //~| NOTE all local variables must have a statically known size //~| NOTE doesn't have a size known at compile-time diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr index 45685ef0ce9cd..56f1bf770607e 100644 --- a/tests/ui/iterators/collect-into-slice.stderr +++ b/tests/ui/iterators/collect-into-slice.stderr @@ -25,7 +25,7 @@ LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i32]` -note: required by a bound in `collect` +note: required by an implicit `Sized` bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error[E0277]: a slice of type `&[i32]` cannot be built since we need to store the elements somewhere diff --git a/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr index 27b86145e90f4..47c01b9e805d8 100644 --- a/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr +++ b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr @@ -60,11 +60,11 @@ LL | implA{fn d(){fn d(){Self(1)}}} | | | this type parameter needs to be `Sized` | -note: required by a bound in `A` +note: required by an implicit `Sized` bound in `A` --> $DIR/do-not-ice-on-note_and_explain.rs:1:10 | LL | struct A(B); - | ^ required by this bound in `A` + | ^ required by the implicit `Sized` requirement on this bound in `A` help: you could relax the implicit `Sized` bound on `B` if it were used through indirection like `&B` or `Box` --> $DIR/do-not-ice-on-note_and_explain.rs:1:10 | diff --git a/tests/ui/methods/issues/issue-61525.stderr b/tests/ui/methods/issues/issue-61525.stderr index 2670a3e4755b1..777d0b4f3d125 100644 --- a/tests/ui/methods/issues/issue-61525.stderr +++ b/tests/ui/methods/issues/issue-61525.stderr @@ -7,11 +7,11 @@ LL | 1.query::("") | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `dyn ToString` -note: required by a bound in `Example::query` +note: required by an implicit `Sized` bound in `Example::query` --> $DIR/issue-61525.rs:2:14 | LL | fn query(self, q: Q); - | ^ required by this bound in `Example::query` + | ^ required by the implicit `Sized` requirement on this bound in `Example::query` help: consider relaxing the implicit `Sized` restriction | LL | fn query(self, q: Q); diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr index 22adc19c8029f..2380cba89486f 100644 --- a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr +++ b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr @@ -22,11 +22,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | trait Baz : Bar { | ^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Bar` +note: required by an implicit `Sized` bound in `Bar` --> $DIR/object-safety-supertrait-mentions-Self.rs:4:11 | LL | trait Bar { - | ^ required by this bound in `Bar` + | ^ required by the implicit `Sized` requirement on this bound in `Bar` help: consider further restricting `Self` | LL | trait Baz : Bar + Sized { diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr index 569f700cf10ba..3d9b7a940b7c8 100644 --- a/tests/ui/range/range-1.stderr +++ b/tests/ui/range/range-1.stderr @@ -30,7 +30,7 @@ LL | let range = *arr..; | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[{integer}]` -note: required by a bound in `RangeFrom` +note: required by an implicit `Sized` bound in `RangeFrom` --> $SRC_DIR/core/src/ops/range.rs:LL:COL error: aborting due to 3 previous errors diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr index 17a75bf8c2ae6..5a2664f4522e8 100644 --- a/tests/ui/str/str-mut-idx.stderr +++ b/tests/ui/str/str-mut-idx.stderr @@ -5,11 +5,11 @@ LL | s[1..2] = bot(); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` -note: required by a bound in `bot` +note: required by an implicit `Sized` bound in `bot` --> $DIR/str-mut-idx.rs:1:8 | LL | fn bot() -> T { loop {} } - | ^ required by this bound in `bot` + | ^ required by the implicit `Sized` requirement on this bound in `bot` help: consider relaxing the implicit `Sized` restriction | LL | fn bot() -> T { loop {} } diff --git a/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr index d136f5ff6543f..705f078c367d0 100644 --- a/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr +++ b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr @@ -6,11 +6,11 @@ LL | struct Struct5{ LL | _t: X, | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `X` +note: required by an implicit `Sized` bound in `X` --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 | LL | struct X(T); - | ^ required by this bound in `X` + | ^ required by the implicit `Sized` requirement on this bound in `X` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 | @@ -30,11 +30,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | fn func1() -> Struct1; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Struct1` +note: required by an implicit `Sized` bound in `Struct1` --> $DIR/adt-param-with-implicit-sized-bound.rs:8:16 | LL | struct Struct1{ - | ^ required by this bound in `Struct1` + | ^ required by the implicit `Sized` requirement on this bound in `Struct1` help: consider further restricting `Self` | LL | fn func1() -> Struct1 where Self: Sized; @@ -50,11 +50,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | fn func2<'a>() -> Struct2<'a, Self>; | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Struct2` +note: required by an implicit `Sized` bound in `Struct2` --> $DIR/adt-param-with-implicit-sized-bound.rs:11:20 | LL | struct Struct2<'a, T>{ - | ^ required by this bound in `Struct2` + | ^ required by the implicit `Sized` requirement on this bound in `Struct2` help: consider further restricting `Self` | LL | fn func2<'a>() -> Struct2<'a, Self> where Self: Sized; @@ -70,11 +70,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | fn func3() -> Struct3; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Struct3` +note: required by an implicit `Sized` bound in `Struct3` --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16 | LL | struct Struct3{ - | ^ required by this bound in `Struct3` + | ^ required by the implicit `Sized` requirement on this bound in `Struct3` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16 | @@ -93,11 +93,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | fn func4() -> Struct4; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Struct4` +note: required by an implicit `Sized` bound in `Struct4` --> $DIR/adt-param-with-implicit-sized-bound.rs:20:16 | LL | struct Struct4{ - | ^ required by this bound in `Struct4` + | ^ required by the implicit `Sized` requirement on this bound in `Struct4` help: consider further restricting `Self` | LL | fn func4() -> Struct4 where Self: Sized; diff --git a/tests/ui/suggestions/bound-suggestions.stderr b/tests/ui/suggestions/bound-suggestions.stderr index cd27947f02fad..7e58ccd461d19 100644 --- a/tests/ui/suggestions/bound-suggestions.stderr +++ b/tests/ui/suggestions/bound-suggestions.stderr @@ -76,7 +76,7 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider further restricting `Self` | @@ -89,7 +89,7 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider further restricting `Self` | @@ -102,7 +102,7 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider further restricting `Self` | @@ -115,7 +115,7 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider further restricting `Self` | @@ -128,7 +128,7 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider further restricting `Self` | diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr index e0bdb6949a9c9..8e980997089e6 100644 --- a/tests/ui/suggestions/issue-84973-blacklist.stderr +++ b/tests/ui/suggestions/issue-84973-blacklist.stderr @@ -57,10 +57,10 @@ LL | f_sized(*ref_cl); | = help: the trait `Sized` is not implemented for `dyn Fn()` note: required by a bound in `f_sized` - --> $DIR/issue-84973-blacklist.rs:9:12 + --> $DIR/issue-84973-blacklist.rs:9:15 | LL | fn f_sized(t: T) {} - | ^ required by this bound in `f_sized` + | ^^^^^ required by this bound in `f_sized` error[E0277]: `Rc<{integer}>` cannot be sent between threads safely --> $DIR/issue-84973-blacklist.rs:27:12 diff --git a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr index 21b568b02ad25..e2f1532cc4eaf 100644 --- a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr +++ b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr @@ -5,11 +5,11 @@ LL | struct B(A<[u8]>); | ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `A` +note: required by an implicit `Sized` bound in `A` --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10 | LL | struct A(T) where T: Send; - | ^ required by this bound in `A` + | ^ required by the implicit `Sized` requirement on this bound in `A` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10 | diff --git a/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr index 77e5dcd91a1ea..1cbcfbf84bcf4 100644 --- a/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr +++ b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr @@ -8,10 +8,10 @@ LL | fn bar() { foo(""); } | = help: the trait `Sized` is not implemented for `str` note: required by a bound in `foo` - --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:8 + --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:27 | LL | fn foo(_: &T) where T: Sized {} - | ^ required by this bound in `foo` + | ^^^^^ required by this bound in `foo` error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr index eb74679d66049..7d20120654af3 100644 --- a/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr +++ b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr @@ -6,11 +6,11 @@ LL | fn foo(foo: Wrapper) | | | this type parameter needs to be `Sized` | -note: required by a bound in `Wrapper` +note: required by an implicit `Sized` bound in `Wrapper` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | LL | struct Wrapper(T); - | ^ required by this bound in `Wrapper` + | ^ required by the implicit `Sized` requirement on this bound in `Wrapper` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | @@ -35,11 +35,11 @@ LL | fn bar(foo: Wrapper) | | | this type parameter needs to be `Sized` | -note: required by a bound in `Wrapper` +note: required by an implicit `Sized` bound in `Wrapper` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | LL | struct Wrapper(T); - | ^ required by this bound in `Wrapper` + | ^ required by the implicit `Sized` requirement on this bound in `Wrapper` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | @@ -60,11 +60,11 @@ LL | fn qux(foo: Wrapper) | | | this type parameter needs to be `Sized` | -note: required by a bound in `Wrapper` +note: required by an implicit `Sized` bound in `Wrapper` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | LL | struct Wrapper(T); - | ^ required by this bound in `Wrapper` + | ^ required by the implicit `Sized` requirement on this bound in `Wrapper` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | diff --git a/tests/ui/trait-bounds/unsized-bound.stderr b/tests/ui/trait-bounds/unsized-bound.stderr index 4d45bffabce5e..87a43a6fddab0 100644 --- a/tests/ui/trait-bounds/unsized-bound.stderr +++ b/tests/ui/trait-bounds/unsized-bound.stderr @@ -7,11 +7,11 @@ LL | impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} | this type parameter needs to be `Sized` | = note: required because it appears within the type `(A, B)` -note: required by a bound in `Trait` +note: required by an implicit `Sized` bound in `Trait` --> $DIR/unsized-bound.rs:1:13 | LL | trait Trait {} - | ^ required by this bound in `Trait` + | ^ required by the implicit `Sized` requirement on this bound in `Trait` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} @@ -46,11 +46,11 @@ LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Size | this type parameter needs to be `Sized` | = note: required because it appears within the type `(A, B, C)` -note: required by a bound in `Trait` +note: required by an implicit `Sized` bound in `Trait` --> $DIR/unsized-bound.rs:1:13 | LL | trait Trait {} - | ^ required by this bound in `Trait` + | ^ required by the implicit `Sized` requirement on this bound in `Trait` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} @@ -96,11 +96,11 @@ LL | impl Trait2<(A, B)> for (A, B) {} | this type parameter needs to be `Sized` | = note: required because it appears within the type `(A, B)` -note: required by a bound in `Trait2` +note: required by an implicit `Sized` bound in `Trait2` --> $DIR/unsized-bound.rs:9:14 | LL | trait Trait2 {} - | ^ required by this bound in `Trait2` + | ^ required by the implicit `Sized` requirement on this bound in `Trait2` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait2<(A, B)> for (A, B) {} @@ -134,11 +134,11 @@ LL | impl Trait3 for A where A: ?Sized {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait3` +note: required by an implicit `Sized` bound in `Trait3` --> $DIR/unsized-bound.rs:13:14 | LL | trait Trait3 {} - | ^ required by this bound in `Trait3` + | ^ required by the implicit `Sized` requirement on this bound in `Trait3` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait3 for A where A: ?Sized {} @@ -157,11 +157,11 @@ LL | impl Trait4 for A {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait4` +note: required by an implicit `Sized` bound in `Trait4` --> $DIR/unsized-bound.rs:16:14 | LL | trait Trait4 {} - | ^ required by this bound in `Trait4` + | ^ required by the implicit `Sized` requirement on this bound in `Trait4` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait4 for A {} @@ -180,11 +180,11 @@ LL | impl Trait5 for X where X: ?Sized {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait5` +note: required by an implicit `Sized` bound in `Trait5` --> $DIR/unsized-bound.rs:19:14 | LL | trait Trait5 {} - | ^ required by this bound in `Trait5` + | ^ required by the implicit `Sized` requirement on this bound in `Trait5` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait5 for X where X: ?Sized {} @@ -203,11 +203,11 @@ LL | impl Trait6 for X {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait6` +note: required by an implicit `Sized` bound in `Trait6` --> $DIR/unsized-bound.rs:22:14 | LL | trait Trait6 {} - | ^ required by this bound in `Trait6` + | ^ required by the implicit `Sized` requirement on this bound in `Trait6` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait6 for X {} @@ -226,11 +226,11 @@ LL | impl Trait7 for X where Y: ?Sized {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait7` +note: required by an implicit `Sized` bound in `Trait7` --> $DIR/unsized-bound.rs:25:17 | LL | trait Trait7 {} - | ^ required by this bound in `Trait7` + | ^ required by the implicit `Sized` requirement on this bound in `Trait7` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait7 for X where Y: ?Sized {} @@ -249,11 +249,11 @@ LL | impl Trait8 for X {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait8` +note: required by an implicit `Sized` bound in `Trait8` --> $DIR/unsized-bound.rs:28:17 | LL | trait Trait8 {} - | ^ required by this bound in `Trait8` + | ^ required by the implicit `Sized` requirement on this bound in `Trait8` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait8 for X {} diff --git a/tests/ui/traits/bad-sized.stderr b/tests/ui/traits/bad-sized.stderr index 857495f4a156d..4c1835dfed085 100644 --- a/tests/ui/traits/bad-sized.stderr +++ b/tests/ui/traits/bad-sized.stderr @@ -16,7 +16,7 @@ LL | let x: Vec = Vec::new(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Trait` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time @@ -36,7 +36,7 @@ LL | let x: Vec = Vec::new(); | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Trait` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error: aborting due to 4 previous errors diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr index 96e8aaee23d56..dc08f9f6ccd4c 100644 --- a/tests/ui/traits/issue-28576.stderr +++ b/tests/ui/traits/issue-28576.stderr @@ -25,11 +25,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | pub trait Bar: Foo { | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Foo` +note: required by an implicit `Sized` bound in `Foo` --> $DIR/issue-28576.rs:1:15 | LL | pub trait Foo { - | ^^^^^^^^ required by this bound in `Foo` + | ^^^^^^^^ required by the implicit `Sized` requirement on this bound in `Foo` help: consider further restricting `Self` | LL | pub trait Bar: Foo + Sized { @@ -45,11 +45,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | pub trait Bar: Foo { | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Foo` +note: required by an implicit `Sized` bound in `Foo` --> $DIR/issue-28576.rs:1:15 | LL | pub trait Foo { - | ^^^^^^^^ required by this bound in `Foo` + | ^^^^^^^^ required by the implicit `Sized` requirement on this bound in `Foo` help: consider further restricting `Self` | LL | ) where Self: Sized; diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.rs b/tests/ui/traits/issue-85360-eval-obligation-ice.rs index ac8bda9c01042..75483a810949d 100644 --- a/tests/ui/traits/issue-85360-eval-obligation-ice.rs +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.rs @@ -8,11 +8,9 @@ use core::marker::PhantomData; fn main() { test::>>(make()); //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) test::>>(make()); //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) - //~| ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) } #[rustc_evaluate_where_clauses] diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.stderr b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr index 9590ea12c05e4..d2b00a45a4f15 100644 --- a/tests/ui/traits/issue-85360-eval-obligation-ice.stderr +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr @@ -1,12 +1,3 @@ -error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) - --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 - | -LL | test::>>(make()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | fn test(_: T) {} - | - predicate - error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 | @@ -17,16 +8,7 @@ LL | fn test(_: T) {} | ----- predicate error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) - --> $DIR/issue-85360-eval-obligation-ice.rs:13:5 - | -LL | test::>>(make()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | fn test(_: T) {} - | - predicate - -error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) - --> $DIR/issue-85360-eval-obligation-ice.rs:13:5 + --> $DIR/issue-85360-eval-obligation-ice.rs:12:5 | LL | test::>>(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,5 +16,5 @@ LL | test::>>(make()); LL | fn test(_: T) {} | ----- predicate -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/traits/mutual-recursion-issue-75860.stderr b/tests/ui/traits/mutual-recursion-issue-75860.stderr index 420ed2dcd2f09..8f83bab003db3 100644 --- a/tests/ui/traits/mutual-recursion-issue-75860.stderr +++ b/tests/ui/traits/mutual-recursion-issue-75860.stderr @@ -5,7 +5,7 @@ LL | iso(left, right) | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mutual_recursion_issue_75860`) -note: required by a bound in `Option` +note: required by an implicit `Sized` bound in `Option` --> $SRC_DIR/core/src/option.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/traits/suggest-where-clause.stderr b/tests/ui/traits/suggest-where-clause.stderr index e3bbf768c6e73..08f3a8dc23dd1 100644 --- a/tests/ui/traits/suggest-where-clause.stderr +++ b/tests/ui/traits/suggest-where-clause.stderr @@ -7,7 +7,7 @@ LL | // suggest a where-clause, if needed LL | mem::size_of::(); | ^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider removing the `?Sized` bound to make the type parameter `Sized` | @@ -29,7 +29,7 @@ note: required because it appears within the type `Misc` | LL | struct Misc(T); | ^^^^ -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider removing the `?Sized` bound to make the type parameter `Sized` | @@ -72,7 +72,7 @@ LL | mem::size_of::<[T]>(); | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[T]` -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error[E0277]: the size for values of type `[&U]` cannot be known at compilation time @@ -82,7 +82,7 @@ LL | mem::size_of::<[&U]>(); | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[&U]` -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error: aborting due to 7 previous errors diff --git a/tests/ui/unsized/unsized-bare-typaram.stderr b/tests/ui/unsized/unsized-bare-typaram.stderr index aa3f8fae72a17..4202e76b6a2ae 100644 --- a/tests/ui/unsized/unsized-bare-typaram.stderr +++ b/tests/ui/unsized/unsized-bare-typaram.stderr @@ -7,10 +7,10 @@ LL | fn foo() { bar::() } | this type parameter needs to be `Sized` | note: required by a bound in `bar` - --> $DIR/unsized-bare-typaram.rs:1:8 + --> $DIR/unsized-bare-typaram.rs:1:11 | LL | fn bar() { } - | ^ required by this bound in `bar` + | ^^^^^ required by this bound in `bar` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn foo() { bar::() } diff --git a/tests/ui/unsized/unsized-enum.stderr b/tests/ui/unsized/unsized-enum.stderr index 8c56a83a5122e..003922a149e31 100644 --- a/tests/ui/unsized/unsized-enum.stderr +++ b/tests/ui/unsized/unsized-enum.stderr @@ -6,11 +6,11 @@ LL | fn foo2() { not_sized::>() } | | | this type parameter needs to be `Sized` | -note: required by a bound in `Foo` +note: required by an implicit `Sized` bound in `Foo` --> $DIR/unsized-enum.rs:4:10 | LL | enum Foo { FooSome(U), FooNone } - | ^ required by this bound in `Foo` + | ^ required by the implicit `Sized` requirement on this bound in `Foo` help: you could relax the implicit `Sized` bound on `U` if it were used through indirection like `&U` or `Box` --> $DIR/unsized-enum.rs:4:10 | diff --git a/tests/ui/unsized/unsized-inherent-impl-self-type.stderr b/tests/ui/unsized/unsized-inherent-impl-self-type.stderr index 3e16a20d726dc..4f5e69135be99 100644 --- a/tests/ui/unsized/unsized-inherent-impl-self-type.stderr +++ b/tests/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -6,11 +6,11 @@ LL | impl S5 { | | | this type parameter needs to be `Sized` | -note: required by a bound in `S5` +note: required by an implicit `Sized` bound in `S5` --> $DIR/unsized-inherent-impl-self-type.rs:5:11 | LL | struct S5(Y); - | ^ required by this bound in `S5` + | ^ required by the implicit `Sized` requirement on this bound in `S5` help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box` --> $DIR/unsized-inherent-impl-self-type.rs:5:11 | diff --git a/tests/ui/unsized/unsized-struct.stderr b/tests/ui/unsized/unsized-struct.stderr index 4e7cb09f0ccaf..92cedecd60592 100644 --- a/tests/ui/unsized/unsized-struct.stderr +++ b/tests/ui/unsized/unsized-struct.stderr @@ -6,11 +6,11 @@ LL | fn foo2() { not_sized::>() } | | | this type parameter needs to be `Sized` | -note: required by a bound in `Foo` +note: required by an implicit `Sized` bound in `Foo` --> $DIR/unsized-struct.rs:4:12 | LL | struct Foo { data: T } - | ^ required by this bound in `Foo` + | ^ required by the implicit `Sized` requirement on this bound in `Foo` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/unsized-struct.rs:4:12 | @@ -38,10 +38,10 @@ note: required because it appears within the type `Bar` LL | struct Bar { data: T } | ^^^ note: required by a bound in `is_sized` - --> $DIR/unsized-struct.rs:1:13 + --> $DIR/unsized-struct.rs:1:15 | LL | fn is_sized() { } - | ^ required by this bound in `is_sized` + | ^^^^^ required by this bound in `is_sized` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn bar2() { is_sized::>() } diff --git a/tests/ui/unsized/unsized-trait-impl-self-type.stderr b/tests/ui/unsized/unsized-trait-impl-self-type.stderr index 5bc8dc590cacb..43a3d9d00c4da 100644 --- a/tests/ui/unsized/unsized-trait-impl-self-type.stderr +++ b/tests/ui/unsized/unsized-trait-impl-self-type.stderr @@ -6,11 +6,11 @@ LL | impl T3 for S5 { | | | this type parameter needs to be `Sized` | -note: required by a bound in `S5` +note: required by an implicit `Sized` bound in `S5` --> $DIR/unsized-trait-impl-self-type.rs:8:11 | LL | struct S5(Y); - | ^ required by this bound in `S5` + | ^ required by the implicit `Sized` requirement on this bound in `S5` help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box` --> $DIR/unsized-trait-impl-self-type.rs:8:11 | diff --git a/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr index e9353d2bbd94a..2ce9dcd221063 100644 --- a/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr +++ b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr @@ -6,11 +6,11 @@ LL | impl T2 for S4 { | | | this type parameter needs to be `Sized` | -note: required by a bound in `T2` +note: required by an implicit `Sized` bound in `T2` --> $DIR/unsized-trait-impl-trait-arg.rs:4:10 | LL | trait T2 { - | ^ required by this bound in `T2` + | ^ required by the implicit `Sized` requirement on this bound in `T2` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl T2 for S4 { diff --git a/tests/ui/unsized/unsized3.stderr b/tests/ui/unsized/unsized3.stderr index a11243980d1a3..6d17b7b9c71ff 100644 --- a/tests/ui/unsized/unsized3.stderr +++ b/tests/ui/unsized/unsized3.stderr @@ -6,11 +6,11 @@ LL | fn f1(x: &X) { LL | f2::(x); | ^ doesn't have a size known at compile-time | -note: required by a bound in `f2` +note: required by an implicit `Sized` bound in `f2` --> $DIR/unsized3.rs:10:7 | LL | fn f2(x: &X) { - | ^ required by this bound in `f2` + | ^ required by the implicit `Sized` requirement on this bound in `f2` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f1(x: &X) { @@ -29,11 +29,11 @@ LL | fn f3(x: &X) { LL | f4::(x); | ^ doesn't have a size known at compile-time | -note: required by a bound in `f4` +note: required by an implicit `Sized` bound in `f4` --> $DIR/unsized3.rs:21:7 | LL | fn f4(x: &X) { - | ^ required by this bound in `f4` + | ^ required by the implicit `Sized` requirement on this bound in `f4` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f3(x: &X) { @@ -59,11 +59,11 @@ note: required because it appears within the type `S` | LL | struct S { | ^ -note: required by a bound in `f5` +note: required by an implicit `Sized` bound in `f5` --> $DIR/unsized3.rs:24:7 | LL | fn f5(x: &Y) {} - | ^ required by this bound in `f5` + | ^ required by the implicit `Sized` requirement on this bound in `f5` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f8(x1: &S, x2: &S) { @@ -131,11 +131,11 @@ note: required because it appears within the type `S` LL | struct S { | ^ = note: required because it appears within the type `({integer}, S)` -note: required by a bound in `f5` +note: required by an implicit `Sized` bound in `f5` --> $DIR/unsized3.rs:24:7 | LL | fn f5(x: &Y) {} - | ^ required by this bound in `f5` + | ^ required by the implicit `Sized` requirement on this bound in `f5` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f10(x1: Box>) { diff --git a/tests/ui/unsized/unsized7.stderr b/tests/ui/unsized/unsized7.stderr index 2edde15965343..3580d8581360d 100644 --- a/tests/ui/unsized/unsized7.stderr +++ b/tests/ui/unsized/unsized7.stderr @@ -6,11 +6,11 @@ LL | impl T1 for S3 { | | | this type parameter needs to be `Sized` | -note: required by a bound in `T1` +note: required by an implicit `Sized` bound in `T1` --> $DIR/unsized7.rs:7:10 | LL | trait T1 { - | ^ required by this bound in `T1` + | ^ required by the implicit `Sized` requirement on this bound in `T1` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl T1 for S3 { diff --git a/tests/ui/wf/hir-wf-canonicalized.stderr b/tests/ui/wf/hir-wf-canonicalized.stderr index 21122e37da53d..2d2ad331fc692 100644 --- a/tests/ui/wf/hir-wf-canonicalized.stderr +++ b/tests/ui/wf/hir-wf-canonicalized.stderr @@ -29,11 +29,11 @@ LL | callback: Box>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` -note: required by a bound in `Bar` +note: required by an implicit `Sized` bound in `Bar` --> $DIR/hir-wf-canonicalized.rs:9:16 | LL | struct Bar<'a, T> { - | ^ required by this bound in `Bar` + | ^ required by the implicit `Sized` requirement on this bound in `Bar` help: consider relaxing the implicit `Sized` restriction | LL | struct Bar<'a, T: ?Sized> { diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr index cd6c051feedf5..d64a6eee1abe2 100644 --- a/tests/ui/wf/wf-fn-where-clause.stderr +++ b/tests/ui/wf/wf-fn-where-clause.stderr @@ -30,11 +30,11 @@ LL | fn bar() where Vec:, {} | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Copy + 'static)` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $DIR/wf-fn-where-clause.rs:16:12 | LL | struct Vec { - | ^ required by this bound in `Vec` + | ^ required by the implicit `Sized` requirement on this bound in `Vec` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/wf-fn-where-clause.rs:16:12 | diff --git a/tests/ui/wf/wf-impl-self-type.stderr b/tests/ui/wf/wf-impl-self-type.stderr index 86fe6df32bf21..6c3abd9f2816e 100644 --- a/tests/ui/wf/wf-impl-self-type.stderr +++ b/tests/ui/wf/wf-impl-self-type.stderr @@ -5,7 +5,7 @@ LL | impl Foo for Option<[u8]> {} | ^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `Option` +note: required by an implicit `Sized` bound in `Option` --> $SRC_DIR/core/src/option.rs:LL:COL error: aborting due to 1 previous error From 95d9009f49100a6cd111557bfc16e6bc997656cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 25 Jan 2024 01:31:08 +0000 Subject: [PATCH 185/246] Change incr comp test when adding explicit `Sized` bound Given the previous change to add implicit `Sized` bounds only if there isn't already an explicit `Sized` bound, now the incr comp machinery doesn't consider adding the explicit bound as being dirty, as long as `-Zincremental-ignore-spans` is set. --- tests/incremental/hashes/trait_defs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/incremental/hashes/trait_defs.rs b/tests/incremental/hashes/trait_defs.rs index 49c388600de05..437b364e001ee 100644 --- a/tests/incremental/hashes/trait_defs.rs +++ b/tests/incremental/hashes/trait_defs.rs @@ -559,10 +559,10 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToMethodTypeParameter { - #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] From 8b0ab54ffefd8855a9030f2c08463f041d0e9770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 30 Jan 2024 19:47:45 +0000 Subject: [PATCH 186/246] review comment: change wording --- .../src/traits/error_reporting/suggestions.rs | 6 +++--- tests/ui/associated-types/issue-20005.stderr | 2 +- tests/ui/dst/dst-sized-trait-param.stderr | 2 +- tests/ui/extern/extern-types-unsized.stderr | 8 ++++---- .../issue-88287.stderr | 2 +- tests/ui/impl-trait/in-trait/wf-bounds.stderr | 2 +- tests/ui/issues/issue-10412.stderr | 2 +- tests/ui/issues/issue-18919.stderr | 2 +- tests/ui/issues/issue-23281.stderr | 2 +- tests/ui/issues/issue-87199.stderr | 2 +- .../do-not-ice-on-note_and_explain.stderr | 2 +- tests/ui/methods/issues/issue-61525.stderr | 2 +- ...ject-safety-supertrait-mentions-Self.stderr | 2 +- tests/ui/str/str-mut-idx.stderr | 2 +- .../adt-param-with-implicit-sized-bound.stderr | 10 +++++----- ...-unsized-indirection-in-where-clause.stderr | 2 +- ...ultiline-trait-bound-in-where-clause.stderr | 6 +++--- tests/ui/trait-bounds/unsized-bound.stderr | 18 +++++++++--------- tests/ui/traits/issue-28576.stderr | 4 ++-- .../recursive-self-normalization-2.stderr | 4 ++-- .../recursive-self-normalization.stderr | 4 ++-- tests/ui/unsized/unsized-enum.stderr | 2 +- .../unsized-inherent-impl-self-type.stderr | 2 +- tests/ui/unsized/unsized-struct.stderr | 2 +- .../unsized-trait-impl-self-type.stderr | 2 +- .../unsized-trait-impl-trait-arg.stderr | 2 +- tests/ui/unsized/unsized3.stderr | 8 ++++---- tests/ui/unsized/unsized7.stderr | 2 +- tests/ui/wf/hir-wf-canonicalized.stderr | 2 +- tests/ui/wf/wf-fn-where-clause.stderr | 2 +- 30 files changed, 55 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 3060f33330e51..a1e1130796b55 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3010,7 +3010,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } let mut a = "a"; - let mut this = "this"; + let mut this = "this bound"; let mut note = None; let mut help = None; if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() @@ -3036,7 +3036,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .any(|param| tcx.def_span(param.def_id) == span) { a = "an implicit `Sized`"; - this = "the implicit `Sized` requirement on this"; + this = "the implicit `Sized` requirement on this type parameter"; } if let Some(hir::Node::TraitItem(hir::TraitItem { ident, @@ -3106,7 +3106,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }; let descr = format!("required by {a} bound in `{item_name}`"); if span.is_visible(sm) { - let msg = format!("required by {this} bound in `{short_item_name}`"); + let msg = format!("required by {this} in `{short_item_name}`"); multispan.push_span_label(span, msg); err.span_note(multispan, descr); } else { diff --git a/tests/ui/associated-types/issue-20005.stderr b/tests/ui/associated-types/issue-20005.stderr index ce3f556f2d744..f2983383fa623 100644 --- a/tests/ui/associated-types/issue-20005.stderr +++ b/tests/ui/associated-types/issue-20005.stderr @@ -8,7 +8,7 @@ note: required by an implicit `Sized` bound in `From` --> $DIR/issue-20005.rs:1:12 | LL | trait From { - | ^^^ required by the implicit `Sized` requirement on this bound in `From` + | ^^^ required by the implicit `Sized` requirement on this type parameter in `From` help: consider further restricting `Self` | LL | ) -> >::Result where Dst: From, Self: Sized { diff --git a/tests/ui/dst/dst-sized-trait-param.stderr b/tests/ui/dst/dst-sized-trait-param.stderr index a3a686dced217..2ac666c8a2cc7 100644 --- a/tests/ui/dst/dst-sized-trait-param.stderr +++ b/tests/ui/dst/dst-sized-trait-param.stderr @@ -9,7 +9,7 @@ note: required by an implicit `Sized` bound in `Foo` --> $DIR/dst-sized-trait-param.rs:5:11 | LL | trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is sized - | ^ required by the implicit `Sized` requirement on this bound in `Foo` + | ^ required by the implicit `Sized` requirement on this type parameter in `Foo` help: consider relaxing the implicit `Sized` restriction | LL | trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is sized diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr index 6592724a53e70..7428e6a60b520 100644 --- a/tests/ui/extern/extern-types-unsized.stderr +++ b/tests/ui/extern/extern-types-unsized.stderr @@ -9,7 +9,7 @@ note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by the implicit `Sized` requirement on this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} @@ -31,7 +31,7 @@ note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by the implicit `Sized` requirement on this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} @@ -53,7 +53,7 @@ note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by the implicit `Sized` requirement on this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} @@ -75,7 +75,7 @@ note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by the implicit `Sized` requirement on this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} diff --git a/tests/ui/generic-associated-types/issue-88287.stderr b/tests/ui/generic-associated-types/issue-88287.stderr index 6b26223dd5144..54ecc5cfcd810 100644 --- a/tests/ui/generic-associated-types/issue-88287.stderr +++ b/tests/ui/generic-associated-types/issue-88287.stderr @@ -11,7 +11,7 @@ note: required by an implicit `Sized` bound in ` $DIR/issue-88287.rs:24:6 | LL | impl SearchableResourceExt for T - | ^ required by the implicit `Sized` requirement on this bound in `>` + | ^ required by the implicit `Sized` requirement on this type parameter in `>` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - A: SearchableResource + ?Sized + 'f, diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.stderr index e2e06ba4e5ae8..7d42659d81edb 100644 --- a/tests/ui/impl-trait/in-trait/wf-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/wf-bounds.stderr @@ -19,7 +19,7 @@ note: required by an implicit `Sized` bound in `Wf` --> $DIR/wf-bounds.rs:7:10 | LL | trait Wf { - | ^ required by the implicit `Sized` requirement on this bound in `Wf` + | ^ required by the implicit `Sized` requirement on this type parameter in `Wf` help: consider relaxing the implicit `Sized` restriction | LL | trait Wf { diff --git a/tests/ui/issues/issue-10412.stderr b/tests/ui/issues/issue-10412.stderr index dcf7769264b22..02a26034f9aa7 100644 --- a/tests/ui/issues/issue-10412.stderr +++ b/tests/ui/issues/issue-10412.stderr @@ -62,7 +62,7 @@ note: required by an implicit `Sized` bound in `Serializable` --> $DIR/issue-10412.rs:1:27 | LL | trait Serializable<'self, T> { - | ^ required by the implicit `Sized` requirement on this bound in `Serializable` + | ^ required by the implicit `Sized` requirement on this type parameter in `Serializable` help: consider relaxing the implicit `Sized` restriction | LL | trait Serializable<'self, T: ?Sized> { diff --git a/tests/ui/issues/issue-18919.stderr b/tests/ui/issues/issue-18919.stderr index 471b5d5bdf12a..714b6d7d86be3 100644 --- a/tests/ui/issues/issue-18919.stderr +++ b/tests/ui/issues/issue-18919.stderr @@ -9,7 +9,7 @@ note: required by an implicit `Sized` bound in `Option` --> $DIR/issue-18919.rs:7:13 | LL | enum Option { - | ^ required by the implicit `Sized` requirement on this bound in `Option` + | ^ required by the implicit `Sized` requirement on this type parameter in `Option` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/issue-18919.rs:7:13 | diff --git a/tests/ui/issues/issue-23281.stderr b/tests/ui/issues/issue-23281.stderr index 4c25d1efedd6a..ee079f2deeca3 100644 --- a/tests/ui/issues/issue-23281.stderr +++ b/tests/ui/issues/issue-23281.stderr @@ -9,7 +9,7 @@ note: required by an implicit `Sized` bound in `Vec` --> $DIR/issue-23281.rs:8:12 | LL | struct Vec { - | ^ required by the implicit `Sized` requirement on this bound in `Vec` + | ^ required by the implicit `Sized` requirement on this type parameter in `Vec` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/issue-23281.rs:8:12 | diff --git a/tests/ui/issues/issue-87199.stderr b/tests/ui/issues/issue-87199.stderr index 6c4fbddb04924..34433eef5c70b 100644 --- a/tests/ui/issues/issue-87199.stderr +++ b/tests/ui/issues/issue-87199.stderr @@ -27,7 +27,7 @@ note: required by an implicit `Sized` bound in `ref_arg` --> $DIR/issue-87199.rs:10:12 | LL | fn ref_arg(_: &T) {} - | ^ required by the implicit `Sized` requirement on this bound in `ref_arg` + | ^ required by the implicit `Sized` requirement on this type parameter in `ref_arg` help: consider relaxing the implicit `Sized` restriction | LL | fn ref_arg(_: &T) {} diff --git a/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr index 47c01b9e805d8..41d0f17366b1e 100644 --- a/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr +++ b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr @@ -64,7 +64,7 @@ note: required by an implicit `Sized` bound in `A` --> $DIR/do-not-ice-on-note_and_explain.rs:1:10 | LL | struct A(B); - | ^ required by the implicit `Sized` requirement on this bound in `A` + | ^ required by the implicit `Sized` requirement on this type parameter in `A` help: you could relax the implicit `Sized` bound on `B` if it were used through indirection like `&B` or `Box` --> $DIR/do-not-ice-on-note_and_explain.rs:1:10 | diff --git a/tests/ui/methods/issues/issue-61525.stderr b/tests/ui/methods/issues/issue-61525.stderr index 777d0b4f3d125..35001ae22a6c7 100644 --- a/tests/ui/methods/issues/issue-61525.stderr +++ b/tests/ui/methods/issues/issue-61525.stderr @@ -11,7 +11,7 @@ note: required by an implicit `Sized` bound in `Example::query` --> $DIR/issue-61525.rs:2:14 | LL | fn query(self, q: Q); - | ^ required by the implicit `Sized` requirement on this bound in `Example::query` + | ^ required by the implicit `Sized` requirement on this type parameter in `Example::query` help: consider relaxing the implicit `Sized` restriction | LL | fn query(self, q: Q); diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr index 2380cba89486f..e7fcdbd0c9c53 100644 --- a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr +++ b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr @@ -26,7 +26,7 @@ note: required by an implicit `Sized` bound in `Bar` --> $DIR/object-safety-supertrait-mentions-Self.rs:4:11 | LL | trait Bar { - | ^ required by the implicit `Sized` requirement on this bound in `Bar` + | ^ required by the implicit `Sized` requirement on this type parameter in `Bar` help: consider further restricting `Self` | LL | trait Baz : Bar + Sized { diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr index 5a2664f4522e8..679f783126ff4 100644 --- a/tests/ui/str/str-mut-idx.stderr +++ b/tests/ui/str/str-mut-idx.stderr @@ -9,7 +9,7 @@ note: required by an implicit `Sized` bound in `bot` --> $DIR/str-mut-idx.rs:1:8 | LL | fn bot() -> T { loop {} } - | ^ required by the implicit `Sized` requirement on this bound in `bot` + | ^ required by the implicit `Sized` requirement on this type parameter in `bot` help: consider relaxing the implicit `Sized` restriction | LL | fn bot() -> T { loop {} } diff --git a/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr index 705f078c367d0..6da6f8e23b4f4 100644 --- a/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr +++ b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr @@ -10,7 +10,7 @@ note: required by an implicit `Sized` bound in `X` --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 | LL | struct X(T); - | ^ required by the implicit `Sized` requirement on this bound in `X` + | ^ required by the implicit `Sized` requirement on this type parameter in `X` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 | @@ -34,7 +34,7 @@ note: required by an implicit `Sized` bound in `Struct1` --> $DIR/adt-param-with-implicit-sized-bound.rs:8:16 | LL | struct Struct1{ - | ^ required by the implicit `Sized` requirement on this bound in `Struct1` + | ^ required by the implicit `Sized` requirement on this type parameter in `Struct1` help: consider further restricting `Self` | LL | fn func1() -> Struct1 where Self: Sized; @@ -54,7 +54,7 @@ note: required by an implicit `Sized` bound in `Struct2` --> $DIR/adt-param-with-implicit-sized-bound.rs:11:20 | LL | struct Struct2<'a, T>{ - | ^ required by the implicit `Sized` requirement on this bound in `Struct2` + | ^ required by the implicit `Sized` requirement on this type parameter in `Struct2` help: consider further restricting `Self` | LL | fn func2<'a>() -> Struct2<'a, Self> where Self: Sized; @@ -74,7 +74,7 @@ note: required by an implicit `Sized` bound in `Struct3` --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16 | LL | struct Struct3{ - | ^ required by the implicit `Sized` requirement on this bound in `Struct3` + | ^ required by the implicit `Sized` requirement on this type parameter in `Struct3` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16 | @@ -97,7 +97,7 @@ note: required by an implicit `Sized` bound in `Struct4` --> $DIR/adt-param-with-implicit-sized-bound.rs:20:16 | LL | struct Struct4{ - | ^ required by the implicit `Sized` requirement on this bound in `Struct4` + | ^ required by the implicit `Sized` requirement on this type parameter in `Struct4` help: consider further restricting `Self` | LL | fn func4() -> Struct4 where Self: Sized; diff --git a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr index e2f1532cc4eaf..7dcb2deb06a04 100644 --- a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr +++ b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr @@ -9,7 +9,7 @@ note: required by an implicit `Sized` bound in `A` --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10 | LL | struct A(T) where T: Send; - | ^ required by the implicit `Sized` requirement on this bound in `A` + | ^ required by the implicit `Sized` requirement on this type parameter in `A` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10 | diff --git a/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr index 7d20120654af3..dcab4d7c4fcb3 100644 --- a/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr +++ b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr @@ -10,7 +10,7 @@ note: required by an implicit `Sized` bound in `Wrapper` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | LL | struct Wrapper(T); - | ^ required by the implicit `Sized` requirement on this bound in `Wrapper` + | ^ required by the implicit `Sized` requirement on this type parameter in `Wrapper` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | @@ -39,7 +39,7 @@ note: required by an implicit `Sized` bound in `Wrapper` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | LL | struct Wrapper(T); - | ^ required by the implicit `Sized` requirement on this bound in `Wrapper` + | ^ required by the implicit `Sized` requirement on this type parameter in `Wrapper` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | @@ -64,7 +64,7 @@ note: required by an implicit `Sized` bound in `Wrapper` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | LL | struct Wrapper(T); - | ^ required by the implicit `Sized` requirement on this bound in `Wrapper` + | ^ required by the implicit `Sized` requirement on this type parameter in `Wrapper` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | diff --git a/tests/ui/trait-bounds/unsized-bound.stderr b/tests/ui/trait-bounds/unsized-bound.stderr index 87a43a6fddab0..c8049ebee1173 100644 --- a/tests/ui/trait-bounds/unsized-bound.stderr +++ b/tests/ui/trait-bounds/unsized-bound.stderr @@ -11,7 +11,7 @@ note: required by an implicit `Sized` bound in `Trait` --> $DIR/unsized-bound.rs:1:13 | LL | trait Trait {} - | ^ required by the implicit `Sized` requirement on this bound in `Trait` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} @@ -50,7 +50,7 @@ note: required by an implicit `Sized` bound in `Trait` --> $DIR/unsized-bound.rs:1:13 | LL | trait Trait {} - | ^ required by the implicit `Sized` requirement on this bound in `Trait` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} @@ -100,7 +100,7 @@ note: required by an implicit `Sized` bound in `Trait2` --> $DIR/unsized-bound.rs:9:14 | LL | trait Trait2 {} - | ^ required by the implicit `Sized` requirement on this bound in `Trait2` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait2` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait2<(A, B)> for (A, B) {} @@ -138,7 +138,7 @@ note: required by an implicit `Sized` bound in `Trait3` --> $DIR/unsized-bound.rs:13:14 | LL | trait Trait3 {} - | ^ required by the implicit `Sized` requirement on this bound in `Trait3` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait3` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait3 for A where A: ?Sized {} @@ -161,7 +161,7 @@ note: required by an implicit `Sized` bound in `Trait4` --> $DIR/unsized-bound.rs:16:14 | LL | trait Trait4 {} - | ^ required by the implicit `Sized` requirement on this bound in `Trait4` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait4` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait4 for A {} @@ -184,7 +184,7 @@ note: required by an implicit `Sized` bound in `Trait5` --> $DIR/unsized-bound.rs:19:14 | LL | trait Trait5 {} - | ^ required by the implicit `Sized` requirement on this bound in `Trait5` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait5` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait5 for X where X: ?Sized {} @@ -207,7 +207,7 @@ note: required by an implicit `Sized` bound in `Trait6` --> $DIR/unsized-bound.rs:22:14 | LL | trait Trait6 {} - | ^ required by the implicit `Sized` requirement on this bound in `Trait6` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait6` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait6 for X {} @@ -230,7 +230,7 @@ note: required by an implicit `Sized` bound in `Trait7` --> $DIR/unsized-bound.rs:25:17 | LL | trait Trait7 {} - | ^ required by the implicit `Sized` requirement on this bound in `Trait7` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait7` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait7 for X where Y: ?Sized {} @@ -253,7 +253,7 @@ note: required by an implicit `Sized` bound in `Trait8` --> $DIR/unsized-bound.rs:28:17 | LL | trait Trait8 {} - | ^ required by the implicit `Sized` requirement on this bound in `Trait8` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait8` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait8 for X {} diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr index dc08f9f6ccd4c..adba5830b10e1 100644 --- a/tests/ui/traits/issue-28576.stderr +++ b/tests/ui/traits/issue-28576.stderr @@ -29,7 +29,7 @@ note: required by an implicit `Sized` bound in `Foo` --> $DIR/issue-28576.rs:1:15 | LL | pub trait Foo { - | ^^^^^^^^ required by the implicit `Sized` requirement on this bound in `Foo` + | ^^^^^^^^ required by the implicit `Sized` requirement on this type parameter in `Foo` help: consider further restricting `Self` | LL | pub trait Bar: Foo + Sized { @@ -49,7 +49,7 @@ note: required by an implicit `Sized` bound in `Foo` --> $DIR/issue-28576.rs:1:15 | LL | pub trait Foo { - | ^^^^^^^^ required by the implicit `Sized` requirement on this bound in `Foo` + | ^^^^^^^^ required by the implicit `Sized` requirement on this type parameter in `Foo` help: consider further restricting `Self` | LL | ) where Self: Sized; diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr index ed87404d57395..09622bb9b6c28 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr @@ -26,11 +26,11 @@ LL | needs_bar::(); | ^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`) -note: required by a bound in `needs_bar` +note: required by an implicit `Sized` bound in `needs_bar` --> $DIR/recursive-self-normalization-2.rs:12:14 | LL | fn needs_bar() {} - | ^ required by this bound in `needs_bar` + | ^ required by the implicit `Sized` requirement on this type parameter in `needs_bar` help: consider relaxing the implicit `Sized` restriction | LL | fn needs_bar() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr index e4ef2f60740f4..7c058909df7c5 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr @@ -26,11 +26,11 @@ LL | needs_bar::(); | ^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`) -note: required by a bound in `needs_bar` +note: required by an implicit `Sized` bound in `needs_bar` --> $DIR/recursive-self-normalization.rs:8:14 | LL | fn needs_bar() {} - | ^ required by this bound in `needs_bar` + | ^ required by the implicit `Sized` requirement on this type parameter in `needs_bar` help: consider relaxing the implicit `Sized` restriction | LL | fn needs_bar() {} diff --git a/tests/ui/unsized/unsized-enum.stderr b/tests/ui/unsized/unsized-enum.stderr index 003922a149e31..5a30d7fab65a7 100644 --- a/tests/ui/unsized/unsized-enum.stderr +++ b/tests/ui/unsized/unsized-enum.stderr @@ -10,7 +10,7 @@ note: required by an implicit `Sized` bound in `Foo` --> $DIR/unsized-enum.rs:4:10 | LL | enum Foo { FooSome(U), FooNone } - | ^ required by the implicit `Sized` requirement on this bound in `Foo` + | ^ required by the implicit `Sized` requirement on this type parameter in `Foo` help: you could relax the implicit `Sized` bound on `U` if it were used through indirection like `&U` or `Box` --> $DIR/unsized-enum.rs:4:10 | diff --git a/tests/ui/unsized/unsized-inherent-impl-self-type.stderr b/tests/ui/unsized/unsized-inherent-impl-self-type.stderr index 4f5e69135be99..5a379f4065aa7 100644 --- a/tests/ui/unsized/unsized-inherent-impl-self-type.stderr +++ b/tests/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -10,7 +10,7 @@ note: required by an implicit `Sized` bound in `S5` --> $DIR/unsized-inherent-impl-self-type.rs:5:11 | LL | struct S5(Y); - | ^ required by the implicit `Sized` requirement on this bound in `S5` + | ^ required by the implicit `Sized` requirement on this type parameter in `S5` help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box` --> $DIR/unsized-inherent-impl-self-type.rs:5:11 | diff --git a/tests/ui/unsized/unsized-struct.stderr b/tests/ui/unsized/unsized-struct.stderr index 92cedecd60592..06c4ffb7773c6 100644 --- a/tests/ui/unsized/unsized-struct.stderr +++ b/tests/ui/unsized/unsized-struct.stderr @@ -10,7 +10,7 @@ note: required by an implicit `Sized` bound in `Foo` --> $DIR/unsized-struct.rs:4:12 | LL | struct Foo { data: T } - | ^ required by the implicit `Sized` requirement on this bound in `Foo` + | ^ required by the implicit `Sized` requirement on this type parameter in `Foo` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/unsized-struct.rs:4:12 | diff --git a/tests/ui/unsized/unsized-trait-impl-self-type.stderr b/tests/ui/unsized/unsized-trait-impl-self-type.stderr index 43a3d9d00c4da..3b684193b4aca 100644 --- a/tests/ui/unsized/unsized-trait-impl-self-type.stderr +++ b/tests/ui/unsized/unsized-trait-impl-self-type.stderr @@ -10,7 +10,7 @@ note: required by an implicit `Sized` bound in `S5` --> $DIR/unsized-trait-impl-self-type.rs:8:11 | LL | struct S5(Y); - | ^ required by the implicit `Sized` requirement on this bound in `S5` + | ^ required by the implicit `Sized` requirement on this type parameter in `S5` help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box` --> $DIR/unsized-trait-impl-self-type.rs:8:11 | diff --git a/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr index 2ce9dcd221063..79fc9567dae6f 100644 --- a/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr +++ b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr @@ -10,7 +10,7 @@ note: required by an implicit `Sized` bound in `T2` --> $DIR/unsized-trait-impl-trait-arg.rs:4:10 | LL | trait T2 { - | ^ required by the implicit `Sized` requirement on this bound in `T2` + | ^ required by the implicit `Sized` requirement on this type parameter in `T2` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl T2 for S4 { diff --git a/tests/ui/unsized/unsized3.stderr b/tests/ui/unsized/unsized3.stderr index 6d17b7b9c71ff..c7a145b1c5171 100644 --- a/tests/ui/unsized/unsized3.stderr +++ b/tests/ui/unsized/unsized3.stderr @@ -10,7 +10,7 @@ note: required by an implicit `Sized` bound in `f2` --> $DIR/unsized3.rs:10:7 | LL | fn f2(x: &X) { - | ^ required by the implicit `Sized` requirement on this bound in `f2` + | ^ required by the implicit `Sized` requirement on this type parameter in `f2` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f1(x: &X) { @@ -33,7 +33,7 @@ note: required by an implicit `Sized` bound in `f4` --> $DIR/unsized3.rs:21:7 | LL | fn f4(x: &X) { - | ^ required by the implicit `Sized` requirement on this bound in `f4` + | ^ required by the implicit `Sized` requirement on this type parameter in `f4` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f3(x: &X) { @@ -63,7 +63,7 @@ note: required by an implicit `Sized` bound in `f5` --> $DIR/unsized3.rs:24:7 | LL | fn f5(x: &Y) {} - | ^ required by the implicit `Sized` requirement on this bound in `f5` + | ^ required by the implicit `Sized` requirement on this type parameter in `f5` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f8(x1: &S, x2: &S) { @@ -135,7 +135,7 @@ note: required by an implicit `Sized` bound in `f5` --> $DIR/unsized3.rs:24:7 | LL | fn f5(x: &Y) {} - | ^ required by the implicit `Sized` requirement on this bound in `f5` + | ^ required by the implicit `Sized` requirement on this type parameter in `f5` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f10(x1: Box>) { diff --git a/tests/ui/unsized/unsized7.stderr b/tests/ui/unsized/unsized7.stderr index 3580d8581360d..6e9c052a07022 100644 --- a/tests/ui/unsized/unsized7.stderr +++ b/tests/ui/unsized/unsized7.stderr @@ -10,7 +10,7 @@ note: required by an implicit `Sized` bound in `T1` --> $DIR/unsized7.rs:7:10 | LL | trait T1 { - | ^ required by the implicit `Sized` requirement on this bound in `T1` + | ^ required by the implicit `Sized` requirement on this type parameter in `T1` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl T1 for S3 { diff --git a/tests/ui/wf/hir-wf-canonicalized.stderr b/tests/ui/wf/hir-wf-canonicalized.stderr index 2d2ad331fc692..4dca1f65232e2 100644 --- a/tests/ui/wf/hir-wf-canonicalized.stderr +++ b/tests/ui/wf/hir-wf-canonicalized.stderr @@ -33,7 +33,7 @@ note: required by an implicit `Sized` bound in `Bar` --> $DIR/hir-wf-canonicalized.rs:9:16 | LL | struct Bar<'a, T> { - | ^ required by the implicit `Sized` requirement on this bound in `Bar` + | ^ required by the implicit `Sized` requirement on this type parameter in `Bar` help: consider relaxing the implicit `Sized` restriction | LL | struct Bar<'a, T: ?Sized> { diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr index d64a6eee1abe2..40f2f45263930 100644 --- a/tests/ui/wf/wf-fn-where-clause.stderr +++ b/tests/ui/wf/wf-fn-where-clause.stderr @@ -34,7 +34,7 @@ note: required by an implicit `Sized` bound in `Vec` --> $DIR/wf-fn-where-clause.rs:16:12 | LL | struct Vec { - | ^ required by the implicit `Sized` requirement on this bound in `Vec` + | ^ required by the implicit `Sized` requirement on this type parameter in `Vec` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/wf-fn-where-clause.rs:16:12 | From 3434466a7f3d82103beb32e1b53ec26231cbe6c7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 15 Jan 2024 16:20:37 +1100 Subject: [PATCH 187/246] Tweak `emit_stashed_diagnostics`. `take` + `into_iter` + pattern matching is nicer than `drain` + `map` + `collect`. --- compiler/rustc_errors/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 960b68196ff02..901fe3fb79930 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1224,9 +1224,8 @@ impl DiagCtxtInner { /// Emit all stashed diagnostics. fn emit_stashed_diagnostics(&mut self) -> Option { let has_errors = self.has_errors(); - let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::>(); let mut reported = None; - for diag in diags { + for (_, diag) in std::mem::take(&mut self.stashed_diagnostics).into_iter() { // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { if diag.is_lint.is_some() { From 3db37fb78a9a6b76373faf85c2976a2916599f85 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jan 2024 14:09:24 +1100 Subject: [PATCH 188/246] A small fix in `enforce_slug_naming.rs`. In #119972 the code should have become `E0123` rather than `0123`. This fix doesn't affect the outcome because the proc macro errors out before the type of the code is checked, but the fix makes the test's code consistent with other similar code elsewhere. --- tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs | 2 +- tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs index 785da11b9b2e3..3056ebb7575fd 100644 --- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs +++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs @@ -19,6 +19,6 @@ use rustc_errors::{Applicability, MultiSpan}; extern crate rustc_session; #[derive(Diagnostic)] -#[diag(compiletest_example, code = 0123)] +#[diag(compiletest_example, code = E0123)] //~^ ERROR diagnostic slug and crate name do not match struct Hello {} diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr index eda24a555f848..df1bad3cad0cf 100644 --- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr +++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr @@ -1,7 +1,7 @@ error: diagnostic slug and crate name do not match --> $DIR/enforce_slug_naming.rs:22:8 | -LL | #[diag(compiletest_example, code = 0123)] +LL | #[diag(compiletest_example, code = E0123)] | ^^^^^^^^^^^^^^^^^^^ | = note: slug is `compiletest_example` but the crate name is `rustc_dummy` From 26eb6da4e7f19fd1408eac2c67891f3dbfc47e5a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jan 2024 14:46:51 +1100 Subject: [PATCH 189/246] Fit more values into `DiagnosticArgValue::Number`. It contains an `i128`, but when creating them we convert any number outside the range -100..100 to a string, because Fluent uses an `f64`. It's all a bit strange. This commit changes the `i128` to an `i32`, which fits safely in Fluent's `f64`, and removes the -100..100 range check. This means that only integers outside the range of `i32` will be converted to strings. --- compiler/rustc_errors/src/diagnostic.rs | 5 ++++- compiler/rustc_errors/src/diagnostic_impls.rs | 8 ++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index b87eef07fd53a..249155ba7c641 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -33,7 +33,10 @@ pub type DiagnosticArgName = Cow<'static, str>; #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub enum DiagnosticArgValue { Str(Cow<'static, str>), - Number(i128), + // This gets converted to a `FluentNumber`, which is an `f64`. An `i32` + // safely fits in an `f64`. Any integers bigger than that will be converted + // to strings in `into_diagnostic_arg` and stored using the `Str` variant. + Number(i32), StrListSepByAnd(Vec>), } diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index faab3fc663a82..15effd3cbec9b 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -63,12 +63,8 @@ macro_rules! into_diagnostic_arg_for_number { $( impl IntoDiagnosticArg for $ty { fn into_diagnostic_arg(self) -> DiagnosticArgValue { - // HACK: `FluentNumber` the underline backing struct represent - // numbers using a f64 which can't represent all the i128 numbers - // So in order to be able to use fluent selectors and still - // have all the numbers representable we only convert numbers - // below a certain threshold. - if let Ok(n) = TryInto::::try_into(self) && n >= -100 && n <= 100 { + // Convert to a string if it won't fit into `Number`. + if let Ok(n) = TryInto::::try_into(self) { DiagnosticArgValue::Number(n) } else { self.to_string().into_diagnostic_arg() From 2621f7fd9ba97bbbd1b5b1df96184353948e2249 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jan 2024 17:10:48 +1100 Subject: [PATCH 190/246] Rework `StringPart`. When there are two possibilities, both of which use a `String`, it's nicer to use a struct than an enum. Especially when mapping the contents into a tuple. --- compiler/rustc_errors/src/diagnostic.rs | 36 +++++++++++-------------- compiler/rustc_errors/src/snippet.rs | 2 +- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 249155ba7c641..6deaaef780d41 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -165,10 +165,10 @@ impl DiagnosticStyledString { DiagnosticStyledString(vec![]) } pub fn push_normal>(&mut self, t: S) { - self.0.push(StringPart::Normal(t.into())); + self.0.push(StringPart::normal(t.into())); } pub fn push_highlighted>(&mut self, t: S) { - self.0.push(StringPart::Highlighted(t.into())); + self.0.push(StringPart::highlighted(t.into())); } pub fn push>(&mut self, t: S, highlight: bool) { if highlight { @@ -178,29 +178,31 @@ impl DiagnosticStyledString { } } pub fn normal>(t: S) -> DiagnosticStyledString { - DiagnosticStyledString(vec![StringPart::Normal(t.into())]) + DiagnosticStyledString(vec![StringPart::normal(t.into())]) } pub fn highlighted>(t: S) -> DiagnosticStyledString { - DiagnosticStyledString(vec![StringPart::Highlighted(t.into())]) + DiagnosticStyledString(vec![StringPart::highlighted(t.into())]) } pub fn content(&self) -> String { - self.0.iter().map(|x| x.content()).collect::() + self.0.iter().map(|x| x.content.as_str()).collect::() } } #[derive(Debug, PartialEq, Eq)] -pub enum StringPart { - Normal(String), - Highlighted(String), +pub struct StringPart { + content: String, + style: Style, } impl StringPart { - pub fn content(&self) -> &str { - match self { - &StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s, - } + fn normal(content: String) -> StringPart { + StringPart { content, style: Style::NoStyle } + } + + fn highlighted(content: String) -> StringPart { + StringPart { content, style: Style::Highlight } } } @@ -394,16 +396,10 @@ impl Diagnostic { }; let mut msg: Vec<_> = vec![(format!("{}{} `", " ".repeat(expected_padding), expected_label), Style::NoStyle)]; - msg.extend(expected.0.iter().map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); + msg.extend(expected.0.into_iter().map(|p| (p.content, p.style))); msg.push((format!("`{expected_extra}\n"), Style::NoStyle)); msg.push((format!("{}{} `", " ".repeat(found_padding), found_label), Style::NoStyle)); - msg.extend(found.0.iter().map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); + msg.extend(found.0.into_iter().map(|p| (p.content, p.style))); msg.push((format!("`{found_extra}"), Style::NoStyle)); // For now, just attach these as notes. diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs index 98eb70b5fceee..b55f78538852a 100644 --- a/compiler/rustc_errors/src/snippet.rs +++ b/compiler/rustc_errors/src/snippet.rs @@ -197,7 +197,7 @@ pub struct StyledString { pub style: Style, } -#[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub enum Style { MainHeaderMsg, HeaderMsg, From 671c776d594e26f740ece619f26bcae7f911c111 Mon Sep 17 00:00:00 2001 From: Thomas Frans Date: Thu, 1 Feb 2024 11:06:34 +0100 Subject: [PATCH 191/246] minor: Recommend maintained Neovim plugin in documentation --- docs/user/manual.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index 069a62ddbfe96..9e9ea25779047 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc @@ -369,7 +369,7 @@ EOF See https://sharksforarms.dev/posts/neovim-rust/ for more tips on getting started. -Check out https://github.com/simrat39/rust-tools.nvim for a batteries included rust-analyzer setup for Neovim. +Check out https://github.com/mrcjkb/rustaceanvim for a batteries included rust-analyzer setup for Neovim. ==== vim-lsp From 4feec41e0589e53a429de261c534909703185279 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 1 Feb 2024 10:27:54 +0000 Subject: [PATCH 192/246] `#![feature(inline_const_pat)]` is no longer incomplete --- compiler/rustc_feature/src/unstable.rs | 2 +- .../invalid-inline-const-in-match-arm.rs | 1 - .../invalid-inline-const-in-match-arm.stderr | 2 +- .../range_pat_interactions0.rs | 1 - .../inline-const/const-match-pat-generic.rs | 1 - .../const-match-pat-generic.stderr | 4 ++-- .../inline-const/const-match-pat-inference.rs | 1 - .../const-match-pat-lifetime-err.rs | 1 - .../const-match-pat-lifetime-err.stderr | 4 ++-- .../inline-const/const-match-pat-lifetime.rs | 1 - .../ui/inline-const/const-match-pat-range.rs | 1 - tests/ui/inline-const/const-match-pat.rs | 1 - tests/ui/inline-const/pat-match-fndef.rs | 1 - tests/ui/inline-const/pat-match-fndef.stderr | 13 ++--------- tests/ui/inline-const/pat-unsafe-err.rs | 1 - tests/ui/inline-const/pat-unsafe-err.stderr | 4 ++-- tests/ui/inline-const/pat-unsafe.rs | 1 - tests/ui/inline-const/pat-unsafe.stderr | 6 ++--- tests/ui/lint/dead-code/anon-const-in-pat.rs | 1 - tests/ui/match/issue-112438.rs | 1 - tests/ui/match/validate-range-endpoints.rs | 1 - .../ui/match/validate-range-endpoints.stderr | 22 +++++++++---------- .../ui/pattern/non-structural-match-types.rs | 1 - .../pattern/non-structural-match-types.stderr | 8 +++---- .../unsafe/const_pat_in_layout_restricted.rs | 1 - 25 files changed, 28 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 643185ba20a7c..d00621d8254c3 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -496,7 +496,7 @@ declare_features! ( /// Allow anonymous constants from an inline `const` block (unstable, inline_const, "1.49.0", Some(76001)), /// Allow anonymous constants from an inline `const` block in pattern position - (incomplete, inline_const_pat, "1.58.0", Some(76001)), + (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 setting the threshold for the `large_assignments` lint. diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.rs b/tests/ui/consts/invalid-inline-const-in-match-arm.rs index 4d2d8fb1303ce..0654fd82fbc59 100644 --- a/tests/ui/consts/invalid-inline-const-in-match-arm.rs +++ b/tests/ui/consts/invalid-inline-const-in-match-arm.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(inline_const_pat)] fn main() { diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr index db7db4b613181..a88c16158f324 100644 --- a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr +++ b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const closure in constants - --> $DIR/invalid-inline-const-in-match-arm.rs:6:17 + --> $DIR/invalid-inline-const-in-match-arm.rs:5:17 | LL | const { (|| {})() } => {} | ^^^^^^^^^ 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 acb7feac132f4..e6d5e64a15b7a 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs @@ -1,5 +1,4 @@ // run-pass -#![allow(incomplete_features)] #![feature(exclusive_range_pattern)] #![feature(inline_const_pat)] diff --git a/tests/ui/inline-const/const-match-pat-generic.rs b/tests/ui/inline-const/const-match-pat-generic.rs index 46e501abf6c2e..9d76fc2ad65bc 100644 --- a/tests/ui/inline-const/const-match-pat-generic.rs +++ b/tests/ui/inline-const/const-match-pat-generic.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(inline_const_pat)] // rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr index 4ffbde4101d72..15c3a876afcf7 100644 --- a/tests/ui/inline-const/const-match-pat-generic.stderr +++ b/tests/ui/inline-const/const-match-pat-generic.stderr @@ -1,11 +1,11 @@ error: constant pattern depends on a generic parameter - --> $DIR/const-match-pat-generic.rs:8:9 + --> $DIR/const-match-pat-generic.rs:7:9 | LL | const { V } => {}, | ^^^^^^^^^^^ error: constant pattern depends on a generic parameter - --> $DIR/const-match-pat-generic.rs:20:9 + --> $DIR/const-match-pat-generic.rs:19:9 | LL | const { f(V) } => {}, | ^^^^^^^^^^^^^^ diff --git a/tests/ui/inline-const/const-match-pat-inference.rs b/tests/ui/inline-const/const-match-pat-inference.rs index d83ae6e983486..c595824833f5f 100644 --- a/tests/ui/inline-const/const-match-pat-inference.rs +++ b/tests/ui/inline-const/const-match-pat-inference.rs @@ -1,7 +1,6 @@ // check-pass #![feature(inline_const_pat)] -#![allow(incomplete_features)] fn main() { match 1u64 { diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.rs b/tests/ui/inline-const/const-match-pat-lifetime-err.rs index ce91e5233bccd..ff0a9dbf110c4 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime-err.rs +++ b/tests/ui/inline-const/const-match-pat-lifetime-err.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(const_mut_refs)] #![feature(inline_const_pat)] diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr index c5760f1027ef2..98ce6cfae7b38 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr +++ b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr @@ -1,5 +1,5 @@ error[E0597]: `y` does not live long enough - --> $DIR/const-match-pat-lifetime-err.rs:29:29 + --> $DIR/const-match-pat-lifetime-err.rs:28:29 | LL | fn match_invariant_ref<'a>() { | -- lifetime `'a` defined here @@ -15,7 +15,7 @@ LL | } | - `y` dropped here while still borrowed error: lifetime may not live long enough - --> $DIR/const-match-pat-lifetime-err.rs:39:12 + --> $DIR/const-match-pat-lifetime-err.rs:38:12 | LL | fn match_covariant_ref<'a>() { | -- lifetime `'a` defined here diff --git a/tests/ui/inline-const/const-match-pat-lifetime.rs b/tests/ui/inline-const/const-match-pat-lifetime.rs index 6d943bbcc0160..595741b101e93 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime.rs +++ b/tests/ui/inline-const/const-match-pat-lifetime.rs @@ -1,6 +1,5 @@ // run-pass -#![allow(incomplete_features)] #![feature(const_mut_refs)] #![feature(inline_const)] #![feature(inline_const_pat)] diff --git a/tests/ui/inline-const/const-match-pat-range.rs b/tests/ui/inline-const/const-match-pat-range.rs index 73d6334c36f8e..0f9372c537f89 100644 --- a/tests/ui/inline-const/const-match-pat-range.rs +++ b/tests/ui/inline-const/const-match-pat-range.rs @@ -1,6 +1,5 @@ // build-pass -#![allow(incomplete_features)] #![feature(inline_const_pat, exclusive_range_pattern)] fn main() { diff --git a/tests/ui/inline-const/const-match-pat.rs b/tests/ui/inline-const/const-match-pat.rs index 2f55e16b35cd9..fc4d37714585e 100644 --- a/tests/ui/inline-const/const-match-pat.rs +++ b/tests/ui/inline-const/const-match-pat.rs @@ -1,6 +1,5 @@ // run-pass -#![allow(incomplete_features)] #![feature(inline_const_pat)] const MMIO_BIT1: u8 = 4; const MMIO_BIT2: u8 = 5; diff --git a/tests/ui/inline-const/pat-match-fndef.rs b/tests/ui/inline-const/pat-match-fndef.rs index fbd4dc66c3a05..013a4a6756102 100644 --- a/tests/ui/inline-const/pat-match-fndef.rs +++ b/tests/ui/inline-const/pat-match-fndef.rs @@ -1,5 +1,4 @@ #![feature(inline_const_pat)] -//~^ WARN the feature `inline_const_pat` is incomplete fn uwu() {} diff --git a/tests/ui/inline-const/pat-match-fndef.stderr b/tests/ui/inline-const/pat-match-fndef.stderr index 02c4a60b68f20..b189ec51ade38 100644 --- a/tests/ui/inline-const/pat-match-fndef.stderr +++ b/tests/ui/inline-const/pat-match-fndef.stderr @@ -1,17 +1,8 @@ -warning: the feature `inline_const_pat` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/pat-match-fndef.rs:1:12 - | -LL | #![feature(inline_const_pat)] - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #76001 for more information - = note: `#[warn(incomplete_features)]` on by default - error: `fn() {uwu}` cannot be used in patterns - --> $DIR/pat-match-fndef.rs:9:9 + --> $DIR/pat-match-fndef.rs:8:9 | LL | const { uwu } => {} | ^^^^^^^^^^^^^ -error: aborting due to 1 previous error; 1 warning emitted +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 index 7680c82efb5c5..b906def702950 100644 --- a/tests/ui/inline-const/pat-unsafe-err.rs +++ b/tests/ui/inline-const/pat-unsafe-err.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(inline_const_pat)] const unsafe fn require_unsafe() -> usize { diff --git a/tests/ui/inline-const/pat-unsafe-err.stderr b/tests/ui/inline-const/pat-unsafe-err.stderr index 9b995d6ccf27e..786c7f31ccce1 100644 --- a/tests/ui/inline-const/pat-unsafe-err.stderr +++ b/tests/ui/inline-const/pat-unsafe-err.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block - --> $DIR/pat-unsafe-err.rs:11:13 + --> $DIR/pat-unsafe-err.rs:10:13 | LL | require_unsafe(); | ^^^^^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | require_unsafe(); = 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:18:13 + --> $DIR/pat-unsafe-err.rs:17:13 | LL | require_unsafe() | ^^^^^^^^^^^^^^^^ call to unsafe function diff --git a/tests/ui/inline-const/pat-unsafe.rs b/tests/ui/inline-const/pat-unsafe.rs index f7073ef40eb09..5a90920ef3cff 100644 --- a/tests/ui/inline-const/pat-unsafe.rs +++ b/tests/ui/inline-const/pat-unsafe.rs @@ -1,6 +1,5 @@ // check-pass -#![allow(incomplete_features)] #![warn(unused_unsafe)] #![feature(inline_const_pat)] diff --git a/tests/ui/inline-const/pat-unsafe.stderr b/tests/ui/inline-const/pat-unsafe.stderr index 84dc10c490258..59460271ac010 100644 --- a/tests/ui/inline-const/pat-unsafe.stderr +++ b/tests/ui/inline-const/pat-unsafe.stderr @@ -1,17 +1,17 @@ warning: unnecessary `unsafe` block - --> $DIR/pat-unsafe.rs:16:17 + --> $DIR/pat-unsafe.rs:15:17 | LL | unsafe {} | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/pat-unsafe.rs:4:9 + --> $DIR/pat-unsafe.rs:3:9 | LL | #![warn(unused_unsafe)] | ^^^^^^^^^^^^^ warning: unnecessary `unsafe` block - --> $DIR/pat-unsafe.rs:23:17 + --> $DIR/pat-unsafe.rs:22:17 | LL | unsafe {} | ^^^^^^ unnecessary `unsafe` block diff --git a/tests/ui/lint/dead-code/anon-const-in-pat.rs b/tests/ui/lint/dead-code/anon-const-in-pat.rs index d3e39c0de69c8..4d7fdddf246ed 100644 --- a/tests/ui/lint/dead-code/anon-const-in-pat.rs +++ b/tests/ui/lint/dead-code/anon-const-in-pat.rs @@ -1,6 +1,5 @@ // check-pass #![feature(inline_const_pat)] -#![allow(incomplete_features)] #![deny(dead_code)] const fn one() -> i32 { diff --git a/tests/ui/match/issue-112438.rs b/tests/ui/match/issue-112438.rs index 15f380f7fb471..46c69d5ba9c77 100644 --- a/tests/ui/match/issue-112438.rs +++ b/tests/ui/match/issue-112438.rs @@ -1,7 +1,6 @@ // run-pass #![feature(inline_const_pat)] #![allow(dead_code)] -#![allow(incomplete_features)] fn foo() { match 0 { const { 1 << 5 } | _ => {} diff --git a/tests/ui/match/validate-range-endpoints.rs b/tests/ui/match/validate-range-endpoints.rs index 1d1737f8b82f4..31d5bc3b65d50 100644 --- a/tests/ui/match/validate-range-endpoints.rs +++ b/tests/ui/match/validate-range-endpoints.rs @@ -1,6 +1,5 @@ #![feature(exclusive_range_pattern)] #![feature(inline_const_pat)] -#![allow(incomplete_features)] #![allow(overlapping_range_endpoints)] fn main() { diff --git a/tests/ui/match/validate-range-endpoints.stderr b/tests/ui/match/validate-range-endpoints.stderr index 0813fccff5187..b3b4066cd9158 100644 --- a/tests/ui/match/validate-range-endpoints.stderr +++ b/tests/ui/match/validate-range-endpoints.stderr @@ -1,59 +1,59 @@ error: literal out of range for `u8` - --> $DIR/validate-range-endpoints.rs:9:12 + --> $DIR/validate-range-endpoints.rs:8: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:11:13 + --> $DIR/validate-range-endpoints.rs:10: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:20:9 + --> $DIR/validate-range-endpoints.rs:19: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:22:9 + --> $DIR/validate-range-endpoints.rs:21:9 | LL | 1..=const { 256 } => {} | ^^^^^^^^^^^^^^^^^ lower bound larger than upper bound error: literal out of range for `u64` - --> $DIR/validate-range-endpoints.rs:28:32 + --> $DIR/validate-range-endpoints.rs:27: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:34:12 + --> $DIR/validate-range-endpoints.rs:33: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:36:13 + --> $DIR/validate-range-endpoints.rs:35: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:38:9 + --> $DIR/validate-range-endpoints.rs:37: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:40:9 + --> $DIR/validate-range-endpoints.rs:39: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:51:11 + --> $DIR/validate-range-endpoints.rs:50:11 | LL | match 0i8 { | ^^^ patterns `i8::MIN..=-17_i8` and `1_i8..=i8::MAX` not covered @@ -66,7 +66,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:55:11 + --> $DIR/validate-range-endpoints.rs:54:11 | LL | match 0i8 { | ^^^ pattern `i8::MIN..=-17_i8` not covered diff --git a/tests/ui/pattern/non-structural-match-types.rs b/tests/ui/pattern/non-structural-match-types.rs index b4f19bb829407..552342a1d3841 100644 --- a/tests/ui/pattern/non-structural-match-types.rs +++ b/tests/ui/pattern/non-structural-match-types.rs @@ -1,6 +1,5 @@ // edition:2021 -#![allow(incomplete_features)] #![allow(unreachable_code)] #![feature(const_async_blocks)] #![feature(inline_const_pat)] diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr index 4a6990da56f6d..f3e0665fef51d 100644 --- a/tests/ui/pattern/non-structural-match-types.stderr +++ b/tests/ui/pattern/non-structural-match-types.stderr @@ -1,11 +1,11 @@ -error: `{closure@$DIR/non-structural-match-types.rs:10:17: 10:19}` cannot be used in patterns - --> $DIR/non-structural-match-types.rs:10:9 +error: `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:9:9 | LL | const { || {} } => {} | ^^^^^^^^^^^^^^^ -error: `{async block@$DIR/non-structural-match-types.rs:13:17: 13:25}` cannot be used in patterns - --> $DIR/non-structural-match-types.rs:13:9 +error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:25}` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:12:9 | LL | const { async {} } => {} | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unsafe/const_pat_in_layout_restricted.rs b/tests/ui/unsafe/const_pat_in_layout_restricted.rs index 5bc7a7113e4f6..9a085958c1080 100644 --- a/tests/ui/unsafe/const_pat_in_layout_restricted.rs +++ b/tests/ui/unsafe/const_pat_in_layout_restricted.rs @@ -2,7 +2,6 @@ // unsafe because they're within a pattern for a layout constrained stuct. // check-pass -#![allow(incomplete_features)] #![feature(rustc_attrs)] #![feature(inline_const_pat)] From 36cb5187918e84e3ab57220aed1a73b5caed3537 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Thu, 1 Feb 2024 21:04:38 +0800 Subject: [PATCH 193/246] internal: add typos.toml as typo white list --- .typos.toml | 55 ++++++++++++++++++++++++++++++++++++++ docs/dev/lsp-extensions.md | 2 +- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 .typos.toml diff --git a/.typos.toml b/.typos.toml new file mode 100644 index 0000000000000..b46fd902ac970 --- /dev/null +++ b/.typos.toml @@ -0,0 +1,55 @@ +[default.extend-identifiers] +makro = "makro" +VisibilityExplicity = "VisibilityExplicity" +impl_froms = "impl_froms" +AnserStyle = "AnserStyle" +explicity = "explicity" +syntaxically = "syntaxically" +datas = "datas" +selfs = "selfs" +TOOD = "TOOD" +strustS = "strustS" +new_function_with_generics_and_wheres = "new_function_with_generics_and_wheres" +Defaul = "Defaul" +nto = "nto" +nknown = "nknown" +ded = "ded" +truct = "truct" +inpu = "inpu" +Convertable = "Convertable" +substitude = "substitude" +nner = "nner" +Contro = "Contro" +numbe = "numbe" +MyUnio = "MyUnio" + +[default.extend-words] +anser = "anser" +ba = "ba" +fromed = "fromed" +fo = "fo" +trivias = "trivias" +mmaped = "mmaped" +mis = "mis" +ket = "ket" +foor = "foor" +FPR = "FPR" +mak = "mak" +OT = "OT" +raison = "raison" +strat = "strat" +unaccessable = "unaccessable" + +[default] +extend-ignore-re = [ + # ignore string which contains $x (x is a num), which use widely in test + ".*\\$\\d.*" +] + +[files] +extend-exclude = [ + "*.json", + "*.rast", + "crates/parser/test_data/lexer/err/*", + "bench_data/*", +] diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 3251dd752682e..b5e3842dd2e66 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -239,7 +239,7 @@ The primary goal of `onEnter` is to handle automatic indentation when opening a This is not yet implemented. The secondary goal is to handle fixing up syntax, like continuing doc strings and comments, and escaping `\n` in string literals. -As proper cursor positioning is raison-d'etat for `onEnter`, it uses `SnippetTextEdit`. +As proper cursor positioning is raison d'être for `onEnter`, it uses `SnippetTextEdit`. ### Unresolved Question From b0be2967cc98659487b728e5d168a8bbecd7b37a Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Thu, 1 Feb 2024 21:07:50 +0800 Subject: [PATCH 194/246] internal: add typos CI check --- .github/workflows/ci.yaml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b5c5ff04738a7..da61627704749 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -207,11 +207,24 @@ jobs: working-directory: ./editors/code if: needs.changes.outputs.typescript == 'true' + typos-check: + name: Typos Check + runs-on: ubuntu-latest + timeout-minutes: 10 + env: + FORCE_COLOR: 1 + steps: + - uses: actions/checkout@v4 + - run: curl -LsSf https://github.com/crate-ci/typos/releases/download/v1.17.2/typos-v1.17.2-x86_64-unknown-linux-musl.tar.gz | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin + + - name: do typos check with typos-cli + run: typos + end-success: name: bors build finished if: github.event.pusher.name == 'bors' && success() runs-on: ubuntu-latest - needs: [rust, rust-cross, typescript] + needs: [rust, rust-cross, typescript, typos-check] steps: - name: Mark the job as successful run: exit 0 @@ -220,7 +233,7 @@ jobs: name: bors build finished if: github.event.pusher.name == 'bors' && !success() runs-on: ubuntu-latest - needs: [rust, rust-cross, typescript] + needs: [rust, rust-cross, typescript, typos-check] steps: - name: Mark the job as a failure run: exit 1 From 0148da3528c2b20103566c5c229a596a900ba9d3 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 1 Feb 2024 09:51:29 -0500 Subject: [PATCH 195/246] put pnkfelix (me) back on the review queue. --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index bf898819cfc16..68c863bb919db 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -652,6 +652,7 @@ compiler-team = [ "@davidtwco", "@estebank", "@oli-obk", + "@pnkfelix", "@wesleywiser", "@michaelwoerister", ] From 02320b502d6ae1398126a068cd1efbb96f87faaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 1 Feb 2024 15:58:07 +0100 Subject: [PATCH 196/246] Improve the diagnostics for unused generic parameters --- .../src/error_codes/E0091.md | 6 +- compiler/rustc_hir_analysis/messages.ftl | 11 +++ .../rustc_hir_analysis/src/check/check.rs | 77 +++++++++++++------ .../rustc_hir_analysis/src/check/wfcheck.rs | 64 +++++++-------- compiler/rustc_hir_analysis/src/errors.rs | 24 ++++++ .../generic_arg_infer/infer-arg-test.stderr | 6 +- tests/ui/const-generics/issue-46511.stderr | 4 +- .../issues/issue-67375.min.stderr | 6 +- .../issues/issue-67945-1.min.stderr | 6 +- .../issues/issue-67945-3.min.stderr | 6 +- .../issues/issue-67945-4.min.stderr | 6 +- .../unused-type-param-suggestion.rs | 27 ++++++- .../unused-type-param-suggestion.stderr | 56 ++++++++++++-- .../issue-70453-generics-in-discr-ice.stderr | 6 +- tests/ui/enum/issue-67945-1.stderr | 6 +- tests/ui/enum/issue-67945-2.stderr | 6 +- tests/ui/error-codes/E0091.stderr | 10 ++- tests/ui/error-codes/E0392.stderr | 6 +- tests/ui/inner-static-type-parameter.stderr | 6 +- tests/ui/issues/issue-17904-2.stderr | 4 +- tests/ui/issues/issue-17994.rs | 2 +- tests/ui/issues/issue-17994.stderr | 4 +- tests/ui/issues/issue-20413.stderr | 6 +- tests/ui/issues/issue-30236.rs | 2 +- tests/ui/issues/issue-30236.stderr | 5 +- tests/ui/issues/issue-31910.stderr | 4 +- tests/ui/issues/issue-34373.stderr | 6 +- tests/ui/issues/issue-36299.stderr | 10 +-- tests/ui/issues/issue-37534.stderr | 4 +- .../lang-item-generic-requirements.stderr | 12 +-- .../unused-generic-parameters.rs | 22 ++++++ .../unused-generic-parameters.stderr | 28 +++++++ .../issue-64173-unused-lifetimes.stderr | 8 +- .../item-free-type-bounds-semantic-fail.rs | 4 +- ...item-free-type-bounds-semantic-fail.stderr | 10 ++- ...unds-on-objects-and-type-parameters.stderr | 4 +- .../tilde-const-invalid-places.stderr | 4 +- tests/ui/self/self_type_keyword.stderr | 4 +- tests/ui/tag-type-args.stderr | 6 +- .../variance-regions-unused-direct.stderr | 8 +- .../variance-regions-unused-indirect.stderr | 8 +- .../variance-unused-region-param.stderr | 8 +- .../variance-unused-type-param.stderr | 30 ++++---- 43 files changed, 371 insertions(+), 171 deletions(-) create mode 100644 tests/ui/lazy-type-alias/unused-generic-parameters.rs create mode 100644 tests/ui/lazy-type-alias/unused-generic-parameters.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0091.md b/compiler/rustc_error_codes/src/error_codes/E0091.md index 03cb32803715e..3bf4e907ecb1f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0091.md +++ b/compiler/rustc_error_codes/src/error_codes/E0091.md @@ -1,11 +1,11 @@ -An unnecessary type or const parameter was given in a type alias. +An unnecessary type parameter was given in a type alias. Erroneous code example: ```compile_fail,E0091 -type Foo = u32; // error: type parameter `T` is unused +type Foo = u32; // error: type parameter `T` is never used // or: -type Foo = Box; // error: type parameter `B` is unused +type Foo = Box; // error: type parameter `B` is never used ``` Please check you didn't write too many parameters. Example: diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 432c9c12cbfbc..54d0fb6ffab72 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -434,6 +434,17 @@ hir_analysis_unused_associated_type_bounds = .note = this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. .suggestion = remove this bound +hir_analysis_unused_generic_parameter = + {$param_def_kind} `{$param_name}` is never used + .label = unused {$param_def_kind} + .const_param_help = if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead +hir_analysis_unused_generic_parameter_adt_help = + consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}` +hir_analysis_unused_generic_parameter_adt_no_phantom_data_help = + consider removing `{$param_name}` or referring to it in a field +hir_analysis_unused_generic_parameter_ty_alias_help = + consider removing `{$param_name}` or referring to it in the body of the type alias + hir_analysis_value_of_associated_struct_already_specified = the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified .label = re-bound here diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 2fe3499e8e690..50809a571b8dc 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -31,6 +31,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _}; use rustc_type_ir::fold::TypeFoldable; +use std::cell::LazyCell; use std::ops::ControlFlow; pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { @@ -520,9 +521,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { } } DefKind::TyAlias => { - let pty_ty = tcx.type_of(def_id).instantiate_identity(); - let generics = tcx.generics_of(def_id); - check_type_params_are_used(tcx, generics, pty_ty); + check_type_alias_type_params_are_used(tcx, def_id); } DefKind::ForeignMod => { let it = tcx.hir().expect_item(def_id); @@ -1269,28 +1268,51 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) } } -pub(super) fn check_type_params_are_used<'tcx>( - tcx: TyCtxt<'tcx>, - generics: &ty::Generics, - ty: Ty<'tcx>, -) { - debug!("check_type_params_are_used(generics={:?}, ty={:?})", generics, ty); - - assert_eq!(generics.parent, None); +fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { + if tcx.type_alias_is_lazy(def_id) { + // Since we compute the variances for lazy type aliases and already reject bivariant + // parameters as unused, we can and should skip this check for lazy type aliases. + return; + } + let generics = tcx.generics_of(def_id); if generics.own_counts().types == 0 { return; } - let mut params_used = BitSet::new_empty(generics.params.len()); - + let ty = tcx.type_of(def_id).instantiate_identity(); if ty.references_error() { - // If there is already another error, do not emit - // an error for not using a type parameter. + // If there is already another error, do not emit an error for not using a type parameter. assert!(tcx.dcx().has_errors().is_some()); return; } + // Lazily calculated because it is only needed in case of an error. + let bounded_params = LazyCell::new(|| { + tcx.explicit_predicates_of(def_id) + .predicates + .iter() + .filter_map(|(predicate, span)| { + let bounded_ty = match predicate.kind().skip_binder() { + ty::ClauseKind::Trait(pred) => pred.trait_ref.self_ty(), + ty::ClauseKind::TypeOutlives(pred) => pred.0, + _ => return None, + }; + if let ty::Param(param) = bounded_ty.kind() { + Some((param.index, span)) + } else { + None + } + }) + // FIXME: This assumes that elaborated `Sized` bounds come first (which does hold at the + // time of writing). This is a bit fragile since we later use the span to detect elaborated + // `Sized` bounds. If they came last for example, this would break `Trait + /*elab*/Sized` + // since it would overwrite the span of the user-written bound. This could be fixed by + // folding the spans with `Span::to` which requires a bit of effort I think. + .collect::>() + }); + + let mut params_used = BitSet::new_empty(generics.params.len()); for leaf in ty.walk() { if let GenericArgKind::Type(leaf_ty) = leaf.unpack() && let ty::Param(param) = leaf_ty.kind() @@ -1305,15 +1327,24 @@ pub(super) fn check_type_params_are_used<'tcx>( && let ty::GenericParamDefKind::Type { .. } = param.kind { let span = tcx.def_span(param.def_id); - struct_span_code_err!( - tcx.dcx(), + let param_name = Ident::new(param.name, span); + + // The corresponding predicates are post-`Sized`-elaboration. Therefore we + // * check for emptiness to detect lone user-written `?Sized` bounds + // * compare the param span to the pred span to detect lone user-written `Sized` bounds + let has_explicit_bounds = bounded_params.is_empty() + || (*bounded_params).get(¶m.index).is_some_and(|&&pred_sp| pred_sp != span); + let const_param_help = (!has_explicit_bounds).then_some(()); + + let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter { span, - E0091, - "type parameter `{}` is unused", - param.name, - ) - .with_span_label(span, "unused type parameter") - .emit(); + param_name, + param_def_kind: tcx.def_descr(param.def_id), + help: errors::UnusedGenericParameterHelp::TyAlias { param_name }, + const_param_help, + }); + diag.code(E0091); + diag.emit(); } } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b9c9eec28139a..07f798dcbda22 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1,11 +1,10 @@ use crate::autoderef::Autoderef; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; +use crate::errors; use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_errors::{ - codes::*, pluralize, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, -}; +use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::lang_items::LangItem; @@ -21,7 +20,7 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{GenericArgKind, GenericArgs}; use rustc_session::parse::feature_err; -use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::regions::InferCtxtRegionExt; @@ -1869,7 +1868,7 @@ fn check_variances_for_type_defn<'tcx>( hir::ParamName::Error => {} _ => { let has_explicit_bounds = explicitly_bounded_params.contains(¶meter); - report_bivariance(tcx, hir_param, has_explicit_bounds); + report_bivariance(tcx, hir_param, has_explicit_bounds, item.kind); } } } @@ -1879,30 +1878,38 @@ fn report_bivariance( tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>, has_explicit_bounds: bool, + item_kind: ItemKind<'_>, ) -> ErrorGuaranteed { - let span = param.span; - let param_name = param.name.ident().name; - let mut err = error_392(tcx, span, param_name); - - let suggested_marker_id = tcx.lang_items().phantom_data(); - // Help is available only in presence of lang items. - let msg = if let Some(def_id) = suggested_marker_id { - format!( - "consider removing `{}`, referring to it in a field, or using a marker such as `{}`", - param_name, - tcx.def_path_str(def_id), - ) - } else { - format!("consider removing `{param_name}` or referring to it in a field") + let param_name = param.name.ident(); + + let help = match item_kind { + ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { + if let Some(def_id) = tcx.lang_items().phantom_data() { + errors::UnusedGenericParameterHelp::Adt { + param_name, + phantom_data: tcx.def_path_str(def_id), + } + } else { + errors::UnusedGenericParameterHelp::AdtNoPhantomData { param_name } + } + } + ItemKind::TyAlias(..) => errors::UnusedGenericParameterHelp::TyAlias { param_name }, + item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"), }; - err.help(msg); - if matches!(param.kind, hir::GenericParamKind::Type { .. }) && !has_explicit_bounds { - err.help(format!( - "if you intended `{param_name}` to be a const parameter, use `const {param_name}: usize` instead" - )); - } - err.emit() + let const_param_help = + matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds) + .then_some(()); + + let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter { + span: param.span, + param_name, + param_def_kind: tcx.def_descr(param.def_id.to_def_id()), + help, + const_param_help, + }); + diag.code(E0392); + diag.emit() } impl<'tcx> WfCheckingCtxt<'_, 'tcx> { @@ -1967,11 +1974,6 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error res } -fn error_392(tcx: TyCtxt<'_>, span: Span, param_name: Symbol) -> DiagnosticBuilder<'_> { - struct_span_code_err!(tcx.dcx(), span, E0392, "parameter `{param_name}` is never used") - .with_span_label(span, "unused parameter") -} - pub fn provide(providers: &mut Providers) { *providers = Providers { check_mod_type_wf, check_well_formed, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index e5871276d6414..4eba31e327f68 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1511,3 +1511,27 @@ pub struct NotSupportedDelegation<'a> { #[label] pub callee_span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_unused_generic_parameter)] +pub(crate) struct UnusedGenericParameter { + #[primary_span] + #[label] + pub span: Span, + pub param_name: Ident, + pub param_def_kind: &'static str, + #[subdiagnostic] + pub help: UnusedGenericParameterHelp, + #[help(hir_analysis_const_param_help)] + pub const_param_help: Option<()>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum UnusedGenericParameterHelp { + #[help(hir_analysis_unused_generic_parameter_adt_help)] + Adt { param_name: Ident, phantom_data: String }, + #[help(hir_analysis_unused_generic_parameter_adt_no_phantom_data_help)] + AdtNoPhantomData { param_name: Ident }, + #[help(hir_analysis_unused_generic_parameter_ty_alias_help)] + TyAlias { param_name: Ident }, +} diff --git a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr index a6b736261e09c..6d8dd017734c0 100644 --- a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr +++ b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr @@ -10,14 +10,14 @@ error: expected identifier, found reserved identifier `_` LL | fn bad_infer_fn<_>() {} | ^ expected identifier, found reserved identifier -error[E0392]: parameter `_` is never used +error[E0392]: type parameter `_` is never used --> $DIR/infer-arg-test.rs:7:17 | LL | struct BadInfer<_>; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `_` to be a const parameter, use `const _: usize` instead + = help: if you intended `_` to be a const parameter, use `const _: /* Type */` instead error[E0107]: struct takes 2 generic arguments but 3 generic arguments were supplied --> $DIR/infer-arg-test.rs:18:10 diff --git a/tests/ui/const-generics/issue-46511.stderr b/tests/ui/const-generics/issue-46511.stderr index d57295fa2fae1..75d59ee40b3b7 100644 --- a/tests/ui/const-generics/issue-46511.stderr +++ b/tests/ui/const-generics/issue-46511.stderr @@ -7,11 +7,11 @@ LL | _a: [u8; std::mem::size_of::<&'a mut u8>()] = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/issue-46511.rs:3:12 | LL | struct Foo<'a> - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/const-generics/issues/issue-67375.min.stderr b/tests/ui/const-generics/issues/issue-67375.min.stderr index 7671e3c468876..e871203ed9b89 100644 --- a/tests/ui/const-generics/issues/issue-67375.min.stderr +++ b/tests/ui/const-generics/issues/issue-67375.min.stderr @@ -7,14 +7,14 @@ LL | inner: [(); { [|_: &T| {}; 0].len() }], = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-67375.rs:5:12 | LL | struct Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-67945-1.min.stderr b/tests/ui/const-generics/issues/issue-67945-1.min.stderr index 1d071da903fa1..1de607644f570 100644 --- a/tests/ui/const-generics/issues/issue-67945-1.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-1.min.stderr @@ -16,14 +16,14 @@ LL | let b = &*(&x as *const _ as *const S); = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0392]: parameter `S` is never used +error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-1.rs:7:12 | LL | struct Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `S` to be a const parameter, use `const S: usize` instead + = help: if you intended `S` to be a const parameter, use `const S: /* Type */` instead error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/issues/issue-67945-3.min.stderr b/tests/ui/const-generics/issues/issue-67945-3.min.stderr index e34869c79386b..0ccba18e953cf 100644 --- a/tests/ui/const-generics/issues/issue-67945-3.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-3.min.stderr @@ -7,14 +7,14 @@ LL | let x: Option = None; = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0392]: parameter `S` is never used +error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-3.rs:9:12 | LL | struct Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `S` to be a const parameter, use `const S: usize` instead + = help: if you intended `S` to be a const parameter, use `const S: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-67945-4.min.stderr b/tests/ui/const-generics/issues/issue-67945-4.min.stderr index 280c6f4f2cdfe..83ae68e2dbf0e 100644 --- a/tests/ui/const-generics/issues/issue-67945-4.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-4.min.stderr @@ -7,14 +7,14 @@ LL | let x: Option> = None; = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0392]: parameter `S` is never used +error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-4.rs:8:12 | LL | struct Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `S` to be a const parameter, use `const S: usize` instead + = help: if you intended `S` to be a const parameter, use `const S: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/unused-type-param-suggestion.rs b/tests/ui/const-generics/unused-type-param-suggestion.rs index 2251512c4596e..fb0ccb4fdcd72 100644 --- a/tests/ui/const-generics/unused-type-param-suggestion.rs +++ b/tests/ui/const-generics/unused-type-param-suggestion.rs @@ -1,4 +1,27 @@ #![crate_type="lib"] -struct Example; -//~^ ERROR parameter +struct S; +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` +//~| HELP if you intended `N` to be a const parameter + +// Ensure that we don't emit the const param suggestion here: +struct T; +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` + +type A = (); +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` +//~| HELP if you intended `N` to be a const parameter + +// Ensure that we don't emit the const param suggestion here: +type B = (); +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` +type C = (); +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` +type D = (); +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` diff --git a/tests/ui/const-generics/unused-type-param-suggestion.stderr b/tests/ui/const-generics/unused-type-param-suggestion.stderr index 6e985f56666bd..67b704d8bc725 100644 --- a/tests/ui/const-generics/unused-type-param-suggestion.stderr +++ b/tests/ui/const-generics/unused-type-param-suggestion.stderr @@ -1,12 +1,54 @@ -error[E0392]: parameter `N` is never used - --> $DIR/unused-type-param-suggestion.rs:3:16 +error[E0392]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:3:10 | -LL | struct Example; - | ^ unused parameter +LL | struct S; + | ^ unused type parameter | = help: consider removing `N`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `N` to be a const parameter, use `const N: usize` instead + = help: if you intended `N` to be a const parameter, use `const N: /* Type */` instead -error: aborting due to 1 previous error +error[E0392]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:9:10 + | +LL | struct T; + | ^ unused type parameter + | + = help: consider removing `N`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0091]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:13:8 + | +LL | type A = (); + | ^ unused type parameter + | + = help: consider removing `N` or referring to it in the body of the type alias + = help: if you intended `N` to be a const parameter, use `const N: /* Type */` instead + +error[E0091]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:19:8 + | +LL | type B = (); + | ^ unused type parameter + | + = help: consider removing `N` or referring to it in the body of the type alias + +error[E0091]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:22:8 + | +LL | type C = (); + | ^ unused type parameter + | + = help: consider removing `N` or referring to it in the body of the type alias + +error[E0091]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:25:8 + | +LL | type D = (); + | ^ unused type parameter + | + = help: consider removing `N` or referring to it in the body of the type alias + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0392`. +Some errors have detailed explanations: E0091, E0392. +For more information about an error, try `rustc --explain E0091`. diff --git a/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr index fac3ce07aeb92..1341b03cb56e4 100644 --- a/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr +++ b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr @@ -6,14 +6,14 @@ LL | Some = std::mem::size_of::(), | = note: type parameters may not be used in enum discriminant values -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-70453-generics-in-discr-ice.rs:7:20 | LL | enum MyWeirdOption { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/enum/issue-67945-1.stderr b/tests/ui/enum/issue-67945-1.stderr index 878fa322f02d5..ce0ea77763663 100644 --- a/tests/ui/enum/issue-67945-1.stderr +++ b/tests/ui/enum/issue-67945-1.stderr @@ -6,14 +6,14 @@ LL | let x: S = 0; | = note: type parameters may not be used in enum discriminant values -error[E0392]: parameter `S` is never used +error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-1.rs:1:10 | LL | enum Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `S` to be a const parameter, use `const S: usize` instead + = help: if you intended `S` to be a const parameter, use `const S: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/enum/issue-67945-2.stderr b/tests/ui/enum/issue-67945-2.stderr index f8ec12d470acf..96bd08f841a40 100644 --- a/tests/ui/enum/issue-67945-2.stderr +++ b/tests/ui/enum/issue-67945-2.stderr @@ -6,14 +6,14 @@ LL | Var = type_ascribe!(0, S), | = note: type parameters may not be used in enum discriminant values -error[E0392]: parameter `S` is never used +error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-2.rs:3:10 | LL | enum Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `S` to be a const parameter, use `const S: usize` instead + = help: if you intended `S` to be a const parameter, use `const S: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0091.stderr b/tests/ui/error-codes/E0091.stderr index a596b75e481de..c1427ec66863a 100644 --- a/tests/ui/error-codes/E0091.stderr +++ b/tests/ui/error-codes/E0091.stderr @@ -1,14 +1,20 @@ -error[E0091]: type parameter `T` is unused +error[E0091]: type parameter `T` is never used --> $DIR/E0091.rs:1:10 | LL | type Foo = u32; | ^ unused type parameter + | + = help: consider removing `T` or referring to it in the body of the type alias + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error[E0091]: type parameter `B` is unused +error[E0091]: type parameter `B` is never used --> $DIR/E0091.rs:2:14 | LL | type Foo2 = Box; | ^ unused type parameter + | + = help: consider removing `B` or referring to it in the body of the type alias + = help: if you intended `B` to be a const parameter, use `const B: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0392.stderr b/tests/ui/error-codes/E0392.stderr index ecbfd5584d5a3..9971267e9270d 100644 --- a/tests/ui/error-codes/E0392.stderr +++ b/tests/ui/error-codes/E0392.stderr @@ -1,11 +1,11 @@ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/E0392.rs:1:10 | LL | enum Foo { Bar } - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 1 previous error diff --git a/tests/ui/inner-static-type-parameter.stderr b/tests/ui/inner-static-type-parameter.stderr index ff6558e494b11..6c7f1ffbe1690 100644 --- a/tests/ui/inner-static-type-parameter.stderr +++ b/tests/ui/inner-static-type-parameter.stderr @@ -6,14 +6,14 @@ LL | fn foo() { LL | static a: Bar = Bar::What; | ^ use of generic parameter from outer item -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/inner-static-type-parameter.rs:3:10 | LL | enum Bar { What } - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-17904-2.stderr b/tests/ui/issues/issue-17904-2.stderr index 102c8537f8e04..9965106d1401a 100644 --- a/tests/ui/issues/issue-17904-2.stderr +++ b/tests/ui/issues/issue-17904-2.stderr @@ -1,8 +1,8 @@ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-17904-2.rs:4:12 | LL | struct Foo where T: Copy; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/issues/issue-17994.rs b/tests/ui/issues/issue-17994.rs index 39b0a7ebe74d8..ab37a172eaa74 100644 --- a/tests/ui/issues/issue-17994.rs +++ b/tests/ui/issues/issue-17994.rs @@ -1,3 +1,3 @@ trait Tr {} -type Huh where T: Tr = isize; //~ ERROR type parameter `T` is unused +type Huh where T: Tr = isize; //~ ERROR type parameter `T` is never used fn main() {} diff --git a/tests/ui/issues/issue-17994.stderr b/tests/ui/issues/issue-17994.stderr index ba3def64dfb5d..f149e5d08faac 100644 --- a/tests/ui/issues/issue-17994.stderr +++ b/tests/ui/issues/issue-17994.stderr @@ -1,8 +1,10 @@ -error[E0091]: type parameter `T` is unused +error[E0091]: type parameter `T` is never used --> $DIR/issue-17994.rs:2:10 | LL | type Huh where T: Tr = isize; | ^ unused type parameter + | + = help: consider removing `T` or referring to it in the body of the type alias error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-20413.stderr b/tests/ui/issues/issue-20413.stderr index 8793029dd224a..5d442eb989851 100644 --- a/tests/ui/issues/issue-20413.stderr +++ b/tests/ui/issues/issue-20413.stderr @@ -1,11 +1,11 @@ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-20413.rs:6:15 | LL | struct NoData; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error[E0275]: overflow evaluating the requirement `NoData>>>>>>: Foo` --> $DIR/issue-20413.rs:9:36 diff --git a/tests/ui/issues/issue-30236.rs b/tests/ui/issues/issue-30236.rs index 9c2d855076d79..08d08a544021e 100644 --- a/tests/ui/issues/issue-30236.rs +++ b/tests/ui/issues/issue-30236.rs @@ -1,5 +1,5 @@ type Foo< - Unused //~ ERROR type parameter `Unused` is unused + Unused //~ ERROR type parameter `Unused` is never used > = u8; fn main() { diff --git a/tests/ui/issues/issue-30236.stderr b/tests/ui/issues/issue-30236.stderr index 0f69f49f505a0..bfe374a653f5f 100644 --- a/tests/ui/issues/issue-30236.stderr +++ b/tests/ui/issues/issue-30236.stderr @@ -1,8 +1,11 @@ -error[E0091]: type parameter `Unused` is unused +error[E0091]: type parameter `Unused` is never used --> $DIR/issue-30236.rs:2:5 | LL | Unused | ^^^^^^ unused type parameter + | + = help: consider removing `Unused` or referring to it in the body of the type alias + = help: if you intended `Unused` to be a const parameter, use `const Unused: /* Type */` instead error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-31910.stderr b/tests/ui/issues/issue-31910.stderr index 89a6d5574a1e5..ca2d2f619e62e 100644 --- a/tests/ui/issues/issue-31910.stderr +++ b/tests/ui/issues/issue-31910.stderr @@ -4,11 +4,11 @@ error[E0308]: mismatched types LL | X = Trait::Number, | ^^^^^^^^^^^^^ expected `isize`, found `i32` -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-31910.rs:1:11 | LL | enum Enum { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/issues/issue-34373.stderr b/tests/ui/issues/issue-34373.stderr index 1a1cfc925b779..13667cd920e9b 100644 --- a/tests/ui/issues/issue-34373.stderr +++ b/tests/ui/issues/issue-34373.stderr @@ -45,14 +45,14 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo(_: T) where Self: Sized {} | +++++++++++++++++ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-34373.rs:7:16 | LL | pub struct Foo>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unused parameter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-36299.stderr b/tests/ui/issues/issue-36299.stderr index dc24fb353f408..29e8d7ca59a24 100644 --- a/tests/ui/issues/issue-36299.stderr +++ b/tests/ui/issues/issue-36299.stderr @@ -1,19 +1,19 @@ -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/issue-36299.rs:1:12 | LL | struct Foo<'a, A> {} - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `A` is never used +error[E0392]: type parameter `A` is never used --> $DIR/issue-36299.rs:1:16 | LL | struct Foo<'a, A> {} - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `A` to be a const parameter, use `const A: usize` instead + = help: if you intended `A` to be a const parameter, use `const A: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-37534.stderr b/tests/ui/issues/issue-37534.stderr index 03fea2c16486d..a687e733d3dae 100644 --- a/tests/ui/issues/issue-37534.stderr +++ b/tests/ui/issues/issue-37534.stderr @@ -15,11 +15,11 @@ warning: relaxing a default bound only does something for `?Sized`; all other tr LL | struct Foo {} | ^^^^^ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-37534.rs:1:12 | LL | struct Foo {} - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/lang-items/lang-item-generic-requirements.stderr b/tests/ui/lang-items/lang-item-generic-requirements.stderr index 8072e6797e49c..30abdf84046ea 100644 --- a/tests/ui/lang-items/lang-item-generic-requirements.stderr +++ b/tests/ui/lang-items/lang-item-generic-requirements.stderr @@ -50,23 +50,23 @@ LL | LL | fn start(_: *const u8, _: isize, _: *const *const u8) -> isize { | - this function has 0 generic arguments -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/lang-item-generic-requirements.rs:24:22 | LL | struct MyPhantomData; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T` or referring to it in a field - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error[E0392]: parameter `U` is never used +error[E0392]: type parameter `U` is never used --> $DIR/lang-item-generic-requirements.rs:24:25 | LL | struct MyPhantomData; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `U` or referring to it in a field - = help: if you intended `U` to be a const parameter, use `const U: usize` instead + = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead error[E0369]: cannot add `{integer}` to `{integer}` --> $DIR/lang-item-generic-requirements.rs:44:7 diff --git a/tests/ui/lazy-type-alias/unused-generic-parameters.rs b/tests/ui/lazy-type-alias/unused-generic-parameters.rs new file mode 100644 index 0000000000000..9d02de7a7212b --- /dev/null +++ b/tests/ui/lazy-type-alias/unused-generic-parameters.rs @@ -0,0 +1,22 @@ +// Check that we reject bivariant generic parameters as unused. +// Furthermore, check that we only emit a single diagnostic for unused type parameters: +// Previously, we would emit *two* errors, namely E0392 and E0091. + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +type A<'a> = (); +//~^ ERROR lifetime parameter `'a` is never used +//~| HELP consider removing `'a` + +type B = (); +//~^ ERROR type parameter `T` is never used +//~| HELP consider removing `T` +//~| HELP if you intended `T` to be a const parameter + +// Check that we don't emit the const param help message here: +type C = (); +//~^ ERROR type parameter `T` is never used +//~| HELP consider removing `T` + +fn main() {} diff --git a/tests/ui/lazy-type-alias/unused-generic-parameters.stderr b/tests/ui/lazy-type-alias/unused-generic-parameters.stderr new file mode 100644 index 0000000000000..484e21b0a03f9 --- /dev/null +++ b/tests/ui/lazy-type-alias/unused-generic-parameters.stderr @@ -0,0 +1,28 @@ +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/unused-generic-parameters.rs:8:8 + | +LL | type A<'a> = (); + | ^^ unused lifetime parameter + | + = help: consider removing `'a` or referring to it in the body of the type alias + +error[E0392]: type parameter `T` is never used + --> $DIR/unused-generic-parameters.rs:12:8 + | +LL | type B = (); + | ^ unused type parameter + | + = help: consider removing `T` or referring to it in the body of the type alias + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/unused-generic-parameters.rs:18:8 + | +LL | type C = (); + | ^ unused type parameter + | + = help: consider removing `T` or referring to it in the body of the type alias + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr index ec4aea623911a..534ba933ba5d0 100644 --- a/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr +++ b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr @@ -13,19 +13,19 @@ error: generic `Self` types are currently not permitted in anonymous constants LL | array: [(); size_of::<&Self>()], | ^^^^ -error[E0392]: parameter `'s` is never used +error[E0392]: lifetime parameter `'s` is never used --> $DIR/issue-64173-unused-lifetimes.rs:3:12 | LL | struct Foo<'s> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'s`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/issue-64173-unused-lifetimes.rs:15:12 | LL | struct Bar<'a> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/parser/item-free-type-bounds-semantic-fail.rs b/tests/ui/parser/item-free-type-bounds-semantic-fail.rs index 9db4111fbabd9..062b51e597845 100644 --- a/tests/ui/parser/item-free-type-bounds-semantic-fail.rs +++ b/tests/ui/parser/item-free-type-bounds-semantic-fail.rs @@ -13,8 +13,8 @@ fn semantics() { //~| ERROR free type alias without body type E<_T>: Ord = u8; //~^ ERROR bounds on `type`s in this context have no effect - //~| ERROR type parameter `_T` is unused + //~| ERROR type parameter `_T` is never used type F<_T>: Ord where 'static: 'static = u8; //~^ ERROR bounds on `type`s in this context have no effect - //~| ERROR type parameter `_T` is unused + //~| ERROR type parameter `_T` is never used } diff --git a/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr b/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr index 1b086512891f2..1077c10392888 100644 --- a/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr +++ b/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr @@ -50,17 +50,23 @@ error: bounds on `type`s in this context have no effect LL | type F<_T>: Ord where 'static: 'static = u8; | ^^^ -error[E0091]: type parameter `_T` is unused +error[E0091]: type parameter `_T` is never used --> $DIR/item-free-type-bounds-semantic-fail.rs:14:12 | LL | type E<_T>: Ord = u8; | ^^ unused type parameter + | + = help: consider removing `_T` or referring to it in the body of the type alias + = help: if you intended `_T` to be a const parameter, use `const _T: /* Type */` instead -error[E0091]: type parameter `_T` is unused +error[E0091]: type parameter `_T` is never used --> $DIR/item-free-type-bounds-semantic-fail.rs:17:12 | LL | type F<_T>: Ord where 'static: 'static = u8; | ^^ unused type parameter + | + = help: consider removing `_T` or referring to it in the body of the type alias + = help: if you intended `_T` to be a const parameter, use `const _T: /* Type */` instead error: aborting due to 10 previous errors diff --git a/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr b/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr index 2ec2ca49b1142..b15d2affeea37 100644 --- a/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr +++ b/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr @@ -21,11 +21,11 @@ note: but lifetime parameter must outlive the lifetime `'a` as defined here LL | struct Foo<'a,'b,'c> { | ^^ -error[E0392]: parameter `'c` is never used +error[E0392]: lifetime parameter `'c` is never used --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:18 | LL | struct Foo<'a,'b,'c> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr index d57f5702a6382..92a9c347a075e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -272,11 +272,11 @@ LL | type Type = (); = help: add `#![feature(inherent_associated_types)]` 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[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/tilde-const-invalid-places.rs:11:19 | LL | struct UnitStruct; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/self/self_type_keyword.stderr b/tests/ui/self/self_type_keyword.stderr index fed853a7e1fd8..4909a9cdc7f5c 100644 --- a/tests/ui/self/self_type_keyword.stderr +++ b/tests/ui/self/self_type_keyword.stderr @@ -72,11 +72,11 @@ note: unit struct `foo::Self` exists but is inaccessible LL | struct Self; | ^^^^^^^^^^^^ not accessible -error[E0392]: parameter `'Self` is never used +error[E0392]: lifetime parameter `'Self` is never used --> $DIR/self_type_keyword.rs:6:12 | LL | struct Bar<'Self>; - | ^^^^^ unused parameter + | ^^^^^ unused lifetime parameter | = help: consider removing `'Self`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/tag-type-args.stderr b/tests/ui/tag-type-args.stderr index 80ffd3a2f0500..a1136f61cc52f 100644 --- a/tests/ui/tag-type-args.stderr +++ b/tests/ui/tag-type-args.stderr @@ -14,14 +14,14 @@ help: add missing generic argument LL | fn foo(c: Quux) { assert!((false)); } | +++ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/tag-type-args.rs:1:11 | LL | enum Quux { Bar } - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/variance/variance-regions-unused-direct.stderr b/tests/ui/variance/variance-regions-unused-direct.stderr index 1a600f5b0580f..4dc2af6ce2cc8 100644 --- a/tests/ui/variance/variance-regions-unused-direct.stderr +++ b/tests/ui/variance/variance-regions-unused-direct.stderr @@ -1,16 +1,16 @@ -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/variance-regions-unused-direct.rs:5:18 | LL | struct Bivariant<'a>; - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `'d` is never used +error[E0392]: lifetime parameter `'d` is never used --> $DIR/variance-regions-unused-direct.rs:7:19 | LL | struct Struct<'a, 'd> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'d`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/variance/variance-regions-unused-indirect.stderr b/tests/ui/variance/variance-regions-unused-indirect.stderr index 14fdd849294b1..ec4d480baab78 100644 --- a/tests/ui/variance/variance-regions-unused-indirect.stderr +++ b/tests/ui/variance/variance-regions-unused-indirect.stderr @@ -21,19 +21,19 @@ LL | enum Bar<'a> { LL ~ Bar1(Box>) | -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/variance-regions-unused-indirect.rs:3:10 | LL | enum Foo<'a> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/variance-regions-unused-indirect.rs:8:10 | LL | enum Bar<'a> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/variance/variance-unused-region-param.stderr b/tests/ui/variance/variance-unused-region-param.stderr index 7c7ec40ba35c3..b9c08bd43c454 100644 --- a/tests/ui/variance/variance-unused-region-param.stderr +++ b/tests/ui/variance/variance-unused-region-param.stderr @@ -1,16 +1,16 @@ -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/variance-unused-region-param.rs:3:19 | LL | struct SomeStruct<'a> { x: u32 } - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/variance-unused-region-param.rs:4:15 | LL | enum SomeEnum<'a> { Nothing } - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/variance/variance-unused-type-param.stderr b/tests/ui/variance/variance-unused-type-param.stderr index e612da118f058..3011b7bd18fa7 100644 --- a/tests/ui/variance/variance-unused-type-param.stderr +++ b/tests/ui/variance/variance-unused-type-param.stderr @@ -1,51 +1,51 @@ -error[E0392]: parameter `A` is never used +error[E0392]: type parameter `A` is never used --> $DIR/variance-unused-type-param.rs:6:19 | LL | struct SomeStruct { x: u32 } - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `A` to be a const parameter, use `const A: usize` instead + = help: if you intended `A` to be a const parameter, use `const A: /* Type */` instead -error[E0392]: parameter `A` is never used +error[E0392]: type parameter `A` is never used --> $DIR/variance-unused-type-param.rs:9:15 | LL | enum SomeEnum { Nothing } - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `A` to be a const parameter, use `const A: usize` instead + = help: if you intended `A` to be a const parameter, use `const A: /* Type */` instead -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/variance-unused-type-param.rs:13:15 | LL | enum ListCell { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/variance-unused-type-param.rs:19:19 | LL | struct WithBounds {} - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/variance-unused-type-param.rs:22:24 | LL | struct WithWhereBounds where T: Sized {} - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/variance-unused-type-param.rs:25:27 | LL | struct WithOutlivesBounds {} - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` From bedd81ef2afdf5979e316cde4c664bd13d49b266 Mon Sep 17 00:00:00 2001 From: Jeremiah Senkpiel Date: Wed, 31 Jan 2024 16:58:35 -0800 Subject: [PATCH 197/246] add test for try-block-in-match-arm This is noted as an implementation concern under the tracking issue for `?` and `try` blocks. (Issue 31436) --- tests/ui/try-block/try-block-in-match-arm.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/ui/try-block/try-block-in-match-arm.rs diff --git a/tests/ui/try-block/try-block-in-match-arm.rs b/tests/ui/try-block/try-block-in-match-arm.rs new file mode 100644 index 0000000000000..ea004ebe29f9e --- /dev/null +++ b/tests/ui/try-block/try-block-in-match-arm.rs @@ -0,0 +1,11 @@ +// check-pass +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn main() { + let _ = match 1 { + 1 => try {} + _ => Ok::<(), ()>(()), + }; +} From 2c0030ff2cb373a31d4dfa7f7cb3596739090ff3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 1 Feb 2024 14:56:41 +0100 Subject: [PATCH 198/246] Correctly check `never_type` feature gating --- compiler/rustc_ast_passes/src/feature_gate.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 82236d2e30678..409aef9185d92 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -362,6 +362,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } + fn visit_generic_args(&mut self, args: &'a ast::GenericArgs) { + // This check needs to happen here because the never type can be returned from a function, + // but cannot be used in any other context. If this check was in `visit_fn_ret_ty`, it + // include both functions and generics like `impl Fn() -> !`. + if let ast::GenericArgs::Parenthesized(generic_args) = args + && let ast::FnRetTy::Ty(ref ty) = generic_args.output + && matches!(ty.kind, ast::TyKind::Never) + { + gate!(&self, never_type, ty.span, "the `!` type is experimental"); + } + visit::walk_generic_args(self, args); + } + fn visit_expr(&mut self, e: &'a ast::Expr) { match e.kind { ast::ExprKind::TryBlock(_) => { From 0f21e45e95ea879ec13a690390c9d0bd327bfe58 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 1 Feb 2024 14:57:01 +0100 Subject: [PATCH 199/246] Update `never_type` feature gate ui test --- .../feature-gates/feature-gate-never_type.rs | 9 ++++++ .../feature-gate-never_type.stderr | 32 ++++++++++++++++++- .../never-type-in-nested-fn-decl.rs | 7 ++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/ui/never_type/never-type-in-nested-fn-decl.rs diff --git a/tests/ui/feature-gates/feature-gate-never_type.rs b/tests/ui/feature-gates/feature-gate-never_type.rs index be8c27dbb1b02..f5d28a4877fdf 100644 --- a/tests/ui/feature-gates/feature-gate-never_type.rs +++ b/tests/ui/feature-gates/feature-gate-never_type.rs @@ -13,5 +13,14 @@ impl Foo for Meeshka { type Wub = !; //~ ERROR type is experimental } +fn look_ma_no_feature_gate !>() {} //~ ERROR type is experimental +fn tadam(f: &dyn Fn() -> !) {} //~ ERROR type is experimental +fn panic() -> ! { + panic!(); +} +fn toudoum() -> impl Fn() -> ! { //~ ERROR type is experimental + panic +} + fn main() { } diff --git a/tests/ui/feature-gates/feature-gate-never_type.stderr b/tests/ui/feature-gates/feature-gate-never_type.stderr index 0fca58519ce13..33e4e019b18d3 100644 --- a/tests/ui/feature-gates/feature-gate-never_type.stderr +++ b/tests/ui/feature-gates/feature-gate-never_type.stderr @@ -48,6 +48,36 @@ LL | type Wub = !; = help: add `#![feature(never_type)]` 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 5 previous errors +error[E0658]: the `!` type is experimental + --> $DIR/feature-gate-never_type.rs:16:43 + | +LL | fn look_ma_no_feature_gate !>() {} + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the `!` type is experimental + --> $DIR/feature-gate-never_type.rs:17:26 + | +LL | fn tadam(f: &dyn Fn() -> !) {} + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the `!` type is experimental + --> $DIR/feature-gate-never_type.rs:21:30 + | +LL | fn toudoum() -> impl Fn() -> ! { + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` 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 8 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/never_type/never-type-in-nested-fn-decl.rs b/tests/ui/never_type/never-type-in-nested-fn-decl.rs new file mode 100644 index 0000000000000..df546c4717eb6 --- /dev/null +++ b/tests/ui/never_type/never-type-in-nested-fn-decl.rs @@ -0,0 +1,7 @@ +// build-pass + +trait X {} + +fn hello ! { loop {} } 1 }>>() {} + +fn main() {} From 0df6dfdc78624282b4193fc2290ba79d26ba6db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 1 Feb 2024 22:38:16 +0000 Subject: [PATCH 200/246] fix rebase --- tests/incremental/hashes/trait_defs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/incremental/hashes/trait_defs.rs b/tests/incremental/hashes/trait_defs.rs index 437b364e001ee..60faf3c47d69d 100644 --- a/tests/incremental/hashes/trait_defs.rs +++ b/tests/incremental/hashes/trait_defs.rs @@ -559,7 +559,7 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToMethodTypeParameter { #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] From 6ac035df442a27cf9e99ab4ec25bb6147a700902 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 1 Feb 2024 22:53:25 +0000 Subject: [PATCH 201/246] Revert unsound libcore changes of #119911 --- library/core/src/lib.rs | 1 - library/core/src/num/int_macros.rs | 284 ++++++++-------------------- library/core/src/num/uint_macros.rs | 249 ++++++++---------------- tests/codegen/pow_of_two.rs | 55 ------ 4 files changed, 149 insertions(+), 440 deletions(-) delete mode 100644 tests/codegen/pow_of_two.rs diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 2af242d4b5071..ead8cbe0e2f43 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -200,7 +200,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(not(bootstrap), feature(is_val_statically_known))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index bb35b6128ea5a..d052dcc3e6ee6 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1374,59 +1374,26 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn checked_pow(self, mut exp: u32) -> Option { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.unsigned_abs().is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return Some(1); - } - if self == -1 { // Avoid divide by zero - return Some(if exp & 1 != 0 { -1 } else { 1 }); - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 }; - if exp > Self::BITS / power_used { return None; } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - let res = unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )}; - // LLVM doesn't always optimize out the checks - // at the ir level. - - let sign = self.is_negative() && exp & 1 != 0; - if !sign && res == Self::MIN { - None - } else if sign { - Some(res.wrapping_neg()) - } else { - Some(res) - } - } else { - if exp == 0 { - return Some(1); - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = try_opt!(acc.checked_mul(base)); - } - exp /= 2; - base = try_opt!(base.checked_mul(base)); + if exp == 0 { + return Some(1); + } + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = try_opt!(acc.checked_mul(base)); } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.checked_mul(base) + exp /= 2; + base = try_opt!(base.checked_mul(base)); } + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.checked_mul(base) } /// Strict exponentiation. Computes `self.pow(exp)`, panicking if @@ -2091,58 +2058,27 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn wrapping_pow(self, mut exp: u32) -> Self { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.unsigned_abs().is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return 1; - } - if self == -1 { // Avoid divide by zero - return if exp & 1 != 0 { -1 } else { 1 }; - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 }; - if exp > Self::BITS / power_used { return 0; } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - let res = unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )}; - // LLVM doesn't always optimize out the checks - // at the ir level. - - let sign = self.is_negative() && exp & 1 != 0; - if sign { - res.wrapping_neg() - } else { - res - } - } else { - if exp == 0 { - return 1; - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.wrapping_mul(base); - } - exp /= 2; - base = base.wrapping_mul(base); - } + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.wrapping_mul(base) + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + } + exp /= 2; + base = base.wrapping_mul(base); } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.wrapping_mul(base) } /// Calculates `self` + `rhs` @@ -2625,68 +2561,36 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.unsigned_abs().is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return (1, false); - } - if self == -1 { // Avoid divide by zero - return (if exp & 1 != 0 { -1 } else { 1 }, false); - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 }; - if exp > Self::BITS / power_used { return (0, true); } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - let res = unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )}; - // LLVM doesn't always optimize out the checks - // at the ir level. - - let sign = self.is_negative() && exp & 1 != 0; - let overflow = res == Self::MIN; - if sign { - (res.wrapping_neg(), overflow) - } else { - (res, overflow) - } - } else { - if exp == 0 { - return (1,false); - } - let mut base = self; - let mut acc: Self = 1; - let mut overflown = false; - // Scratch space for storing results of overflowing_mul. - let mut r; - - while exp > 1 { - if (exp & 1) == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } - exp /= 2; - r = base.overflowing_mul(base); - base = r.0; + if exp == 0 { + return (1,false); + } + let mut base = self; + let mut acc: Self = 1; + let mut overflown = false; + // Scratch space for storing results of overflowing_mul. + let mut r; + + while exp > 1 { + if (exp & 1) == 1 { + r = acc.overflowing_mul(base); + acc = r.0; overflown |= r.1; } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - r = acc.overflowing_mul(base); - r.1 |= overflown; - r + exp /= 2; + r = base.overflowing_mul(base); + base = r.0; + overflown |= r.1; } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + r = acc.overflowing_mul(base); + r.1 |= overflown; + r } /// Raises self to the power of `exp`, using exponentiation by squaring. @@ -2704,68 +2608,28 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] #[rustc_inherit_overflow_checks] - #[track_caller] // Hides the hackish overflow check for powers of two. pub const fn pow(self, mut exp: u32) -> Self { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.unsigned_abs().is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return 1; - } - if self == -1 { // Avoid divide by zero - return if exp & 1 != 0 { -1 } else { 1 }; - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 }; - if exp > Self::BITS / power_used { // Division of constants is free - #[allow(arithmetic_overflow)] - return Self::MAX * Self::MAX * 0; - } + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc = 1; - // SAFETY: exp <= Self::BITS / power_used - let res = unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )}; - // LLVM doesn't always optimize out the checks - // at the ir level. - - let sign = self.is_negative() && exp & 1 != 0; - #[allow(arithmetic_overflow)] - if !sign && res == Self::MIN { - // So it panics. - _ = Self::MAX * Self::MAX; - } - if sign { - res.wrapping_neg() - } else { - res - } - } else { - if exp == 0 { - return 1; - } - let mut base = self; - let mut acc = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc * base; - } - exp /= 2; - base = base * base; + while exp > 1 { + if (exp & 1) == 1 { + acc = acc * base; } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc * base + exp /= 2; + base = base * base; } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc * base } /// Returns the square root of the number, rounded down. diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index d450c68a5b230..a217c2e259d2b 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1364,49 +1364,28 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn checked_pow(self, mut exp: u32) -> Option { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return Some(1); - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 }; - if exp > Self::BITS / power_used { return None; } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - unsafe { Some(intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )) } - // LLVM doesn't always optimize out the checks - // at the ir level. - } else { - if exp == 0 { - return Some(1); - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = try_opt!(acc.checked_mul(base)); - } - exp /= 2; - base = try_opt!(base.checked_mul(base)); + if exp == 0 { + return Some(1); + } + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = try_opt!(acc.checked_mul(base)); } + exp /= 2; + base = try_opt!(base.checked_mul(base)); + } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. - acc.checked_mul(base) - } + acc.checked_mul(base) } /// Strict exponentiation. Computes `self.pow(exp)`, panicking if @@ -1908,48 +1887,27 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn wrapping_pow(self, mut exp: u32) -> Self { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return 1; - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 }; - if exp > Self::BITS / power_used { return 0; } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )} - // LLVM doesn't always optimize out the checks - // at the ir level. - } else { - if exp == 0 { - return 1; - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.wrapping_mul(base); - } - exp /= 2; - base = base.wrapping_mul(base); - } + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.wrapping_mul(base) + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + } + exp /= 2; + base = base.wrapping_mul(base); } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.wrapping_mul(base) } /// Calculates `self` + `rhs` @@ -2383,58 +2341,37 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return (1, false); - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 }; - if exp > Self::BITS / power_used { return (0, true); } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - unsafe { (intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - ), false) } - // LLVM doesn't always optimize out the checks - // at the ir level. - } else { - if exp == 0{ - return (1,false); - } - let mut base = self; - let mut acc: Self = 1; - let mut overflown = false; - // Scratch space for storing results of overflowing_mul. - let mut r; - - while exp > 1 { - if (exp & 1) == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } - exp /= 2; - r = base.overflowing_mul(base); - base = r.0; + if exp == 0{ + return (1,false); + } + let mut base = self; + let mut acc: Self = 1; + let mut overflown = false; + // Scratch space for storing results of overflowing_mul. + let mut r; + + while exp > 1 { + if (exp & 1) == 1 { + r = acc.overflowing_mul(base); + acc = r.0; overflown |= r.1; } + exp /= 2; + r = base.overflowing_mul(base); + base = r.0; + overflown |= r.1; + } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - r = acc.overflowing_mul(base); - r.1 |= overflown; + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + r = acc.overflowing_mul(base); + r.1 |= overflown; - r - } + r } /// Raises self to the power of `exp`, using exponentiation by squaring. @@ -2450,64 +2387,28 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] #[rustc_inherit_overflow_checks] - #[track_caller] // Hides the hackish overflow check for powers of two. pub const fn pow(self, mut exp: u32) -> Self { - // LLVM now knows that `self` is a constant value, but not a - // constant in Rust. This allows us to compute the power used at - // compile-time. - // - // This will likely add a branch in debug builds, but this should - // be ok. - // - // This is a massive performance boost in release builds as you can - // get the power of a power of two and the exponent through a `shl` - // instruction, but we must add a couple more checks for parity with - // our own `pow`. - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return 1; - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 }; - if exp > Self::BITS / power_used { // Division of constants is free - #[allow(arithmetic_overflow)] - return Self::MAX * Self::MAX * 0; - } + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc = 1; - // SAFETY: exp <= Self::BITS / power_used - unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )} - // LLVM doesn't always optimize out the checks - // at the ir level. - } else { - if exp == 0 { - return 1; - } - let mut base = self; - let mut acc = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc * base; - } - exp /= 2; - base = base * base; + while exp > 1 { + if (exp & 1) == 1 { + acc = acc * base; } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc * base + exp /= 2; + base = base * base; } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc * base } /// Returns the square root of the number, rounded down. diff --git a/tests/codegen/pow_of_two.rs b/tests/codegen/pow_of_two.rs deleted file mode 100644 index 372360dfd12c7..0000000000000 --- a/tests/codegen/pow_of_two.rs +++ /dev/null @@ -1,55 +0,0 @@ -// compile-flags: --crate-type=lib -Zmerge-functions=disabled -O -C overflow-checks=false - -// CHECK-LABEL: @a( -#[no_mangle] -pub fn a(exp: u32) -> u64 { - // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64 - // CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64 - // CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}} - // CHECK: ret i64 %{{[^ ]+}} - 2u64.pow(exp) -} - -// CHECK-LABEL: @b( -#[no_mangle] -pub fn b(exp: u32) -> i64 { - // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64 - // CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64 - // CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}} - // CHECK: ret i64 %{{[^ ]+}} - 2i64.pow(exp) -} - -// CHECK-LABEL: @c( -#[no_mangle] -pub fn c(exp: u32) -> u32 { - // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 16 - // CHECK: %{{[^ ]+}} = shl nuw nsw i32 %exp, 1 - // CHECK: %{{[^ ]+}} = shl nuw i32 1, %{{[^ ]+}} - // CHECK: %{{[^ ]+}} = select i1 %{{[^ ]+}}, i32 0, i32 %{{[^ ]+}} - // CHECK: ret i32 %{{[^ ]+}} - 4u32.pow(exp) -} - -// CHECK-LABEL: @d( -#[no_mangle] -pub fn d(exp: u32) -> u32 { - // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 6 - // CHECK: %{{[^ ]+}} = mul nuw nsw i32 %exp, 5 - // CHECK: %{{[^ ]+}} = shl nuw nsw i32 1, %{{[^ ]+}} - // CHECK: %{{[^ ]+}} = select i1 {{[^ ]+}}, i32 0, i32 %{{[^ ]+}} - // CHECK: ret i32 %{{[^ ]+}} - 32u32.pow(exp) -} - -// CHECK-LABEL: @e( -#[no_mangle] -pub fn e(exp: u32) -> i32 { - // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 6 - // CHECK: %{{[^ ]+}} = mul nuw {{(nsw )?}}i32 %exp, 5 - // CHECK: %{{[^ ]+}} = shl nuw {{(nsw )?}}i32 1, %{{[^ ]+}} - // CHECK: %{{[^ ]+}} = select i1 {{[^ ]+}}, i32 0, i32 %{{[^ ]+}} - // CHECK: ret i32 %{{[^ ]+}} - 32i32.pow(exp) -} -// note: d and e are expected to yield the same IR From c9c049b2b42f4c05ec49fd1c9125fa4333badd3f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 12 Jan 2024 17:12:45 +1100 Subject: [PATCH 202/246] coverage: Use normal `edition:` headers in coverage tests Some of these tests were originally written as part of a custom `run-make` test, so at that time they weren't able to use the normal compiletest header directive parser. Now that they're properly integrated, there's no need for them to use `compile-flags` to specify the edition, since they can use `edition` instead. --- tests/coverage/bad_counter_ids.cov-map | 32 ++++++++++++------------- tests/coverage/bad_counter_ids.coverage | 3 ++- tests/coverage/bad_counter_ids.rs | 3 ++- tests/coverage/closure_macro.coverage | 2 +- tests/coverage/closure_macro.rs | 2 +- tests/coverage/fn_sig_into_try.coverage | 2 +- tests/coverage/fn_sig_into_try.rs | 2 +- tests/coverage/issue-93054.cov-map | 12 +++++----- tests/coverage/issue-93054.coverage | 3 +-- tests/coverage/issue-93054.rs | 3 +-- tests/coverage/long_and_wide.coverage | 2 +- tests/coverage/long_and_wide.rs | 2 +- tests/coverage/sort_groups.coverage | 2 +- tests/coverage/sort_groups.rs | 2 +- tests/coverage/trivial.coverage | 2 +- tests/coverage/trivial.rs | 2 +- tests/coverage/unreachable.coverage | 2 +- tests/coverage/unreachable.rs | 2 +- 18 files changed, 40 insertions(+), 40 deletions(-) diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map index 3b51e3ef9de66..7eff7f5f02f3c 100644 --- a/tests/coverage/bad_counter_ids.cov-map +++ b/tests/coverage/bad_counter_ids.cov-map @@ -1,81 +1,81 @@ Function name: bad_counter_ids::eq_bad -Raw bytes (14): 0x[01, 01, 00, 02, 01, 23, 01, 02, 1f, 00, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 1f, 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 + 35, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 31) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) Function name: bad_counter_ids::eq_bad_message -Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 28, 01, 02, 0f, 02, 02, 20, 00, 2b, 00, 01, 01, 00, 02] +Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 29, 01, 02, 0f, 02, 02, 20, 00, 2b, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Zero Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 40, 1) to (start + 2, 15) +- Code(Counter(0)) at (prev + 41, 1) to (start + 2, 15) - Code(Expression(0, Sub)) at (prev + 2, 32) to (start + 0, 43) = (c0 - Zero) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Function name: bad_counter_ids::eq_good -Raw bytes (14): 0x[01, 01, 00, 02, 01, 0f, 01, 02, 1f, 05, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 1f, 05, 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 + 15, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 31) - Code(Counter(1)) at (prev + 3, 1) to (start + 0, 2) Function name: bad_counter_ids::eq_good_message -Raw bytes (19): 0x[01, 01, 00, 03, 01, 14, 01, 02, 0f, 00, 02, 20, 00, 2b, 05, 01, 01, 00, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 15, 01, 02, 0f, 00, 02, 20, 00, 2b, 05, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 20, 1) to (start + 2, 15) +- Code(Counter(0)) at (prev + 21, 1) to (start + 2, 15) - Code(Zero) at (prev + 2, 32) to (start + 0, 43) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) Function name: bad_counter_ids::ne_bad -Raw bytes (14): 0x[01, 01, 00, 02, 01, 2d, 01, 02, 1f, 00, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 1f, 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 + 45, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 31) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) Function name: bad_counter_ids::ne_bad_message -Raw bytes (19): 0x[01, 01, 00, 03, 01, 32, 01, 02, 0f, 05, 02, 20, 00, 2b, 00, 01, 01, 00, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 33, 01, 02, 0f, 05, 02, 20, 00, 2b, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 50, 1) to (start + 2, 15) +- Code(Counter(0)) at (prev + 51, 1) to (start + 2, 15) - Code(Counter(1)) at (prev + 2, 32) to (start + 0, 43) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Function name: bad_counter_ids::ne_good -Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 19, 01, 02, 1f, 02, 03, 01, 00, 02] +Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 1a, 01, 02, 1f, 02, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Zero Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 25, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 31) - Code(Expression(0, Sub)) at (prev + 3, 1) to (start + 0, 2) = (c0 - Zero) Function name: bad_counter_ids::ne_good_message -Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 1e, 01, 02, 0f, 00, 02, 20, 00, 2b, 02, 01, 01, 00, 02] +Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 1f, 01, 02, 0f, 00, 02, 20, 00, 2b, 02, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Zero Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 15) +- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 15) - Code(Zero) at (prev + 2, 32) to (start + 0, 43) - Code(Expression(0, Sub)) at (prev + 1, 1) to (start + 0, 2) = (c0 - Zero) diff --git a/tests/coverage/bad_counter_ids.coverage b/tests/coverage/bad_counter_ids.coverage index 5474ec2f78552..39e6cae11ddac 100644 --- a/tests/coverage/bad_counter_ids.coverage +++ b/tests/coverage/bad_counter_ids.coverage @@ -1,5 +1,6 @@ LL| |#![feature(coverage_attribute)] - LL| |// compile-flags: --edition=2021 -Copt-level=0 -Zmir-opt-level=3 + LL| |// edition: 2021 + LL| |// compile-flags: -Copt-level=0 -Zmir-opt-level=3 LL| | LL| |// Regression test for . LL| |// diff --git a/tests/coverage/bad_counter_ids.rs b/tests/coverage/bad_counter_ids.rs index ef5460102b70c..e22b96468abd3 100644 --- a/tests/coverage/bad_counter_ids.rs +++ b/tests/coverage/bad_counter_ids.rs @@ -1,5 +1,6 @@ #![feature(coverage_attribute)] -// compile-flags: --edition=2021 -Copt-level=0 -Zmir-opt-level=3 +// edition: 2021 +// compile-flags: -Copt-level=0 -Zmir-opt-level=3 // Regression test for . // diff --git a/tests/coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage index a6eeb79a71c8f..ab152a91356a0 100644 --- a/tests/coverage/closure_macro.coverage +++ b/tests/coverage/closure_macro.coverage @@ -1,5 +1,5 @@ - LL| |// compile-flags: --edition=2018 LL| |#![feature(coverage_attribute)] + LL| |// edition: 2018 LL| | LL| |macro_rules! bail { LL| | ($msg:literal $(,)?) => { diff --git a/tests/coverage/closure_macro.rs b/tests/coverage/closure_macro.rs index c3ef916788091..38a81ea434b9b 100644 --- a/tests/coverage/closure_macro.rs +++ b/tests/coverage/closure_macro.rs @@ -1,5 +1,5 @@ -// compile-flags: --edition=2018 #![feature(coverage_attribute)] +// edition: 2018 macro_rules! bail { ($msg:literal $(,)?) => { diff --git a/tests/coverage/fn_sig_into_try.coverage b/tests/coverage/fn_sig_into_try.coverage index 71e15fc11eb8a..aac5c9d9a94ee 100644 --- a/tests/coverage/fn_sig_into_try.coverage +++ b/tests/coverage/fn_sig_into_try.coverage @@ -1,5 +1,5 @@ LL| |#![feature(coverage_attribute)] - LL| |// compile-flags: --edition=2021 + LL| |// edition: 2021 LL| | LL| |// Regression test for inconsistent handling of function signature spans that LL| |// are followed by code using the `?` operator. diff --git a/tests/coverage/fn_sig_into_try.rs b/tests/coverage/fn_sig_into_try.rs index 1f4cc67af8386..5d8e7929ef975 100644 --- a/tests/coverage/fn_sig_into_try.rs +++ b/tests/coverage/fn_sig_into_try.rs @@ -1,5 +1,5 @@ #![feature(coverage_attribute)] -// compile-flags: --edition=2021 +// edition: 2021 // Regression test for inconsistent handling of function signature spans that // are followed by code using the `?` operator. diff --git a/tests/coverage/issue-93054.cov-map b/tests/coverage/issue-93054.cov-map index c2c6e9a651673..024ef519fcffe 100644 --- a/tests/coverage/issue-93054.cov-map +++ b/tests/coverage/issue-93054.cov-map @@ -1,24 +1,24 @@ Function name: issue_93054::foo2 (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 00, 1d] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 00, 1d] 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 + 0, 29) +- Code(Zero) at (prev + 21, 1) to (start + 0, 29) Function name: issue_93054::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 00, 0d] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 00, 0d] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 30, 1) to (start + 0, 13) +- Code(Counter(0)) at (prev + 29, 1) to (start + 0, 13) Function name: issue_93054::make (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 26, 1) to (start + 2, 2) +- Code(Zero) at (prev + 25, 1) to (start + 2, 2) diff --git a/tests/coverage/issue-93054.coverage b/tests/coverage/issue-93054.coverage index 15f225326a427..6ae8ffb5cb4f2 100644 --- a/tests/coverage/issue-93054.coverage +++ b/tests/coverage/issue-93054.coverage @@ -1,11 +1,10 @@ LL| |#![allow(dead_code, unreachable_code)] + LL| |// edition: 2021 LL| | LL| |// Regression test for #93054: Functions using uninhabited types often only have a single, LL| |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail. LL| |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them. LL| | - LL| |// compile-flags: --edition=2021 - LL| | LL| |enum Never {} LL| | LL| |impl Never { diff --git a/tests/coverage/issue-93054.rs b/tests/coverage/issue-93054.rs index da546cfeef854..f16fc1e423962 100644 --- a/tests/coverage/issue-93054.rs +++ b/tests/coverage/issue-93054.rs @@ -1,11 +1,10 @@ #![allow(dead_code, unreachable_code)] +// edition: 2021 // Regression test for #93054: Functions using uninhabited types often only have a single, // unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail. // Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them. -// compile-flags: --edition=2021 - enum Never {} impl Never { diff --git a/tests/coverage/long_and_wide.coverage b/tests/coverage/long_and_wide.coverage index d7d29ca40cddd..cf4dd2811406c 100644 --- a/tests/coverage/long_and_wide.coverage +++ b/tests/coverage/long_and_wide.coverage @@ -1,4 +1,4 @@ - LL| |// compile-flags: --edition=2021 + LL| |// edition: 2021 LL| |// ignore-tidy-linelength LL| | LL| |// This file deliberately contains line and column numbers larger than 127, diff --git a/tests/coverage/long_and_wide.rs b/tests/coverage/long_and_wide.rs index a7cbcd4802791..87f2207bd7e67 100644 --- a/tests/coverage/long_and_wide.rs +++ b/tests/coverage/long_and_wide.rs @@ -1,4 +1,4 @@ -// compile-flags: --edition=2021 +// edition: 2021 // ignore-tidy-linelength // This file deliberately contains line and column numbers larger than 127, diff --git a/tests/coverage/sort_groups.coverage b/tests/coverage/sort_groups.coverage index c70d7b3b28253..77cbb09c74a73 100644 --- a/tests/coverage/sort_groups.coverage +++ b/tests/coverage/sort_groups.coverage @@ -1,4 +1,4 @@ - LL| |// compile-flags: --edition=2021 + LL| |// edition: 2021 LL| | LL| |// Demonstrate that `sort_subviews.py` can sort instantiation groups into a LL| |// predictable order, while preserving their heterogeneous contents. diff --git a/tests/coverage/sort_groups.rs b/tests/coverage/sort_groups.rs index 5adbbc6a87d1f..17fd862ca2cad 100644 --- a/tests/coverage/sort_groups.rs +++ b/tests/coverage/sort_groups.rs @@ -1,4 +1,4 @@ -// compile-flags: --edition=2021 +// edition: 2021 // Demonstrate that `sort_subviews.py` can sort instantiation groups into a // predictable order, while preserving their heterogeneous contents. diff --git a/tests/coverage/trivial.coverage b/tests/coverage/trivial.coverage index 4f417979ef97d..af4be7b8f3356 100644 --- a/tests/coverage/trivial.coverage +++ b/tests/coverage/trivial.coverage @@ -1,4 +1,4 @@ - LL| |// compile-flags: --edition=2021 + LL| |// edition: 2021 LL| | LL| 1|fn main() {} diff --git a/tests/coverage/trivial.rs b/tests/coverage/trivial.rs index d0a9b44fb3605..782472739a002 100644 --- a/tests/coverage/trivial.rs +++ b/tests/coverage/trivial.rs @@ -1,3 +1,3 @@ -// compile-flags: --edition=2021 +// edition: 2021 fn main() {} diff --git a/tests/coverage/unreachable.coverage b/tests/coverage/unreachable.coverage index 7015bb90aa38d..a58765f688be5 100644 --- a/tests/coverage/unreachable.coverage +++ b/tests/coverage/unreachable.coverage @@ -1,6 +1,6 @@ LL| |#![feature(core_intrinsics)] LL| |#![feature(coverage_attribute)] - LL| |// compile-flags: --edition=2021 + LL| |// edition: 2021 LL| | LL| |// LL| |// If we instrument a function for coverage, but all of its counter-increment diff --git a/tests/coverage/unreachable.rs b/tests/coverage/unreachable.rs index 6385bfa160d7d..6d0c7b3ca8db5 100644 --- a/tests/coverage/unreachable.rs +++ b/tests/coverage/unreachable.rs @@ -1,6 +1,6 @@ #![feature(core_intrinsics)] #![feature(coverage_attribute)] -// compile-flags: --edition=2021 +// edition: 2021 // // If we instrument a function for coverage, but all of its counter-increment From 3f7b1a5f491a66365e9973babc1b3dde2c90ad55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 1 Feb 2024 17:59:36 +0100 Subject: [PATCH 203/246] Clean up some things in the name resolver * Get rid of a typo in a function name * Rename `currently_processing_generics`: The old name confused me at first since I assumed it referred to generic *parameters* when it was in fact referring to generic *arguments*. Generics are typically short for generic params. * Get rid of a few unwraps by properly leveraging slice patterns --- compiler/rustc_resolve/src/late.rs | 12 ++++++------ compiler/rustc_resolve/src/late/diagnostics.rs | 16 +++++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9788fcb3c7d36..1f2803d4368ae 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -594,9 +594,9 @@ struct DiagnosticMetadata<'ast> { /// The current trait (used to suggest). current_item: Option<&'ast Item>, - /// When processing generics and encountering a type not found, suggest introducing a type - /// param. - currently_processing_generics: bool, + /// When processing generic arguments and encountering an unresolved ident not found, + /// suggest introducing a type or const param depending on the context. + currently_processing_generic_args: bool, /// The current enclosing (non-closure) function (used for better errors). current_function: Option<(FnKind<'ast>, Span)>, @@ -1069,7 +1069,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, fn visit_generic_arg(&mut self, arg: &'ast GenericArg) { debug!("visit_generic_arg({:?})", arg); - let prev = replace(&mut self.diagnostic_metadata.currently_processing_generics, true); + let prev = replace(&mut self.diagnostic_metadata.currently_processing_generic_args, true); match arg { GenericArg::Type(ref ty) => { // We parse const arguments as path types as we cannot distinguish them during @@ -1100,7 +1100,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, }, ); - self.diagnostic_metadata.currently_processing_generics = prev; + self.diagnostic_metadata.currently_processing_generic_args = prev; return; } } @@ -1113,7 +1113,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No)) } } - self.diagnostic_metadata.currently_processing_generics = prev; + self.diagnostic_metadata.currently_processing_generic_args = prev; } fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a4c041f1ff247..64e2b6a497151 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -452,7 +452,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } self.suggest_self_or_self_ref(&mut err, path, span); - self.detect_assoct_type_constraint_meant_as_path(&mut err, &base_error); + self.detect_assoc_type_constraint_meant_as_path(&mut err, &base_error); if self.suggest_self_ty(&mut err, source, path, span) || self.suggest_self_value(&mut err, source, path, span) { @@ -491,7 +491,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { (err, candidates) } - fn detect_assoct_type_constraint_meant_as_path( + fn detect_assoc_type_constraint_meant_as_path( &self, err: &mut Diagnostic, base_error: &BaseError, @@ -799,7 +799,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { false, ) = (source, res, is_macro) { - if let Some(bounds @ [_, .., _]) = self.diagnostic_metadata.current_trait_object { + if let Some(bounds @ [first_bound, .., last_bound]) = + self.diagnostic_metadata.current_trait_object + { fallback = true; let spans: Vec = bounds .iter() @@ -807,9 +809,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { .filter(|&sp| sp != base_error.span) .collect(); - let start_span = bounds[0].span(); + let start_span = first_bound.span(); // `end_span` is the end of the poly trait ref (Foo + 'baz + Bar><) - let end_span = bounds.last().unwrap().span(); + let end_span = last_bound.span(); // `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar) let last_bound_span = spans.last().cloned().unwrap(); let mut multi_span: MultiSpan = spans.clone().into(); @@ -2419,10 +2421,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let mut iter = ident.chars().map(|c| c.is_uppercase()); let single_uppercase_char = matches!(iter.next(), Some(true)) && matches!(iter.next(), None); - if !self.diagnostic_metadata.currently_processing_generics && !single_uppercase_char { + if !self.diagnostic_metadata.currently_processing_generic_args && !single_uppercase_char { return None; } - match (self.diagnostic_metadata.current_item, single_uppercase_char, self.diagnostic_metadata.currently_processing_generics) { + match (self.diagnostic_metadata.current_item, single_uppercase_char, self.diagnostic_metadata.currently_processing_generic_args) { (Some(Item { kind: ItemKind::Fn(..), ident, .. }), _, _) if ident.name == sym::main => { // Ignore `fn main()` as we don't want to suggest `fn main()` } From 5906237b32a83a1df215b87bbafcc926bf49cd66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 2 Feb 2024 02:49:13 +0100 Subject: [PATCH 204/246] Suggest changing ty to const params if appropriate --- compiler/rustc_resolve/messages.ftl | 3 ++ compiler/rustc_resolve/src/errors.rs | 15 +++++- .../rustc_resolve/src/late/diagnostics.rs | 50 +++++++++++++++++++ .../change-ty-to-const-param-sugg-0.rs | 10 ++++ .../change-ty-to-const-param-sugg-0.stderr | 34 +++++++++++++ .../change-ty-to-const-param-sugg-1.rs | 24 +++++++++ .../change-ty-to-const-param-sugg-1.stderr | 25 ++++++++++ 7 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 tests/ui/resolve/change-ty-to-const-param-sugg-0.rs create mode 100644 tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr create mode 100644 tests/ui/resolve/change-ty-to-const-param-sugg-1.rs create mode 100644 tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index c8ec10cad17c4..02847a0f5f914 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -289,6 +289,9 @@ resolve_underscore_lifetime_name_cannot_be_used_here = `'_` cannot be used here .note = `'_` is a reserved lifetime name +resolve_unexpected_res_change_ty_to_const_param_sugg = + you might have meant to write a const parameter here + resolve_unreachable_label = use of unreachable label `{$name}` .label = unreachable label `{$name}` diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 50ff09feb4d9b..655fc9812d747 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::codes::*; +use rustc_errors::{codes::*, Applicability}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{ symbol::{Ident, Symbol}, @@ -787,3 +787,16 @@ pub(crate) struct IsNotDirectlyImportable { pub(crate) span: Span, pub(crate) target: Ident, } + +#[derive(Subdiagnostic)] +#[suggestion( + resolve_unexpected_res_change_ty_to_const_param_sugg, + code = "const ", + style = "verbose" +)] +pub(crate) struct UnexpectedResChangeTyToConstParamSugg { + #[primary_span] + pub span: Span, + #[applicability] + pub applicability: Applicability, +} diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 64e2b6a497151..9f810741f4907 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -444,6 +444,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } self.suggest_bare_struct_literal(&mut err); + self.suggest_changing_type_to_const_param(&mut err, res, source, span); if self.suggest_pattern_match_with_let(&mut err, source, span) { // Fallback label. @@ -1138,6 +1139,55 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } + fn suggest_changing_type_to_const_param( + &mut self, + err: &mut Diagnostic, + res: Option, + source: PathSource<'_>, + span: Span, + ) { + let PathSource::Trait(_) = source else { return }; + + // We don't include `DefKind::Str` and `DefKind::AssocTy` as they can't be reached here anyway. + let applicability = match res { + Some(Res::PrimTy(PrimTy::Int(_) | PrimTy::Uint(_) | PrimTy::Bool | PrimTy::Char)) => { + Applicability::MachineApplicable + } + // FIXME(const_generics): Add `DefKind::TyParam` and `SelfTyParam` once we support generic + // const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the + // benefits of including them here outweighs the small number of false positives. + Some(Res::Def(DefKind::Struct | DefKind::Enum, _)) + if self.r.tcx.features().adt_const_params => + { + Applicability::MaybeIncorrect + } + _ => return, + }; + + let Some(item) = self.diagnostic_metadata.current_item else { return }; + let Some(generics) = item.kind.generics() else { return }; + + let param = generics.params.iter().find_map(|param| { + // Only consider type params with exactly one trait bound. + if let [bound] = &*param.bounds + && let ast::GenericBound::Trait(tref, ast::TraitBoundModifiers::NONE) = bound + && tref.span == span + && param.ident.span.eq_ctxt(span) + { + Some(param.ident.span) + } else { + None + } + }); + + if let Some(param) = param { + err.subdiagnostic(errors::UnexpectedResChangeTyToConstParamSugg { + span: param.shrink_to_lo(), + applicability, + }); + } + } + fn suggest_pattern_match_with_let( &mut self, err: &mut Diagnostic, diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-0.rs b/tests/ui/resolve/change-ty-to-const-param-sugg-0.rs new file mode 100644 index 0000000000000..36fe16f64ebeb --- /dev/null +++ b/tests/ui/resolve/change-ty-to-const-param-sugg-0.rs @@ -0,0 +1,10 @@ +fn make() {} +//~^ ERROR expected trait, found builtin type `u32` +//~| HELP you might have meant to write a const parameter here + +struct Array([bool; N]); +//~^ ERROR expected trait, found builtin type `usize` +//~| HELP you might have meant to write a const parameter here +//~| ERROR expected value, found type parameter `N` + +fn main() {} diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr b/tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr new file mode 100644 index 0000000000000..4e411eae3cbbb --- /dev/null +++ b/tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr @@ -0,0 +1,34 @@ +error[E0404]: expected trait, found builtin type `u32` + --> $DIR/change-ty-to-const-param-sugg-0.rs:1:12 + | +LL | fn make() {} + | ^^^ not a trait + | +help: you might have meant to write a const parameter here + | +LL | fn make() {} + | +++++ + +error[E0404]: expected trait, found builtin type `usize` + --> $DIR/change-ty-to-const-param-sugg-0.rs:5:17 + | +LL | struct Array([bool; N]); + | ^^^^^ not a trait + | +help: you might have meant to write a const parameter here + | +LL | struct Array([bool; N]); + | +++++ + +error[E0423]: expected value, found type parameter `N` + --> $DIR/change-ty-to-const-param-sugg-0.rs:5:31 + | +LL | struct Array([bool; N]); + | - ^ not a value + | | + | found this type parameter + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0404, E0423. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-1.rs b/tests/ui/resolve/change-ty-to-const-param-sugg-1.rs new file mode 100644 index 0000000000000..b1d2595f3790f --- /dev/null +++ b/tests/ui/resolve/change-ty-to-const-param-sugg-1.rs @@ -0,0 +1,24 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +use std::marker::ConstParamTy; + +struct Tagged; +//~^ ERROR expected trait, found enum `Tag` +//~| HELP you might have meant to write a const parameter here +//~| ERROR expected trait, found struct `Options` +//~| HELP you might have meant to write a const parameter here + +#[derive(PartialEq, Eq, ConstParamTy)] +enum Tag { + One, + Two, +} + +#[derive(PartialEq, Eq, ConstParamTy)] +struct Options { + verbose: bool, + safe: bool, +} + +fn main() {} diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr b/tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr new file mode 100644 index 0000000000000..933fac27f8f4e --- /dev/null +++ b/tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr @@ -0,0 +1,25 @@ +error[E0404]: expected trait, found enum `Tag` + --> $DIR/change-ty-to-const-param-sugg-1.rs:6:18 + | +LL | struct Tagged; + | ^^^ not a trait + | +help: you might have meant to write a const parameter here + | +LL | struct Tagged; + | +++++ + +error[E0404]: expected trait, found struct `Options` + --> $DIR/change-ty-to-const-param-sugg-1.rs:6:26 + | +LL | struct Tagged; + | ^^^^^^^ not a trait + | +help: you might have meant to write a const parameter here + | +LL | struct Tagged; + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0404`. From f066be5f2932e791cb766fdf18e9c1fc0d985451 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Feb 2024 13:02:55 +1100 Subject: [PATCH 205/246] Rename `buffer_non_error_diag` as `buffer_non_error`. To match `buffer_error`. --- .../rustc_borrowck/src/diagnostics/outlives_suggestion.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 6 +++--- compiler/rustc_borrowck/src/nll.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index ad66c677c78f5..bac1d9dd57f6b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -251,6 +251,6 @@ impl OutlivesSuggestionBuilder { diag.sort_span = mir_span.shrink_to_hi(); // Buffer the diagnostic - mbcx.buffer_non_error_diag(diag); + mbcx.buffer_non_error(diag); } } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index ea48e78509b7c..bcd30b3624eb1 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2435,7 +2435,7 @@ mod error { self.buffered.push(t.into_diagnostic()); } - pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) { + pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'_, ()>) { self.buffered.push(t.into_diagnostic()); } @@ -2449,8 +2449,8 @@ mod error { self.errors.buffer_error(t); } - pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) { - self.errors.buffer_non_error_diag(t); + pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'_, ()>) { + self.errors.buffer_non_error(t); } pub fn buffer_move_error( diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index cc8208e9dc306..f4864986e2811 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -310,7 +310,7 @@ pub(super) fn dump_annotation<'tcx>( err.note(format!("Inferred opaque type values:\n{opaque_type_values:#?}")); } - errors.buffer_non_error_diag(err); + errors.buffer_non_error(err); } fn for_each_region_constraint<'tcx>( From 3a02ebcac27fd730ba89cf1565400d516f296815 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Feb 2024 09:05:53 +1100 Subject: [PATCH 206/246] Remove `BorrowckErrors::set_tainted_by_errors`. It has no effect. Note that `infcx.set_tainted_by_errors()` is still called, so taintedness is still being propagated. --- compiler/rustc_borrowck/src/lib.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index bcd30b3624eb1..c5a87437003c7 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -178,7 +178,6 @@ fn do_mir_borrowck<'tcx>( // Gather the upvars of a closure, if any. if let Some(e) = input_body.tainted_by_errors { infcx.set_tainted_by_errors(e); - errors.set_tainted_by_errors(e); } // Replace all regions with fresh inference variables. This @@ -2438,10 +2437,6 @@ mod error { pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'_, ()>) { self.buffered.push(t.into_diagnostic()); } - - pub fn set_tainted_by_errors(&mut self, e: ErrorGuaranteed) { - self.tainted_by_errors = Some(e); - } } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { From ee8703315e1e38f759206d916b6ccf2c76c5882a Mon Sep 17 00:00:00 2001 From: Aphek Date: Thu, 1 Feb 2024 23:58:42 -0300 Subject: [PATCH 207/246] Update libc to 0.2.153 --- Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 25f4959bf141f..8a2c6536d08c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2169,9 +2169,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 5b32bc5117c0c..20f4310603a05 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -libc = { version = "0.2.150", default-features = false, features = ['rustc-dep-of-std'], public = true } +libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true } compiler_builtins = { version = "0.1.105" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } From 5fd824de449575d3de21f3a6a25104d708665664 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Feb 2024 13:04:07 +1100 Subject: [PATCH 208/246] Remove `BorrowckErrors::tainted_by_errors`. `BorrowckErrors` stores a mix of error and non-error diags in `buffered`. As a result, it downgrades `DiagnosticBuilder`s to `Diagnostic`s, losing the emission guarantees, and so has to use a `tainted_by_errors` field to record whether an error has occurred. This commit splits `buffered` into `buffered_errors` and `buffered_non_errors`, keeping them as `DiagnosticBuilder`s and preserving the emission guarantees. This also requires fixing a bunch of incorrect lifetimes on `DiagnosticBuilder` use points. --- .../rustc_borrowck/src/borrowck_errors.rs | 16 ++-- .../src/diagnostics/conflict_errors.rs | 20 ++--- .../src/diagnostics/move_errors.rs | 4 +- compiler/rustc_borrowck/src/lib.rs | 85 ++++++++++--------- 4 files changed, 66 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 8a275a8363010..6cbcda37f50b8 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -130,7 +130,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { noun_old: &str, old_opt_via: &str, previous_end_span: Option, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_code_err!( self.dcx(), new_loan_span, @@ -162,7 +162,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { old_opt_via: &str, previous_end_span: Option, second_borrow_desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_code_err!( self.dcx(), new_loan_span, @@ -194,7 +194,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { kind_old: &str, msg_old: &str, old_load_end_span: Option, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") }; let mut err = struct_span_code_err!( self.dcx(), @@ -235,7 +235,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, borrow_span: Span, desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { struct_span_code_err!( self.dcx(), span, @@ -252,7 +252,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, desc: &str, is_arg: bool, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" }; struct_span_code_err!(self.dcx(), span, E0384, "cannot assign {} {}", msg, desc) } @@ -265,7 +265,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, move_from_span: Span, move_from_desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { struct_span_code_err!( self.dcx(), move_from_span, @@ -283,7 +283,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { move_from_span: Span, ty: Ty<'_>, is_index: Option, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let type_name = match (&ty.kind(), is_index) { (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", (&ty::Slice(_), _) => "slice", @@ -304,7 +304,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, move_from_span: Span, container_ty: Ty<'_>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { struct_span_code_err!( self.dcx(), move_from_span, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2e83072b8d132..da5e189024a9b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -327,7 +327,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, mpi: MovePathIndex, move_span: Span, - err: &mut DiagnosticBuilder<'_>, + err: &mut DiagnosticBuilder<'tcx>, in_pattern: &mut bool, move_spans: UseSpans<'_>, ) { @@ -486,7 +486,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { desired_action: InitializationRequiringAction, span: Span, use_spans: UseSpans<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { // We need all statements in the body where the binding was assigned to later find all // the branching code paths where the binding *wasn't* assigned to. let inits = &self.move_data.init_path_map[mpi]; @@ -880,7 +880,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, (place, _span): (Place<'tcx>, Span), borrow: &BorrowData<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_span = borrow_spans.args_or_use(); @@ -930,7 +930,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (place, span): (Place<'tcx>, Span), gen_borrow_kind: BorrowKind, issued_borrow: &BorrowData<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let issued_spans = self.retrieve_borrow_spans(issued_borrow); let issued_span = issued_spans.args_or_use(); @@ -2129,7 +2129,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { drop_span: Span, borrow_spans: UseSpans<'tcx>, explanation: BorrowExplanation<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { debug!( "report_local_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}, {:?}\ @@ -2304,7 +2304,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, drop_span: Span, borrow_span: Span, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { debug!( "report_thread_local_value_does_not_live_long_enough(\ {:?}, {:?}\ @@ -2329,7 +2329,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_spans: UseSpans<'tcx>, proper_span: Span, explanation: BorrowExplanation<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } = explanation { @@ -2496,7 +2496,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return_span: Span, category: ConstraintCategory<'tcx>, opt_place_desc: Option<&String>, - ) -> Option> { + ) -> Option> { let return_kind = match category { ConstraintCategory::Return(_) => "return", ConstraintCategory::Yield => "yield", @@ -2591,7 +2591,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { constraint_span: Span, captured_var: &str, scope: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let tcx = self.infcx.tcx; let args_span = use_span.args_or_use(); @@ -2699,7 +2699,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { upvar_span: Span, upvar_name: Symbol, escape_span: Span, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let tcx = self.infcx.tcx; let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id()); diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index fb3525e8998c0..0a0bb75a2a3a6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -288,7 +288,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { &mut self, place: Place<'tcx>, span: Span, - ) -> DiagnosticBuilder<'a> { + ) -> DiagnosticBuilder<'tcx> { let description = if place.projection.len() == 1 { format!("static item {}", self.describe_any_place(place.as_ref())) } else { @@ -310,7 +310,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { deref_target_place: Place<'tcx>, span: Span, use_spans: Option>, - ) -> DiagnosticBuilder<'a> { + ) -> DiagnosticBuilder<'tcx> { // Inspect the type of the content behind the // borrow to provide feedback about why this // was a move rather than a copy. diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index c5a87437003c7..e3b03717cc87f 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -19,7 +19,7 @@ extern crate tracing; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::dominators::Dominators; -use rustc_errors::{Diagnostic, DiagnosticBuilder}; +use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::{BitSet, ChunkedBitSet}; @@ -173,7 +173,7 @@ fn do_mir_borrowck<'tcx>( } } - let mut errors = error::BorrowckErrors::new(infcx.tcx); + let mut errors = error::BorrowckErrors::new(); // Gather the upvars of a closure, if any. if let Some(e) = input_body.tainted_by_errors { @@ -2124,7 +2124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | WriteKind::MutableBorrow(BorrowKind::Fake), ) => { if self.is_mutable(place.as_ref(), is_local_mutation_allowed).is_err() - && !self.has_buffered_errors() + && !self.has_buffered_diags() { // rust-lang/rust#46908: In pure NLL mode this code path should be // unreachable, but we use `span_delayed_bug` because we can hit this when @@ -2387,12 +2387,25 @@ mod error { use super::*; + enum BufferedDiag<'tcx> { + Error(DiagnosticBuilder<'tcx>), + NonError(DiagnosticBuilder<'tcx, ()>), + } + + impl<'tcx> BufferedDiag<'tcx> { + fn sort_span(&self) -> Span { + match self { + BufferedDiag::Error(diag) => diag.sort_span, + BufferedDiag::NonError(diag) => diag.sort_span, + } + } + } + pub struct BorrowckErrors<'tcx> { - tcx: TyCtxt<'tcx>, /// This field keeps track of move errors that are to be reported for given move indices. /// - /// There are situations where many errors can be reported for a single move out (see #53807) - /// and we want only the best of those errors. + /// There are situations where many errors can be reported for a single move out (see + /// #53807) and we want only the best of those errors. /// /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of @@ -2405,46 +2418,37 @@ mod error { /// same primary span come out in a consistent order. buffered_move_errors: BTreeMap, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>, + buffered_mut_errors: FxIndexMap, usize)>, - /// Buffer of diagnostics to be reported. Uses `Diagnostic` rather than `DiagnosticBuilder` - /// because it has a mixture of error diagnostics and non-error diagnostics. - buffered: Vec, - /// Set to Some if we emit an error during borrowck - tainted_by_errors: Option, + + /// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics. + buffered_diags: Vec>, } impl<'tcx> BorrowckErrors<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Self { + pub fn new() -> Self { BorrowckErrors { - tcx, buffered_move_errors: BTreeMap::new(), buffered_mut_errors: Default::default(), - buffered: Default::default(), - tainted_by_errors: None, + buffered_diags: Default::default(), } } - pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) { - if let None = self.tainted_by_errors { - self.tainted_by_errors = Some(self.tcx.dcx().span_delayed_bug( - t.span.clone_ignoring_labels(), - "diagnostic buffered but not emitted", - )) - } - self.buffered.push(t.into_diagnostic()); + pub fn buffer_error(&mut self, t: DiagnosticBuilder<'tcx>) { + self.buffered_diags.push(BufferedDiag::Error(t)); } - pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'_, ()>) { - self.buffered.push(t.into_diagnostic()); + pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'tcx, ()>) { + self.buffered_diags.push(BufferedDiag::NonError(t)); } } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { - pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) { + pub fn buffer_error(&mut self, t: DiagnosticBuilder<'tcx>) { self.errors.buffer_error(t); } - pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'_, ()>) { + pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'tcx, ()>) { self.errors.buffer_non_error(t); } @@ -2476,38 +2480,41 @@ mod error { } pub fn emit_errors(&mut self) -> Option { + let mut res = None; + // Buffer any move errors that we collected and de-duplicated. for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) { // We have already set tainted for this error, so just buffer it. - self.errors.buffered.push(diag.into_diagnostic()); + self.errors.buffered_diags.push(BufferedDiag::Error(diag)); } for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) { if count > 10 { diag.note(format!("...and {} other attempted mutable borrows", count - 10)); } - self.errors.buffered.push(diag.into_diagnostic()); + self.errors.buffered_diags.push(BufferedDiag::Error(diag)); } - if !self.errors.buffered.is_empty() { - self.errors.buffered.sort_by_key(|diag| diag.sort_span); - - let dcx = self.dcx(); - for diag in self.errors.buffered.drain(..) { - dcx.emit_diagnostic(diag); + if !self.errors.buffered_diags.is_empty() { + self.errors.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span()); + for buffered_diag in self.errors.buffered_diags.drain(..) { + match buffered_diag { + BufferedDiag::Error(diag) => res = Some(diag.emit()), + BufferedDiag::NonError(diag) => diag.emit(), + } } } - self.errors.tainted_by_errors + res } - pub fn has_buffered_errors(&self) -> bool { - self.errors.buffered.is_empty() + pub(crate) fn has_buffered_diags(&self) -> bool { + self.errors.buffered_diags.is_empty() } pub fn has_move_error( &self, move_out_indices: &[MoveOutIndex], - ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx>)> { + ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)> { self.errors.buffered_move_errors.get(move_out_indices) } } From 2e6bea59688ae65ca7c94ec4f31eb969ac8a9a6e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Feb 2024 13:05:00 +1100 Subject: [PATCH 209/246] Inline and remove `DiagnosticBuilder::into_diagnostic`. It now has a single call site. --- compiler/rustc_errors/src/diagnostic_builder.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 8bfb181648628..faff7f0b52673 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -255,13 +255,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Stashes diagnostic for possible later improvement in a different, /// later stage of the compiler. The diagnostic can be accessed with /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`]. - pub fn stash(self, span: Span, key: StashKey) { - self.dcx.stash_diagnostic(span, key, self.into_diagnostic()); - } - - /// Converts the builder to a `Diagnostic` for later emission. - pub fn into_diagnostic(mut self) -> Diagnostic { - self.take_diag() + pub fn stash(mut self, span: Span, key: StashKey) { + self.dcx.stash_diagnostic(span, key, self.take_diag()); } /// Delay emission of this diagnostic as a bug. From b6a4f03306fb2d1965e5d71e5a6f99641a0655ee Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Feb 2024 14:27:34 +1100 Subject: [PATCH 210/246] Rename `BorrowckErrors` as `BorrowckDiags`. And some related things. Because it can hold non-error diagnostics. --- compiler/rustc_borrowck/src/lib.rs | 48 +++++++++++++++--------------- compiler/rustc_borrowck/src/nll.rs | 4 +-- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index e3b03717cc87f..8b5e548345c97 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -173,7 +173,7 @@ fn do_mir_borrowck<'tcx>( } } - let mut errors = error::BorrowckErrors::new(); + let mut diags = diags::BorrowckDiags::new(); // Gather the upvars of a closure, if any. if let Some(e) = input_body.tainted_by_errors { @@ -243,7 +243,7 @@ fn do_mir_borrowck<'tcx>( ®ioncx, &opt_closure_req, &opaque_type_values, - &mut errors, + &mut diags, ); // The various `flow_*` structures can be large. We drop `flow_inits` here @@ -304,11 +304,11 @@ fn do_mir_borrowck<'tcx>( next_region_name: RefCell::new(1), polonius_output: None, move_errors: Vec::new(), - errors, + diags, }; MoveVisitor { ctxt: &mut promoted_mbcx }.visit_body(promoted_body); promoted_mbcx.report_move_errors(); - errors = promoted_mbcx.errors; + diags = promoted_mbcx.diags; struct MoveVisitor<'a, 'cx, 'tcx> { ctxt: &'a mut MirBorrowckCtxt<'cx, 'tcx>, @@ -345,7 +345,7 @@ fn do_mir_borrowck<'tcx>( next_region_name: RefCell::new(1), polonius_output, move_errors: Vec::new(), - errors, + diags, }; // Compute and report region errors, if any. @@ -573,7 +573,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> { /// Results of Polonius analysis. polonius_output: Option>, - errors: error::BorrowckErrors<'tcx>, + diags: diags::BorrowckDiags<'tcx>, move_errors: Vec>, } @@ -2382,7 +2382,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } -mod error { +mod diags { use rustc_errors::ErrorGuaranteed; use super::*; @@ -2401,7 +2401,7 @@ mod error { } } - pub struct BorrowckErrors<'tcx> { + pub struct BorrowckDiags<'tcx> { /// This field keeps track of move errors that are to be reported for given move indices. /// /// There are situations where many errors can be reported for a single move out (see @@ -2425,9 +2425,9 @@ mod error { buffered_diags: Vec>, } - impl<'tcx> BorrowckErrors<'tcx> { + impl<'tcx> BorrowckDiags<'tcx> { pub fn new() -> Self { - BorrowckErrors { + BorrowckDiags { buffered_move_errors: BTreeMap::new(), buffered_mut_errors: Default::default(), buffered_diags: Default::default(), @@ -2445,11 +2445,11 @@ mod error { impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { pub fn buffer_error(&mut self, t: DiagnosticBuilder<'tcx>) { - self.errors.buffer_error(t); + self.diags.buffer_error(t); } pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'tcx, ()>) { - self.errors.buffer_non_error(t); + self.diags.buffer_non_error(t); } pub fn buffer_move_error( @@ -2458,7 +2458,7 @@ mod error { place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>), ) -> bool { if let Some((_, diag)) = - self.errors.buffered_move_errors.insert(move_out_indices, place_and_err) + self.diags.buffered_move_errors.insert(move_out_indices, place_and_err) { // Cancel the old diagnostic so we don't ICE diag.cancel(); @@ -2472,31 +2472,31 @@ mod error { &mut self, span: Span, ) -> Option<(DiagnosticBuilder<'tcx>, usize)> { - self.errors.buffered_mut_errors.remove(&span) + self.diags.buffered_mut_errors.remove(&span) } pub fn buffer_mut_error(&mut self, span: Span, t: DiagnosticBuilder<'tcx>, count: usize) { - self.errors.buffered_mut_errors.insert(span, (t, count)); + self.diags.buffered_mut_errors.insert(span, (t, count)); } pub fn emit_errors(&mut self) -> Option { let mut res = None; // Buffer any move errors that we collected and de-duplicated. - for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) { + for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) { // We have already set tainted for this error, so just buffer it. - self.errors.buffered_diags.push(BufferedDiag::Error(diag)); + self.diags.buffered_diags.push(BufferedDiag::Error(diag)); } - for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) { + for (_, (mut diag, count)) in std::mem::take(&mut self.diags.buffered_mut_errors) { if count > 10 { diag.note(format!("...and {} other attempted mutable borrows", count - 10)); } - self.errors.buffered_diags.push(BufferedDiag::Error(diag)); + self.diags.buffered_diags.push(BufferedDiag::Error(diag)); } - if !self.errors.buffered_diags.is_empty() { - self.errors.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span()); - for buffered_diag in self.errors.buffered_diags.drain(..) { + if !self.diags.buffered_diags.is_empty() { + self.diags.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span()); + for buffered_diag in self.diags.buffered_diags.drain(..) { match buffered_diag { BufferedDiag::Error(diag) => res = Some(diag.emit()), BufferedDiag::NonError(diag) => diag.emit(), @@ -2508,14 +2508,14 @@ mod error { } pub(crate) fn has_buffered_diags(&self) -> bool { - self.errors.buffered_diags.is_empty() + self.diags.buffered_diags.is_empty() } pub fn has_move_error( &self, move_out_indices: &[MoveOutIndex], ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)> { - self.errors.buffered_move_errors.get(move_out_indices) + self.diags.buffered_move_errors.get(move_out_indices) } } } diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index f4864986e2811..7ace013975e1b 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -264,7 +264,7 @@ pub(super) fn dump_annotation<'tcx>( regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, opaque_type_values: &FxIndexMap>, - errors: &mut crate::error::BorrowckErrors<'tcx>, + diags: &mut crate::diags::BorrowckDiags<'tcx>, ) { let tcx = infcx.tcx; let base_def_id = tcx.typeck_root_def_id(body.source.def_id()); @@ -310,7 +310,7 @@ pub(super) fn dump_annotation<'tcx>( err.note(format!("Inferred opaque type values:\n{opaque_type_values:#?}")); } - errors.buffer_non_error(err); + diags.buffer_non_error(err); } fn for_each_region_constraint<'tcx>( From ef07b05c0f4ae27909ab96e958bacf0c08a92f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Fri, 2 Feb 2024 08:58:34 +0200 Subject: [PATCH 211/246] Bump rustc_lexer and rustc_parse_format --- Cargo.lock | 41 ++++++++++++++++++++++++++++++++--------- Cargo.toml | 4 ++-- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b5efb4bb81a4..9b8dcf47cfd66 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -595,7 +595,7 @@ dependencies = [ "profile", "project-model", "ra-ap-rustc_abi", - "ra-ap-rustc_index", + "ra-ap-rustc_index 0.33.0", "ra-ap-rustc_pattern_analysis", "rustc-hash", "scoped-tls", @@ -1431,7 +1431,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce9100fc66c6c60aeeb076868ead9c2eaa65d6a5a90404f08c242327a92ff4b" dependencies = [ "bitflags 2.4.1", - "ra-ap-rustc_index", + "ra-ap-rustc_index 0.33.0", "tracing", ] @@ -1442,7 +1442,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5313d7f243b63ef9e58d94355b11aa8499f1328055f1f58adf0a5ea7d2faca" dependencies = [ "arrayvec", - "ra-ap-rustc_index_macros", + "ra-ap-rustc_index_macros 0.33.0", + "smallvec", +] + +[[package]] +name = "ra-ap-rustc_index" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322b751895cc4a0a2ee0c6ab36ec80bc8abf5f8d76254c482f96f03c27c92ebe" +dependencies = [ + "arrayvec", + "ra-ap-rustc_index_macros 0.35.0", "smallvec", ] @@ -1458,11 +1469,23 @@ dependencies = [ "synstructure", ] +[[package]] +name = "ra-ap-rustc_index_macros" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054e25eac52f0506c1309ca4317c11ad4925d7b99eb897f71aa7c3cbafb46c2b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", + "synstructure", +] + [[package]] name = "ra-ap-rustc_lexer" -version = "0.33.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d221356e5717595e8a0afa5fba1620dcb4032ab784dc4d98fdc7284e3feb66" +checksum = "c8da0fa51a1a97ba4296a1c78fa454815a153b472e2546b6338a0902ad59e015" dependencies = [ "unicode-properties", "unicode-xid", @@ -1470,11 +1493,11 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.33.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab62fc925612374103b4f178da347b535b35d9eb1ff5ba42105c990b2e25a164" +checksum = "3851f930a54adcb76889983dcd5c00a0c4e206e190e1384dbc00d49b82dfb45e" dependencies = [ - "ra-ap-rustc_index", + "ra-ap-rustc_index 0.35.0", "ra-ap-rustc_lexer", ] @@ -1485,7 +1508,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c4085e0c771fd4b883930b599ef42966b855762bbe4052c17673b3253421a6d" dependencies = [ "derivative", - "ra-ap-rustc_index", + "ra-ap-rustc_index 0.33.0", "rustc-hash", "rustc_apfloat", "smallvec", diff --git a/Cargo.toml b/Cargo.toml index 5a7486481161a..b5a5c34346171 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,8 +79,8 @@ tt = { path = "./crates/tt", version = "0.0.0" } vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } -ra-ap-rustc_lexer = { version = "0.33.0", default-features = false } -ra-ap-rustc_parse_format = { version = "0.33.0", default-features = false } +ra-ap-rustc_lexer = { version = "0.35.0", default-features = false } +ra-ap-rustc_parse_format = { version = "0.35.0", default-features = false } ra-ap-rustc_index = { version = "0.33.0", default-features = false } ra-ap-rustc_abi = { version = "0.33.0", default-features = false } ra-ap-rustc_pattern_analysis = { version = "0.33.0", default-features = false } From 7a0b8876655b67bf8d9ba27088766d26877c1b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Fri, 2 Feb 2024 09:00:21 +0200 Subject: [PATCH 212/246] Bump rustc_index and rustc_abi --- Cargo.lock | 8 ++++---- Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b8dcf47cfd66..e9492ce0202b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -595,7 +595,7 @@ dependencies = [ "profile", "project-model", "ra-ap-rustc_abi", - "ra-ap-rustc_index 0.33.0", + "ra-ap-rustc_index 0.35.0", "ra-ap-rustc_pattern_analysis", "rustc-hash", "scoped-tls", @@ -1426,12 +1426,12 @@ dependencies = [ [[package]] name = "ra-ap-rustc_abi" -version = "0.33.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce9100fc66c6c60aeeb076868ead9c2eaa65d6a5a90404f08c242327a92ff4b" +checksum = "3c0baa423a2c2bfd6e4bd40e7215f7ddebd12a649ce0b65078a38b91068895aa" dependencies = [ "bitflags 2.4.1", - "ra-ap-rustc_index 0.33.0", + "ra-ap-rustc_index 0.35.0", "tracing", ] diff --git a/Cargo.toml b/Cargo.toml index b5a5c34346171..3fb5d9aa7a869 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,8 +81,8 @@ vfs = { path = "./crates/vfs", version = "0.0.0" } ra-ap-rustc_lexer = { version = "0.35.0", default-features = false } ra-ap-rustc_parse_format = { version = "0.35.0", default-features = false } -ra-ap-rustc_index = { version = "0.33.0", default-features = false } -ra-ap-rustc_abi = { version = "0.33.0", default-features = false } +ra-ap-rustc_index = { version = "0.35.0", default-features = false } +ra-ap-rustc_abi = { version = "0.35.0", default-features = false } ra-ap-rustc_pattern_analysis = { version = "0.33.0", default-features = false } # local crates that aren't published to crates.io. These should not have versions. From ba2910a3a716f0bcc7f18afddc89daf8b51c297e Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Fri, 2 Feb 2024 18:22:54 +0800 Subject: [PATCH 213/246] minor: correct some typos --- crates/hir-def/src/find_path.rs | 6 +- crates/hir-def/src/item_scope.rs | 8 +- crates/hir-def/src/item_tree.rs | 12 +- .../macro_expansion_tests/builtin_fn_macro.rs | 4 +- .../macro_expansion_tests/mbe/regression.rs | 8 +- crates/hir-def/src/nameres.rs | 4 +- crates/hir-def/src/nameres/path_resolution.rs | 4 +- crates/hir-def/src/visibility.rs | 21 +- crates/hir-expand/src/mod_path.rs | 10 +- crates/hir-ty/src/mir/lower.rs | 10 +- crates/hir-ty/src/tests/traits.rs | 4 +- .../src/handlers/generate_default_from_new.rs | 2 +- .../src/handlers/generate_delegate_trait.rs | 2 +- .../src/handlers/into_to_qualified_from.rs | 4 +- crates/ide-db/src/generated/lints.rs | 479 +++++++++++++----- crates/ide/src/folding_ranges.rs | 2 +- crates/mbe/src/syntax_bridge.rs | 12 +- crates/proc-macro-api/src/version.rs | 4 +- docs/dev/lsp-extensions.md | 2 +- docs/dev/style.md | 9 +- 20 files changed, 402 insertions(+), 205 deletions(-) diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index 515a2cc8243ea..1a44c319de58e 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -13,7 +13,7 @@ use crate::{ item_scope::ItemInNs, nameres::DefMap, path::{ModPath, PathKind}, - visibility::{Visibility, VisibilityExplicity}, + visibility::{Visibility, VisibilityExplicitness}, CrateRootModuleId, ModuleDefId, ModuleId, }; @@ -544,11 +544,11 @@ fn find_local_import_locations( if let Some((name, vis, declared)) = data.scope.name_of(item) { if vis.is_visible_from(db, from) { let is_pub_or_explicit = match vis { - Visibility::Module(_, VisibilityExplicity::Explicit) => { + Visibility::Module(_, VisibilityExplicitness::Explicit) => { cov_mark::hit!(explicit_private_imports); true } - Visibility::Module(_, VisibilityExplicity::Implicit) => { + Visibility::Module(_, VisibilityExplicitness::Implicit) => { cov_mark::hit!(discount_private_imports); false } diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 6237ea7353fd2..0b0c838bedb53 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -17,7 +17,7 @@ use syntax::ast; use crate::{ db::DefDatabase, per_ns::PerNs, - visibility::{Visibility, VisibilityExplicity}, + visibility::{Visibility, VisibilityExplicitness}, AdtId, BuiltinType, ConstId, ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, }; @@ -653,14 +653,16 @@ impl ItemScope { .map(|(_, vis, _)| vis) .chain(self.values.values_mut().map(|(_, vis, _)| vis)) .chain(self.unnamed_trait_imports.values_mut().map(|(vis, _)| vis)) - .for_each(|vis| *vis = Visibility::Module(this_module, VisibilityExplicity::Implicit)); + .for_each(|vis| { + *vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit) + }); for (mac, vis, import) in self.macros.values_mut() { if matches!(mac, MacroId::ProcMacroId(_) if import.is_none()) { continue; } - *vis = Visibility::Module(this_module, VisibilityExplicity::Implicit); + *vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit); } } diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 299ad33c34934..336e0de7fd66f 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -69,7 +69,7 @@ use crate::{ generics::{GenericParams, LifetimeParamData, TypeOrConstParamData}, path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, - visibility::{RawVisibility, VisibilityExplicity}, + visibility::{RawVisibility, VisibilityExplicitness}, BlockId, Lookup, }; @@ -253,10 +253,10 @@ impl ItemVisibilities { RawVisibility::Public => RawVisibilityId::PUB, RawVisibility::Module(path, explicitiy) if path.segments().is_empty() => { match (&path.kind, explicitiy) { - (PathKind::Super(0), VisibilityExplicity::Explicit) => { + (PathKind::Super(0), VisibilityExplicitness::Explicit) => { RawVisibilityId::PRIV_EXPLICIT } - (PathKind::Super(0), VisibilityExplicity::Implicit) => { + (PathKind::Super(0), VisibilityExplicitness::Implicit) => { RawVisibilityId::PRIV_IMPLICIT } (PathKind::Crate, _) => RawVisibilityId::PUB_CRATE, @@ -270,11 +270,11 @@ impl ItemVisibilities { static VIS_PUB: RawVisibility = RawVisibility::Public; static VIS_PRIV_IMPLICIT: RawVisibility = - RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Implicit); + RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Implicit); static VIS_PRIV_EXPLICIT: RawVisibility = - RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Explicit); + RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Explicit); static VIS_PUB_CRATE: RawVisibility = - RawVisibility::Module(ModPath::from_kind(PathKind::Crate), VisibilityExplicity::Explicit); + RawVisibility::Module(ModPath::from_kind(PathKind::Crate), VisibilityExplicitness::Explicit); #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index 4690ca5d363cd..9596100b60e13 100644 --- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -460,13 +460,13 @@ fn test_concat_expand() { #[rustc_builtin_macro] macro_rules! concat {} -fn main() { concat!("foo", "r", 0, r#"bar"#, "\n", false, '"', '\0'); } +fn main() { concat!("fo", "o", 0, r#"bar"#, "\n", false, '"', '\0'); } "##, expect![[r##" #[rustc_builtin_macro] macro_rules! concat {} -fn main() { "foor0bar\nfalse\"\u{0}"; } +fn main() { "foo0bar\nfalse\"\u{0}"; } "##]], ); } diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs index 226aa01827be7..6717ee1aa5fdf 100644 --- a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs +++ b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs @@ -544,11 +544,11 @@ fn test_proptest_arbitrary() { check( r#" macro_rules! arbitrary { - ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty; + ([$($bounds : tt)*] $typ: ty, $strategy: ty, $params: ty; $args: ident => $logic: expr) => { impl<$($bounds)*> $crate::arbitrary::Arbitrary for $typ { type Parameters = $params; - type Strategy = $strat; + type Strategy = $strategy; fn arbitrary_with($args: Self::Parameters) -> Self::Strategy { $logic } @@ -569,11 +569,11 @@ arbitrary!( "#, expect![[r#" macro_rules! arbitrary { - ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty; + ([$($bounds : tt)*] $typ: ty, $strategy: ty, $params: ty; $args: ident => $logic: expr) => { impl<$($bounds)*> $crate::arbitrary::Arbitrary for $typ { type Parameters = $params; - type Strategy = $strat; + type Strategy = $strategy; fn arbitrary_with($args: Self::Parameters) -> Self::Strategy { $logic } diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 1fa975789e772..2a9390e797808 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -79,7 +79,7 @@ use crate::{ nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, path::ModPath, per_ns::PerNs, - visibility::{Visibility, VisibilityExplicity}, + visibility::{Visibility, VisibilityExplicitness}, AstId, BlockId, BlockLoc, CrateRootModuleId, EnumId, EnumVariantId, ExternCrateId, FunctionId, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, }; @@ -336,7 +336,7 @@ impl DefMap { // this visibility for anything outside IDE, so that's probably OK. let visibility = Visibility::Module( ModuleId { krate, local_id, block: None }, - VisibilityExplicity::Implicit, + VisibilityExplicitness::Implicit, ); let module_data = ModuleData::new( ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id }, diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 2c7e222791375..8943d22d8764d 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -87,7 +87,7 @@ impl DefMap { within_impl: bool, ) -> Option { let mut vis = match visibility { - RawVisibility::Module(path, explicity) => { + RawVisibility::Module(path, explicitness) => { let (result, remaining) = self.resolve_path(db, original_module, path, BuiltinShadowMode::Module, None); if remaining.is_some() { @@ -95,7 +95,7 @@ impl DefMap { } let types = result.take_types()?; match types { - ModuleDefId::ModuleId(m) => Visibility::Module(m, *explicity), + ModuleDefId::ModuleId(m) => Visibility::Module(m, *explicitness), // error: visibility needs to refer to module _ => { return None; diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs index 3294ce29a4a05..b9676179a5fdd 100644 --- a/crates/hir-def/src/visibility.rs +++ b/crates/hir-def/src/visibility.rs @@ -20,14 +20,17 @@ use crate::{ pub enum RawVisibility { /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is /// equivalent to `pub(self)`. - Module(ModPath, VisibilityExplicity), + Module(ModPath, VisibilityExplicitness), /// `pub`. Public, } impl RawVisibility { pub(crate) const fn private() -> RawVisibility { - RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Implicit) + RawVisibility::Module( + ModPath::from_kind(PathKind::Super(0)), + VisibilityExplicitness::Implicit, + ) } pub(crate) fn from_ast( @@ -53,19 +56,19 @@ impl RawVisibility { None => return RawVisibility::private(), Some(path) => path, }; - RawVisibility::Module(path, VisibilityExplicity::Explicit) + RawVisibility::Module(path, VisibilityExplicitness::Explicit) } ast::VisibilityKind::PubCrate => { let path = ModPath::from_kind(PathKind::Crate); - RawVisibility::Module(path, VisibilityExplicity::Explicit) + RawVisibility::Module(path, VisibilityExplicitness::Explicit) } ast::VisibilityKind::PubSuper => { let path = ModPath::from_kind(PathKind::Super(1)); - RawVisibility::Module(path, VisibilityExplicity::Explicit) + RawVisibility::Module(path, VisibilityExplicitness::Explicit) } ast::VisibilityKind::PubSelf => { let path = ModPath::from_kind(PathKind::Super(0)); - RawVisibility::Module(path, VisibilityExplicity::Explicit) + RawVisibility::Module(path, VisibilityExplicitness::Explicit) } ast::VisibilityKind::Pub => RawVisibility::Public, } @@ -85,7 +88,7 @@ impl RawVisibility { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Visibility { /// Visibility is restricted to a certain module. - Module(ModuleId, VisibilityExplicity), + Module(ModuleId, VisibilityExplicitness), /// Visibility is unrestricted. Public, } @@ -206,12 +209,12 @@ impl Visibility { /// Whether the item was imported through `pub(crate) use` or just `use`. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum VisibilityExplicity { +pub enum VisibilityExplicitness { Explicit, Implicit, } -impl VisibilityExplicity { +impl VisibilityExplicitness { pub fn is_explicit(&self) -> bool { matches!(self, Self::Explicit) } diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index dd41bcaee20ef..b64c3549e421e 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -284,13 +284,13 @@ fn convert_path( } fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option { - let mut leafs = tt.iter().filter_map(|tt| match tt { + let mut leaves = tt.iter().filter_map(|tt| match tt { tt::TokenTree::Leaf(leaf) => Some(leaf), tt::TokenTree::Subtree(_) => None, }); let mut segments = smallvec::smallvec![]; - let kind = match leafs.next()? { - tt::Leaf::Punct(tt::Punct { char: ':', .. }) => match leafs.next()? { + let kind = match leaves.next()? { + tt::Leaf::Punct(tt::Punct { char: ':', .. }) => match leaves.next()? { tt::Leaf::Punct(tt::Punct { char: ':', .. }) => PathKind::Abs, _ => return None, }, @@ -300,7 +300,7 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option PathKind::Super(0), tt::Leaf::Ident(tt::Ident { text, .. }) if text == "super" => { let mut deg = 1; - while let Some(tt::Leaf::Ident(tt::Ident { text, .. })) = leafs.next() { + while let Some(tt::Leaf::Ident(tt::Ident { text, .. })) = leaves.next() { if text != "super" { segments.push(Name::new_text_dont_use(text.clone())); break; @@ -316,7 +316,7 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option return None, }; - segments.extend(leafs.filter_map(|leaf| match leaf { + segments.extend(leaves.filter_map(|leaf| match leaf { ::tt::Leaf::Ident(ident) => Some(Name::new_text_dont_use(ident.text.clone())), _ => None, })); diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 74bac8cbf1249..28d26c6c8ae6e 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -97,7 +97,7 @@ pub enum MirLowerError { MutatingRvalue, UnresolvedLabel, UnresolvedUpvar(Place), - UnaccessableLocal, + InaccessibleLocal, // monomorphization errors: GenericArgNotProvided(TypeOrConstParamId, Substitution), @@ -116,7 +116,7 @@ impl DropScopeToken { ctx.pop_drop_scope_internal(current, span) } - /// It is useful when we want a drop scope is syntaxically closed, but we don't want to execute any drop + /// It is useful when we want a drop scope is syntactically closed, but we don't want to execute any drop /// code. Either when the control flow is diverging (so drop code doesn't reached) or when drop is handled /// for us (for example a block that ended with a return statement. Return will drop everything, so the block shouldn't /// do anything) @@ -186,7 +186,7 @@ impl MirLowerError { | MirLowerError::UnsizedTemporary(_) | MirLowerError::IncompleteExpr | MirLowerError::IncompletePattern - | MirLowerError::UnaccessableLocal + | MirLowerError::InaccessibleLocal | MirLowerError::TraitFunctionDefinition(_, _) | MirLowerError::UnresolvedName(_) | MirLowerError::RecordLiteralWithoutPath @@ -1843,8 +1843,8 @@ impl<'ctx> MirLowerCtx<'ctx> { None => { // FIXME: It should never happens, but currently it will happen in `const_dependent_on_local` test, which // is a hir lowering problem IMO. - // never!("Using unaccessable local for binding is always a bug"); - Err(MirLowerError::UnaccessableLocal) + // never!("Using inaccessible local for binding is always a bug"); + Err(MirLowerError::InaccessibleLocal) } } } diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index e4756ee9e29b5..db14addaf185b 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -3424,7 +3424,7 @@ fn bin_op_with_rhs_is_self_for_assoc_bound() { fn repro(t: T) -> bool where T: Request, - T::Output: Convertable, + T::Output: Convertible, { let a = execute(&t).convert(); let b = execute(&t).convert(); @@ -3439,7 +3439,7 @@ where { ::output() } -trait Convertable { +trait Convertible { type TraitSelf: PartialEq; type AssocAsDefaultSelf: PartialEq; fn convert(self) -> Self::AssocAsDefaultSelf; diff --git a/crates/ide-assists/src/handlers/generate_default_from_new.rs b/crates/ide-assists/src/handlers/generate_default_from_new.rs index 7e4f140a28faa..dc27af5cbed20 100644 --- a/crates/ide-assists/src/handlers/generate_default_from_new.rs +++ b/crates/ide-assists/src/handlers/generate_default_from_new.rs @@ -418,7 +418,7 @@ where } #[test] - fn new_function_with_generics_and_wheres() { + fn new_function_with_generics_and_where() { check_assist( generate_default_from_new, r#" diff --git a/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/crates/ide-assists/src/handlers/generate_delegate_trait.rs index 3964b14f4703f..898bd01291a25 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -295,7 +295,7 @@ fn generate_impl( // those in strukt. // // These generics parameters will also be used in `field_ty` and - // `where_clauses`, so we should substitude arguments in them as well. + // `where_clauses`, so we should substitute arguments in them as well. let strukt_params = resolve_name_conflicts(strukt_params, &old_impl_params); let (field_ty, ty_where_clause) = match &strukt_params { Some(strukt_params) => { diff --git a/crates/ide-assists/src/handlers/into_to_qualified_from.rs b/crates/ide-assists/src/handlers/into_to_qualified_from.rs index 965e4aa786e7a..f7da88b2c1838 100644 --- a/crates/ide-assists/src/handlers/into_to_qualified_from.rs +++ b/crates/ide-assists/src/handlers/into_to_qualified_from.rs @@ -120,7 +120,7 @@ fn main() -> () { } #[test] - fn fromed_in_child_mod_imported() { + fn from_in_child_mod_imported() { check_assist( into_to_qualified_from, r#" @@ -168,7 +168,7 @@ fn main() -> () { } #[test] - fn fromed_in_child_mod_not_imported() { + fn from_in_child_mod_not_imported() { check_assist( into_to_qualified_from, r#" diff --git a/crates/ide-db/src/generated/lints.rs b/crates/ide-db/src/generated/lints.rs index be8419686f44f..677c8fd54c058 100644 --- a/crates/ide-db/src/generated/lints.rs +++ b/crates/ide-db/src/generated/lints.rs @@ -22,10 +22,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"detects certain glob imports that require reporting an ambiguity error"##, }, Lint { label: "ambiguous_glob_reexports", description: r##"ambiguous glob re-exports"## }, - Lint { - label: "ambiguous_wide_pointer_comparisons", - description: r##"detects ambiguous wide pointer comparisons"##, - }, Lint { label: "anonymous_parameters", description: r##"detects anonymous parameters"## }, Lint { label: "arithmetic_overflow", description: r##"arithmetic operation overflows"## }, Lint { @@ -110,7 +106,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, Lint { label: "deref_into_dyn_supertrait", - description: r##"`Deref` implementation usage with a supertrait trait object for output are shadow by implicit coercion"##, + description: r##"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future"##, }, Lint { label: "deref_nullptr", @@ -180,7 +176,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, Lint { label: "future_incompatible", - description: r##"lint group for: ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, }, Lint { label: "fuzzy_provenance_casts", @@ -198,6 +194,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "illegal_floating_point_literal_pattern", description: r##"floating-point literals cannot be used in patterns"##, }, + Lint { + label: "implied_bounds_entailment", + description: r##"impl method assumes more implied bounds than its corresponding trait method"##, + }, Lint { label: "improper_ctypes", description: r##"proper use of libc types in foreign modules"##, @@ -579,10 +579,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"enabling track_caller on an async fn is a no-op unless the async_fn_track_caller feature is enabled"##, }, Lint { label: "uninhabited_static", description: r##"uninhabited static"## }, - Lint { - label: "unit_bindings", - description: r##"binding is useless because it has the unit `()` type"##, - }, Lint { label: "unknown_crate_types", description: r##"unknown crate type found in `#[crate_type]` directive"##, @@ -740,19 +736,16 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "while_true", description: r##"suggest using `loop { }` instead of `while true { }`"##, }, - Lint { - label: "writes_through_immutable_pointer", - description: r##"shared references are immutable, and pointers derived from them must not be written to"##, - }, ]; pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "future_incompatible", - description: r##"lint group for: ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, }, children: &[ + "deref_into_dyn_supertrait", "ambiguous_associated_items", "ambiguous_glob_imports", "byte_slice_in_packed_struct_with_derive", @@ -767,6 +760,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "forbidden_lint_groups", "ill_formed_attribute_input", "illegal_floating_point_literal_pattern", + "implied_bounds_entailment", "indirect_structural_match", "invalid_doc_attributes", "invalid_type_param_default", @@ -790,7 +784,6 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "unstable_syntax_pre_expansion", "unsupported_calling_conventions", "where_clauses_object_safety", - "writes_through_immutable_pointer", ], }, LintGroup { @@ -1392,17 +1385,6 @@ The tracking issue for this feature is: [#91583] [#91583]: https://github.com/rust-lang/rust/issues/91583 ------------------------- -"##, - }, - Lint { - label: "array_methods", - description: r##"# `array_methods` - -The tracking issue for this feature is: [#76118] - -[#76118]: https://github.com/rust-lang/rust/issues/76118 - ------------------------ "##, }, @@ -1575,7 +1557,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `reg_data` | None | `i8`, `i16`, `i32` | | CSKY | `reg` | None | `i8`, `i16`, `i32` | | CSKY | `freg` | None | `f32`, | -| s390x | `reg` | None | `i8`, `i16`, `i32`, `i64` | +| s390x | `reg`, `reg_addr` | None | `i8`, `i16`, `i32`, `i64` | | s390x | `freg` | None | `f32`, `f64` | ## Register aliases @@ -1649,9 +1631,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | NVPTX | `reg64` | None | `rd0` | None | | Hexagon | `reg` | None | `r0` | None | | PowerPC | `reg` | None | `0` | None | -| PowerPC | `reg_nonzero` | None | `3` | `b` | +| PowerPC | `reg_nonzero` | None | `3` | None | | PowerPC | `freg` | None | `0` | None | | s390x | `reg` | None | `%r0` | None | +| s390x | `reg_addr` | None | `%r1` | None | | s390x | `freg` | None | `%f0` | None | | CSKY | `reg` | None | `r0` | None | | CSKY | `freg` | None | `f0` | None | @@ -1745,6 +1728,15 @@ The tracking issue for this feature is: [#110011] [#110011]: https://github.com/rust-lang/rust/issues/110011 +------------------------ +"##, + }, + Lint { + label: "async_fn_traits", + description: r##"# `async_fn_traits` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -1996,17 +1988,6 @@ The tracking issue for this feature is: [#80996] [#80996]: https://github.com/rust-lang/rust/issues/80996 ------------------------- -"##, - }, - Lint { - label: "bound_map", - description: r##"# `bound_map` - -The tracking issue for this feature is: [#86026] - -[#86026]: https://github.com/rust-lang/rust/issues/86026 - ------------------------ "##, }, @@ -2386,6 +2367,17 @@ fn b() { } } ``` +"##, + }, + Lint { + label: "cfg_sanitizer_cfi", + description: r##"# `cfg_sanitizer_cfi` + +The tracking issue for this feature is: [#89653] + +[#89653]: https://github.com/rust-lang/rust/issues/89653 + +------------------------ "##, }, Lint { @@ -2818,17 +2810,6 @@ The tracking issue for this feature is: [#91583] [#91583]: https://github.com/rust-lang/rust/issues/91583 ------------------------- -"##, - }, - Lint { - label: "const_assume", - description: r##"# `const_assume` - -The tracking issue for this feature is: [#76972] - -[#76972]: https://github.com/rust-lang/rust/issues/76972 - ------------------------ "##, }, @@ -3103,6 +3084,17 @@ The tracking issue for this feature is: [#79597] [#79597]: https://github.com/rust-lang/rust/issues/79597 +------------------------ +"##, + }, + Lint { + label: "const_hint_assert_unchecked", + description: r##"# `const_hint_assert_unchecked` + +The tracking issue for this feature is: [#119131] + +[#119131]: https://github.com/rust-lang/rust/issues/119131 + ------------------------ "##, }, @@ -3507,6 +3499,17 @@ The tracking issue for this feature is: [#83570] [#83570]: https://github.com/rust-lang/rust/issues/83570 +------------------------ +"##, + }, + Lint { + label: "const_slice_first_last_chunk", + description: r##"# `const_slice_first_last_chunk` + +The tracking issue for this feature is: [#111774] + +[#111774]: https://github.com/rust-lang/rust/issues/111774 + ------------------------ "##, }, @@ -3582,6 +3585,17 @@ The tracking issue for this feature is: [#101804] [#101804]: https://github.com/rust-lang/rust/issues/101804 +------------------------ +"##, + }, + Lint { + label: "const_str_from_raw_parts_mut", + description: r##"# `const_str_from_raw_parts_mut` + +The tracking issue for this feature is: [#119206] + +[#119206]: https://github.com/rust-lang/rust/issues/119206 + ------------------------ "##, }, @@ -3604,6 +3618,17 @@ The tracking issue for this feature is: [#91005] [#91005]: https://github.com/rust-lang/rust/issues/91005 +------------------------ +"##, + }, + Lint { + label: "const_strict_overflow_ops", + description: r##"# `const_strict_overflow_ops` + +The tracking issue for this feature is: [#118260] + +[#118260]: https://github.com/rust-lang/rust/issues/118260 + ------------------------ "##, }, @@ -3743,15 +3768,6 @@ The tracking issue for this feature is: [#117693] [#117693]: https://github.com/rust-lang/rust/issues/117693 ------------------------- -"##, - }, - Lint { - label: "core_panic", - description: r##"# `core_panic` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------ "##, }, @@ -5305,6 +5321,17 @@ The tracking issue for this feature is: [#113521] [#113521]: https://github.com/rust-lang/rust/issues/113521 +------------------------ +"##, + }, + Lint { + label: "generic_nonzero", + description: r##"# `generic_nonzero` + +The tracking issue for this feature is: [#120257] + +[#120257]: https://github.com/rust-lang/rust/issues/120257 + ------------------------ "##, }, @@ -5425,6 +5452,17 @@ The tracking issue for this feature is: [#44839] [#44839]: https://github.com/rust-lang/rust/issues/44839 +------------------------ +"##, + }, + Lint { + label: "hint_assert_unchecked", + description: r##"# `hint_assert_unchecked` + +The tracking issue for this feature is: [#119131] + +[#119131]: https://github.com/rust-lang/rust/issues/119131 + ------------------------ "##, }, @@ -5748,6 +5786,15 @@ The tracking issue for this feature is: [#53485] Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`; add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `Iterator`. +"##, + }, + Lint { + label: "is_val_statically_known", + description: r##"# `is_val_statically_known` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ "##, }, Lint { @@ -6406,6 +6453,17 @@ The tracking issue for this feature is: [#98262] [#98262]: https://github.com/rust-lang/rust/issues/98262 +------------------------ +"##, + }, + Lint { + label: "min_exhaustive_patterns", + description: r##"# `min_exhaustive_patterns` + +The tracking issue for this feature is: [#119612] + +[#119612]: https://github.com/rust-lang/rust/issues/119612 + ------------------------ "##, }, @@ -6503,17 +6561,6 @@ The tracking issue for this feature is: [#81872] [#81872]: https://github.com/rust-lang/rust/issues/81872 ------------------------- -"##, - }, - Lint { - label: "mutex_unpoison", - description: r##"# `mutex_unpoison` - -The tracking issue for this feature is: [#96469] - -[#96469]: https://github.com/rust-lang/rust/issues/96469 - ------------------------ "##, }, @@ -6521,9 +6568,9 @@ The tracking issue for this feature is: [#96469] label: "naked_functions", description: r##"# `naked_functions` -The tracking issue for this feature is: [#32408] +The tracking issue for this feature is: [#90957] -[#32408]: https://github.com/rust-lang/rust/issues/32408 +[#90957]: https://github.com/rust-lang/rust/issues/90957 ------------------------ "##, @@ -6749,6 +6796,37 @@ The tracking issue for this feature is: [#117691] [#117691]: https://github.com/rust-lang/rust/issues/117691 +------------------------ +"##, + }, + Lint { + label: "non_zero_count_ones", + description: r##"# `non_zero_count_ones` + +The tracking issue for this feature is: [#120287] + +[#120287]: https://github.com/rust-lang/rust/issues/120287 + +------------------------ +"##, + }, + Lint { + label: "nonzero_from_mut", + description: r##"# `nonzero_from_mut` + +The tracking issue for this feature is: [#106290] + +[#106290]: https://github.com/rust-lang/rust/issues/106290 + +------------------------ +"##, + }, + Lint { + label: "nonzero_internals", + description: r##"# `nonzero_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -6806,23 +6884,23 @@ The tracking issue for this feature is: [#43561] "##, }, Lint { - label: "offset_of", - description: r##"# `offset_of` + label: "offset_of_enum", + description: r##"# `offset_of_enum` -The tracking issue for this feature is: [#106655] +The tracking issue for this feature is: [#120141] -[#106655]: https://github.com/rust-lang/rust/issues/106655 +[#120141]: https://github.com/rust-lang/rust/issues/120141 ------------------------ "##, }, Lint { - label: "offset_of_enum", - description: r##"# `offset_of_enum` + label: "offset_of_nested", + description: r##"# `offset_of_nested` -The tracking issue for this feature is: [#106655] +The tracking issue for this feature is: [#120140] -[#106655]: https://github.com/rust-lang/rust/issues/106655 +[#120140]: https://github.com/rust-lang/rust/issues/120140 ------------------------ "##, @@ -7153,6 +7231,17 @@ The tracking issue for this feature is: [#115268] [#115268]: https://github.com/rust-lang/rust/issues/115268 +------------------------ +"##, + }, + Lint { + label: "proc_macro_c_str_literals", + description: r##"# `proc_macro_c_str_literals` + +The tracking issue for this feature is: [#119750] + +[#119750]: https://github.com/rust-lang/rust/issues/119750 + ------------------------ "##, }, @@ -7372,17 +7461,6 @@ The tracking issue for this feature is: [#107792] [#107792]: https://github.com/rust-lang/rust/issues/107792 ------------------------- -"##, - }, - Lint { - label: "raw_os_nonzero", - description: r##"# `raw_os_nonzero` - -The tracking issue for this feature is: [#82363] - -[#82363]: https://github.com/rust-lang/rust/issues/82363 - ------------------------ "##, }, @@ -7542,17 +7620,6 @@ The tracking issue for this feature is: [#93743] [#93743]: https://github.com/rust-lang/rust/issues/93743 ------------------------- -"##, - }, - Lint { - label: "round_ties_even", - description: r##"# `round_ties_even` - -The tracking issue for this feature is: [#96710] - -[#96710]: https://github.com/rust-lang/rust/issues/96710 - ------------------------ "##, }, @@ -7802,17 +7869,6 @@ The tracking issue for this feature is: [#27747] [#27747]: https://github.com/rust-lang/rust/issues/27747 ------------------------- -"##, - }, - Lint { - label: "slice_first_last_chunk", - description: r##"# `slice_first_last_chunk` - -The tracking issue for this feature is: [#111774] - -[#111774]: https://github.com/rust-lang/rust/issues/111774 - ------------------------ "##, }, @@ -7835,17 +7891,6 @@ The tracking issue for this feature is: [#89792] [#89792]: https://github.com/rust-lang/rust/issues/89792 ------------------------- -"##, - }, - Lint { - label: "slice_group_by", - description: r##"# `slice_group_by` - -The tracking issue for this feature is: [#80552] - -[#80552]: https://github.com/rust-lang/rust/issues/80552 - ------------------------ "##, }, @@ -8045,6 +8090,17 @@ The tracking issue for this feature is: [#96137] [#96137]: https://github.com/rust-lang/rust/issues/96137 +------------------------ +"##, + }, + Lint { + label: "split_at_checked", + description: r##"# `split_at_checked` + +The tracking issue for this feature is: [#119128] + +[#119128]: https://github.com/rust-lang/rust/issues/119128 + ------------------------ "##, }, @@ -8181,6 +8237,17 @@ The tracking issue for this feature is: [#15701] [#15701]: https://github.com/rust-lang/rust/issues/15701 +------------------------ +"##, + }, + Lint { + label: "str_from_raw_parts", + description: r##"# `str_from_raw_parts` + +The tracking issue for this feature is: [#119206] + +[#119206]: https://github.com/rust-lang/rust/issues/119206 + ------------------------ "##, }, @@ -8201,6 +8268,17 @@ The tracking issue for this feature is: [#116258] This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "str_lines_remainder", + description: r##"# `str_lines_remainder` + +The tracking issue for this feature is: [#77998] + +[#77998]: https://github.com/rust-lang/rust/issues/77998 + ------------------------ "##, }, @@ -8234,6 +8312,17 @@ The tracking issue for this feature is: [#77998] [#77998]: https://github.com/rust-lang/rust/issues/77998 +------------------------ +"##, + }, + Lint { + label: "strict_overflow_ops", + description: r##"# `strict_overflow_ops` + +The tracking issue for this feature is: [#118260] + +[#118260]: https://github.com/rust-lang/rust/issues/118260 + ------------------------ "##, }, @@ -8747,6 +8836,37 @@ pub fn main() { println!("{:?}", b); } ``` +"##, + }, + Lint { + label: "trait_upcasting", + description: r##"# `trait_upcasting` + +The tracking issue for this feature is: [#65991] + +[#65991]: https://github.com/rust-lang/rust/issues/65991 + +------------------------ + +The `trait_upcasting` feature adds support for trait upcasting coercion. This allows a +trait object of type `dyn Bar` to be cast to a trait object of type `dyn Foo` +so long as `Bar: Foo`. + +```rust,edition2018 +#![feature(trait_upcasting)] +#![allow(incomplete_features)] + +trait Foo {} + +trait Bar: Foo {} + +impl Foo for i32 {} + +impl Bar for T {} + +let bar: &dyn Bar = &123; +let foo: &dyn Foo = bar; +``` "##, }, Lint { @@ -10481,6 +10601,11 @@ differing by an underscore."##, label: "clippy::duration_subsec", description: r##"Checks for calculation of subsecond microseconds or milliseconds from other `Duration` methods."##, + }, + Lint { + label: "clippy::eager_transmute", + description: r##"Checks for integer validity checks, followed by a transmute that is (incorrectly) evaluated +eagerly (e.g. using `bool::then_some`)."##, }, Lint { label: "clippy::else_if_without_else", @@ -10499,6 +10624,10 @@ As of this writing, the `never_type` is still a nightly-only experimental API. Therefore, this lint is only triggered if the `never_type` is enabled."##, }, + Lint { + label: "clippy::empty_enum_variants_with_brackets", + description: r##"Finds enum variants without fields that are declared with empty brackets."##, + }, Lint { label: "clippy::empty_line_after_doc_comments", description: r##"Checks for empty lines after documentation comments."##, @@ -10765,7 +10894,7 @@ multithreaded executors are likely to be used for running these Futures."##, Lint { label: "clippy::get_first", description: r##"Checks for usage of `x.get(0)` instead of -`x.first()`."##, +`x.first()` or `x.front()`."##, }, Lint { label: "clippy::get_last_with_len", @@ -10865,6 +10994,11 @@ because `Deref` is a supertrait of `DerefMut`)"##, description: r##"Looks for floating-point expressions that can be expressed using built-in methods to improve accuracy at the cost of performance."##, + }, + Lint { + label: "clippy::incompatible_msrv", + description: r##"This lint checks that no function newer than the defined MSRV (minimum +supported rust version) is used in the crate."##, }, Lint { label: "clippy::inconsistent_digit_grouping", @@ -11017,6 +11151,16 @@ create a `Vec`."##, label: "clippy::iter_count", description: r##"Checks for the use of `.iter().count()`."##, }, + Lint { + label: "clippy::iter_filter_is_ok", + description: r##"Checks for usage of `.filter(Result::is_ok)` that may be replaced with a `.flatten()` call. +This lint will require additional changes to the follow-up calls as it appects the type."##, + }, + Lint { + label: "clippy::iter_filter_is_some", + description: r##"Checks for usage of `.filter(Option::is_some)` that may be replaced with a `.flatten()` call. +This lint will require additional changes to the follow-up calls as it appects the type."##, + }, Lint { label: "clippy::iter_kv_map", description: r##"Checks for iterating a map (`HashMap` or `BTreeMap`) and @@ -11185,6 +11329,14 @@ when `lines` has type `std::io::Lines`."##, label: "clippy::linkedlist", description: r##"Checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`)."##, + }, + Lint { + label: "clippy::lint_groups_priority", + description: r##"Checks for lint groups with the same priority as lints in the `Cargo.toml` +[`[lints]` table](https://doc.rust-lang.org/cargo/reference/manifest.html#the-lints-section). + +This lint will be removed once [cargo#12918](https://github.com/rust-lang/cargo/issues/12918) +is resolved."##, }, Lint { label: "clippy::little_endian_bytes", @@ -11269,6 +11421,7 @@ ascii range"##, description: r##"Checks for manual `is_infinite` reimplementations (i.e., `x == ::INFINITY || x == ::NEG_INFINITY`)."##, }, + Lint { label: "clippy::manual_is_variant_and", description: r##""## }, Lint { label: "clippy::manual_let_else", description: r##"Warn of cases where `let...else` could be used"##, @@ -11545,10 +11698,10 @@ is greater than the largest index used to index into the slice."##, Lint { label: "clippy::missing_enforced_import_renames", description: r##"Checks for imports that do not rename the item as specified -in the `enforce-import-renames` config option. +in the `enforced-import-renames` config option. Note: Even though this lint is warn-by-default, it will only trigger if -import renames are defined in the clippy.toml file."##, +import renames are defined in the `clippy.toml` file."##, }, Lint { label: "clippy::missing_errors_doc", @@ -11936,6 +12089,10 @@ character escapes in C."##, taken to satisfy a bound and suggests to dereference the other argument instead"##, }, + Lint { + label: "clippy::option_as_ref_cloned", + description: r##"Checks for usage of `.as_ref().cloned()` and `.as_mut().cloned()` on `Option`s"##, + }, Lint { label: "clippy::option_as_ref_deref", description: r##"Checks for usage of `_.as_ref().map(Deref::deref)` or its aliases (such as String::as_str)."##, @@ -11947,7 +12104,7 @@ suggests usage of the `env!` macro."##, }, Lint { label: "clippy::option_filter_map", - description: r##"Checks for iterators of `Option`s using ``.filter(Option::is_some).map(Option::unwrap)` that may + description: r##"Checks for iterators of `Option`s using `.filter(Option::is_some).map(Option::unwrap)` that may be replaced with a `.flatten()` call."##, }, Lint { @@ -12133,6 +12290,11 @@ namely `*const T` to `*const U` and `*mut T` to `*mut U`."##, label: "clippy::pub_enum_variant_names", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { + label: "clippy::pub_underscore_fields", + description: r##"Checks whether any field of the struct is prefixed with an `_` (underscore) and also marked +`pub` (public)"##, + }, Lint { label: "clippy::pub_use", description: r##"Restricts the usage of `pub use ...`"## }, Lint { label: "clippy::pub_with_shorthand", @@ -12228,8 +12390,8 @@ value that is going to be dropped without further use."##, Lint { label: "clippy::redundant_closure", description: r##"Checks for closures which just call another function where -the function can be called directly. `unsafe` functions or calls where types -get adjusted are ignored."##, +the function can be called directly. `unsafe` functions, calls where types +get adjusted or where the callee is marked `#[track_caller]` are ignored."##, }, Lint { label: "clippy::redundant_closure_call", @@ -12337,7 +12499,7 @@ they are equivalent to `1`. (Related discussion in [rust-clippy#7306](https://gi }, Lint { label: "clippy::result_filter_map", - description: r##"Checks for iterators of `Result`s using ``.filter(Result::is_ok).map(Result::unwrap)` that may + description: r##"Checks for iterators of `Result`s using `.filter(Result::is_ok).map(Result::unwrap)` that may be replaced with a `.flatten()` call."##, }, Lint { @@ -12432,7 +12594,7 @@ see the `unseparated_literal_suffix` lint."##, }, Lint { label: "clippy::serde_api_misuse", - description: r##"Checks for mis-uses of the serde API."##, + description: r##"Checks for misuses of the serde API."##, }, Lint { label: "clippy::shadow_reuse", @@ -12569,6 +12731,12 @@ use an unstable sort than a stable sort."##, label: "clippy::std_instead_of_core", description: r##"Finds items imported through `std` when available through `core`."##, }, + Lint { + label: "clippy::str_split_at_newline", + description: r##"Checks for usages of `str.trim().split(\ +)` and `str.trim().split(\\ +)`."##, + }, Lint { label: "clippy::str_to_string", description: r##"This lint checks for `.to_string()` method calls on values of type `&str`."##, @@ -12663,6 +12831,11 @@ is followed immediately by a newline or the `else` seems to be missing."##, label: "clippy::suspicious_op_assign_impl", description: r##"Lints for suspicious operations in impls of OpAssign, e.g. subtracting elements in an AddAssign impl."##, + }, + Lint { + label: "clippy::suspicious_open_options", + description: r##"Checks for the suspicious use of `OpenOptions::create()` +without an explicit `OpenOptions::truncate()`."##, }, Lint { label: "clippy::suspicious_operation_groupings", @@ -12713,6 +12886,10 @@ either `ignore`, `no_run` or `compile_fail`."##, description: r##"Triggers when a testing function (marked with the `#[test]` attribute) isn't inside a testing module (marked with `#[cfg(test)]`)."##, }, + Lint { + label: "clippy::thread_local_initializer_can_be_made_const", + description: r##"Suggests to use `const` in `thread_local!` macro if possible."##, + }, Lint { label: "clippy::to_digit_is_some", description: r##"Checks for `.to_digit(..).is_some()` on `char`s."##, @@ -12723,6 +12900,10 @@ either `ignore`, `no_run` or `compile_fail`."##, applied to a type that implements [`Display`](https://doc.rust-lang.org/std/fmt/trait.Display.html) in a macro that does formatting."##, }, + Lint { + label: "clippy::to_string_trait_impl", + description: r##"Checks for direct implementations of `ToString`."##, + }, Lint { label: "clippy::todo", description: r##"Checks for usage of `todo!`."## }, Lint { label: "clippy::too_many_arguments", @@ -12836,7 +13017,7 @@ declarations above a certain complexity threshold."##, }, Lint { label: "clippy::unchecked_duration_subtraction", - description: r##"Lints subtraction between an [`Instant`] and a [`Duration`]."##, + description: r##"Lints subtraction between an `Instant` and a `Duration`."##, }, Lint { label: "clippy::unconditional_recursion", @@ -12990,6 +13171,10 @@ sub-expression."##, label: "clippy::unnecessary_owned_empty_strings", description: r##"Detects cases of owned empty strings being passed as an argument to a function expecting `&str`"##, }, + Lint { + label: "clippy::unnecessary_result_map_or_else", + description: r##"Checks for usage of `.map_or_else()` map closure for `Result` type."##, + }, Lint { label: "clippy::unnecessary_safety_comment", description: r##"Checks for `// SAFETY: ` comments on safe code."##, @@ -13499,7 +13684,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::correctness", - description: r##"lint group for: clippy::absurd_extreme_comparisons, clippy::almost_swapped, clippy::approx_constant, clippy::async_yields_async, clippy::bad_bit_mask, clippy::cast_slice_different_sizes, clippy::deprecated_semver, clippy::derive_ord_xor_partial_ord, clippy::derived_hash_with_manual_eq, clippy::enum_clike_unportable_variant, clippy::eq_op, clippy::erasing_op, clippy::fn_address_comparisons, clippy::if_let_mutex, clippy::ifs_same_cond, clippy::impl_hash_borrow_with_str_and_bytes, clippy::impossible_comparisons, clippy::ineffective_bit_mask, clippy::infinite_iter, clippy::inherent_to_string_shadow_display, clippy::inline_fn_without_body, clippy::invalid_null_ptr_usage, clippy::invalid_regex, clippy::invisible_characters, clippy::iter_next_loop, clippy::iter_skip_zero, clippy::iterator_step_by_zero, clippy::let_underscore_lock, clippy::match_str_case_mismatch, clippy::mem_replace_with_uninit, clippy::min_max, clippy::mismatched_target_os, clippy::mistyped_literal_suffixes, clippy::modulo_one, clippy::mut_from_ref, clippy::never_loop, clippy::non_octal_unix_permissions, clippy::nonsensical_open_options, clippy::not_unsafe_ptr_arg_deref, clippy::option_env_unwrap, clippy::out_of_bounds_indexing, clippy::overly_complex_bool_expr, clippy::panicking_unwrap, clippy::possible_missing_comma, clippy::read_line_without_trim, clippy::recursive_format_impl, clippy::redundant_comparisons, clippy::redundant_locals, clippy::reversed_empty_ranges, clippy::self_assignment, clippy::serde_api_misuse, clippy::size_of_in_element_count, clippy::suspicious_splitn, clippy::transmute_null_to_fn, clippy::transmuting_null, clippy::uninit_assumed_init, clippy::uninit_vec, clippy::unit_cmp, clippy::unit_hash, clippy::unit_return_expecting_ord, clippy::unsound_collection_transmute, clippy::unused_io_amount, clippy::useless_attribute, clippy::vec_resize_to_zero, clippy::while_immutable_condition, clippy::wrong_transmute, clippy::zst_offset"##, + description: r##"lint group for: clippy::absurd_extreme_comparisons, clippy::almost_swapped, clippy::approx_constant, clippy::async_yields_async, clippy::bad_bit_mask, clippy::cast_slice_different_sizes, clippy::deprecated_semver, clippy::derive_ord_xor_partial_ord, clippy::derived_hash_with_manual_eq, clippy::eager_transmute, clippy::enum_clike_unportable_variant, clippy::eq_op, clippy::erasing_op, clippy::fn_address_comparisons, clippy::if_let_mutex, clippy::ifs_same_cond, clippy::impl_hash_borrow_with_str_and_bytes, clippy::impossible_comparisons, clippy::ineffective_bit_mask, clippy::infinite_iter, clippy::inherent_to_string_shadow_display, clippy::inline_fn_without_body, clippy::invalid_null_ptr_usage, clippy::invalid_regex, clippy::invisible_characters, clippy::iter_next_loop, clippy::iter_skip_zero, clippy::iterator_step_by_zero, clippy::let_underscore_lock, clippy::lint_groups_priority, clippy::match_str_case_mismatch, clippy::mem_replace_with_uninit, clippy::min_max, clippy::mismatched_target_os, clippy::mistyped_literal_suffixes, clippy::modulo_one, clippy::mut_from_ref, clippy::never_loop, clippy::non_octal_unix_permissions, clippy::nonsensical_open_options, clippy::not_unsafe_ptr_arg_deref, clippy::option_env_unwrap, clippy::out_of_bounds_indexing, clippy::overly_complex_bool_expr, clippy::panicking_unwrap, clippy::possible_missing_comma, clippy::read_line_without_trim, clippy::recursive_format_impl, clippy::redundant_comparisons, clippy::redundant_locals, clippy::reversed_empty_ranges, clippy::self_assignment, clippy::serde_api_misuse, clippy::size_of_in_element_count, clippy::suspicious_splitn, clippy::transmute_null_to_fn, clippy::transmuting_null, clippy::uninit_assumed_init, clippy::uninit_vec, clippy::unit_cmp, clippy::unit_hash, clippy::unit_return_expecting_ord, clippy::unsound_collection_transmute, clippy::unused_io_amount, clippy::useless_attribute, clippy::vec_resize_to_zero, clippy::while_immutable_condition, clippy::wrong_transmute, clippy::zst_offset"##, }, children: &[ "clippy::absurd_extreme_comparisons", @@ -13511,6 +13696,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::deprecated_semver", "clippy::derive_ord_xor_partial_ord", "clippy::derived_hash_with_manual_eq", + "clippy::eager_transmute", "clippy::enum_clike_unportable_variant", "clippy::eq_op", "clippy::erasing_op", @@ -13530,6 +13716,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::iter_skip_zero", "clippy::iterator_step_by_zero", "clippy::let_underscore_lock", + "clippy::lint_groups_priority", "clippy::match_str_case_mismatch", "clippy::mem_replace_with_uninit", "clippy::min_max", @@ -13654,7 +13841,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::pedantic", - description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, + description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_filter_is_ok, clippy::iter_filter_is_some, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_is_variant_and, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_as_ref_cloned, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::pub_underscore_fields, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::str_split_at_newline, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, }, children: &[ "clippy::bool_to_int_with_if", @@ -13694,6 +13881,8 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::into_iter_without_iter", "clippy::invalid_upcast_comparisons", "clippy::items_after_statements", + "clippy::iter_filter_is_ok", + "clippy::iter_filter_is_some", "clippy::iter_not_returning_iterator", "clippy::iter_without_into_iter", "clippy::large_digit_groups", @@ -13704,6 +13893,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::macro_use_imports", "clippy::manual_assert", "clippy::manual_instant_elapsed", + "clippy::manual_is_variant_and", "clippy::manual_let_else", "clippy::manual_ok_or", "clippy::manual_string_new", @@ -13730,9 +13920,11 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::needless_raw_string_hashes", "clippy::no_effect_underscore_binding", "clippy::no_mangle_with_rust_abi", + "clippy::option_as_ref_cloned", "clippy::option_option", "clippy::ptr_as_ptr", "clippy::ptr_cast_constness", + "clippy::pub_underscore_fields", "clippy::range_minus_one", "clippy::range_plus_one", "clippy::redundant_closure_for_method_calls", @@ -13746,6 +13938,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::similar_names", "clippy::single_match_else", "clippy::stable_sort_primitive", + "clippy::str_split_at_newline", "clippy::string_add_assign", "clippy::struct_excessive_bools", "clippy::struct_field_names", @@ -13772,7 +13965,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::perf", - description: r##"lint group for: clippy::box_collection, clippy::box_default, clippy::boxed_local, clippy::cmp_owned, clippy::collapsible_str_replace, clippy::drain_collect, clippy::expect_fun_call, clippy::extend_with_drain, clippy::format_collect, clippy::format_in_format_args, clippy::iter_nth, clippy::iter_overeager_cloned, clippy::large_const_arrays, clippy::large_enum_variant, clippy::manual_memcpy, clippy::manual_retain, clippy::manual_str_repeat, clippy::manual_try_fold, clippy::map_entry, clippy::missing_spin_loop, clippy::redundant_allocation, clippy::result_large_err, clippy::single_char_pattern, clippy::slow_vector_initialization, clippy::to_string_in_format_args, clippy::unnecessary_to_owned, clippy::useless_vec, clippy::vec_init_then_push, clippy::waker_clone_wake"##, + description: r##"lint group for: clippy::box_collection, clippy::box_default, clippy::boxed_local, clippy::cmp_owned, clippy::collapsible_str_replace, clippy::drain_collect, clippy::expect_fun_call, clippy::extend_with_drain, clippy::format_collect, clippy::format_in_format_args, clippy::iter_nth, clippy::iter_overeager_cloned, clippy::large_const_arrays, clippy::large_enum_variant, clippy::manual_memcpy, clippy::manual_retain, clippy::manual_str_repeat, clippy::manual_try_fold, clippy::map_entry, clippy::missing_spin_loop, clippy::redundant_allocation, clippy::result_large_err, clippy::single_char_pattern, clippy::slow_vector_initialization, clippy::thread_local_initializer_can_be_made_const, clippy::to_string_in_format_args, clippy::unnecessary_to_owned, clippy::useless_vec, clippy::vec_init_then_push, clippy::waker_clone_wake"##, }, children: &[ "clippy::box_collection", @@ -13799,6 +13992,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::result_large_err", "clippy::single_char_pattern", "clippy::slow_vector_initialization", + "clippy::thread_local_initializer_can_be_made_const", "clippy::to_string_in_format_args", "clippy::unnecessary_to_owned", "clippy::useless_vec", @@ -13809,7 +14003,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::restriction", - description: r##"lint group for: clippy::absolute_paths, clippy::alloc_instead_of_core, clippy::allow_attributes, clippy::allow_attributes_without_reason, clippy::arithmetic_side_effects, clippy::as_conversions, clippy::as_underscore, clippy::assertions_on_result_states, clippy::big_endian_bytes, clippy::clone_on_ref_ptr, clippy::create_dir, clippy::dbg_macro, clippy::decimal_literal_representation, clippy::default_numeric_fallback, clippy::default_union_representation, clippy::deref_by_slicing, clippy::disallowed_script_idents, clippy::else_if_without_else, clippy::empty_drop, clippy::empty_structs_with_brackets, clippy::error_impl_error, clippy::exhaustive_enums, clippy::exhaustive_structs, clippy::exit, clippy::expect_used, clippy::filetype_is_file, clippy::float_arithmetic, clippy::float_cmp_const, clippy::fn_to_numeric_cast_any, clippy::format_push_string, clippy::get_unwrap, clippy::host_endian_bytes, clippy::if_then_some_else_none, clippy::impl_trait_in_params, clippy::implicit_return, clippy::indexing_slicing, clippy::infinite_loop, clippy::inline_asm_x86_att_syntax, clippy::inline_asm_x86_intel_syntax, clippy::integer_division, clippy::iter_over_hash_type, clippy::large_include_file, clippy::let_underscore_must_use, clippy::let_underscore_untyped, clippy::little_endian_bytes, clippy::lossy_float_literal, clippy::map_err_ignore, clippy::mem_forget, clippy::min_ident_chars, clippy::missing_assert_message, clippy::missing_asserts_for_indexing, clippy::missing_docs_in_private_items, clippy::missing_inline_in_public_items, clippy::missing_trait_methods, clippy::mixed_read_write_in_expression, clippy::mod_module_files, clippy::modulo_arithmetic, clippy::multiple_inherent_impl, clippy::multiple_unsafe_ops_per_block, clippy::mutex_atomic, clippy::needless_raw_strings, clippy::non_ascii_literal, clippy::panic, clippy::panic_in_result_fn, clippy::partial_pub_fields, clippy::pattern_type_mismatch, clippy::print_stderr, clippy::print_stdout, clippy::pub_use, clippy::pub_with_shorthand, clippy::pub_without_shorthand, clippy::question_mark_used, clippy::rc_buffer, clippy::rc_mutex, clippy::redundant_type_annotations, clippy::ref_patterns, clippy::rest_pat_in_fully_bound_structs, clippy::same_name_method, clippy::self_named_module_files, clippy::semicolon_inside_block, clippy::semicolon_outside_block, clippy::separated_literal_suffix, clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated, clippy::single_call_fn, clippy::single_char_lifetime_names, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::str_to_string, clippy::string_add, clippy::string_lit_chars_any, clippy::string_slice, clippy::string_to_string, clippy::suspicious_xor_used_as_pow, clippy::tests_outside_test_module, clippy::todo, clippy::try_err, clippy::undocumented_unsafe_blocks, clippy::unimplemented, clippy::unnecessary_safety_comment, clippy::unnecessary_safety_doc, clippy::unnecessary_self_imports, clippy::unneeded_field_pattern, clippy::unreachable, clippy::unseparated_literal_suffix, clippy::unwrap_in_result, clippy::unwrap_used, clippy::use_debug, clippy::verbose_file_reads, clippy::wildcard_enum_match_arm"##, + description: r##"lint group for: clippy::absolute_paths, clippy::alloc_instead_of_core, clippy::allow_attributes, clippy::allow_attributes_without_reason, clippy::arithmetic_side_effects, clippy::as_conversions, clippy::as_underscore, clippy::assertions_on_result_states, clippy::big_endian_bytes, clippy::clone_on_ref_ptr, clippy::create_dir, clippy::dbg_macro, clippy::decimal_literal_representation, clippy::default_numeric_fallback, clippy::default_union_representation, clippy::deref_by_slicing, clippy::disallowed_script_idents, clippy::else_if_without_else, clippy::empty_drop, clippy::empty_enum_variants_with_brackets, clippy::empty_structs_with_brackets, clippy::error_impl_error, clippy::exhaustive_enums, clippy::exhaustive_structs, clippy::exit, clippy::expect_used, clippy::filetype_is_file, clippy::float_arithmetic, clippy::float_cmp_const, clippy::fn_to_numeric_cast_any, clippy::format_push_string, clippy::get_unwrap, clippy::host_endian_bytes, clippy::if_then_some_else_none, clippy::impl_trait_in_params, clippy::implicit_return, clippy::indexing_slicing, clippy::infinite_loop, clippy::inline_asm_x86_att_syntax, clippy::inline_asm_x86_intel_syntax, clippy::integer_division, clippy::iter_over_hash_type, clippy::large_include_file, clippy::let_underscore_must_use, clippy::let_underscore_untyped, clippy::little_endian_bytes, clippy::lossy_float_literal, clippy::map_err_ignore, clippy::mem_forget, clippy::min_ident_chars, clippy::missing_assert_message, clippy::missing_asserts_for_indexing, clippy::missing_docs_in_private_items, clippy::missing_inline_in_public_items, clippy::missing_trait_methods, clippy::mixed_read_write_in_expression, clippy::mod_module_files, clippy::modulo_arithmetic, clippy::multiple_inherent_impl, clippy::multiple_unsafe_ops_per_block, clippy::mutex_atomic, clippy::needless_raw_strings, clippy::non_ascii_literal, clippy::panic, clippy::panic_in_result_fn, clippy::partial_pub_fields, clippy::pattern_type_mismatch, clippy::print_stderr, clippy::print_stdout, clippy::pub_use, clippy::pub_with_shorthand, clippy::pub_without_shorthand, clippy::question_mark_used, clippy::rc_buffer, clippy::rc_mutex, clippy::redundant_type_annotations, clippy::ref_patterns, clippy::rest_pat_in_fully_bound_structs, clippy::same_name_method, clippy::self_named_module_files, clippy::semicolon_inside_block, clippy::semicolon_outside_block, clippy::separated_literal_suffix, clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated, clippy::single_call_fn, clippy::single_char_lifetime_names, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::str_to_string, clippy::string_add, clippy::string_lit_chars_any, clippy::string_slice, clippy::string_to_string, clippy::suspicious_xor_used_as_pow, clippy::tests_outside_test_module, clippy::todo, clippy::try_err, clippy::undocumented_unsafe_blocks, clippy::unimplemented, clippy::unnecessary_safety_comment, clippy::unnecessary_safety_doc, clippy::unnecessary_self_imports, clippy::unneeded_field_pattern, clippy::unreachable, clippy::unseparated_literal_suffix, clippy::unwrap_in_result, clippy::unwrap_used, clippy::use_debug, clippy::verbose_file_reads, clippy::wildcard_enum_match_arm"##, }, children: &[ "clippy::absolute_paths", @@ -13831,6 +14025,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::disallowed_script_idents", "clippy::else_if_without_else", "clippy::empty_drop", + "clippy::empty_enum_variants_with_brackets", "clippy::empty_structs_with_brackets", "clippy::error_impl_error", "clippy::exhaustive_enums", @@ -13928,7 +14123,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::style", - description: r##"lint group for: clippy::assertions_on_constants, clippy::assign_op_pattern, clippy::blocks_in_conditions, clippy::bool_assert_comparison, clippy::borrow_interior_mutable_const, clippy::builtin_type_shadow, clippy::bytes_nth, clippy::chars_last_cmp, clippy::chars_next_cmp, clippy::cmp_null, clippy::collapsible_else_if, clippy::collapsible_if, clippy::collapsible_match, clippy::comparison_chain, clippy::comparison_to_empty, clippy::declare_interior_mutable_const, clippy::default_instead_of_iter_empty, clippy::disallowed_macros, clippy::disallowed_methods, clippy::disallowed_names, clippy::disallowed_types, clippy::double_must_use, clippy::double_neg, clippy::duplicate_underscore_argument, clippy::enum_variant_names, clippy::err_expect, clippy::excessive_precision, clippy::field_reassign_with_default, clippy::filter_map_bool_then, clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation, clippy::for_kv_map, clippy::from_over_into, clippy::from_str_radix_10, clippy::get_first, clippy::if_same_then_else, clippy::implicit_saturating_add, clippy::implicit_saturating_sub, clippy::inconsistent_digit_grouping, clippy::infallible_destructuring_match, clippy::inherent_to_string, clippy::init_numbered_fields, clippy::into_iter_on_ref, clippy::is_digit_ascii_radix, clippy::items_after_test_module, clippy::iter_cloned_collect, clippy::iter_next_slice, clippy::iter_nth_zero, clippy::iter_skip_next, clippy::just_underscores_and_digits, clippy::len_without_is_empty, clippy::len_zero, clippy::let_and_return, clippy::let_unit_value, clippy::main_recursion, clippy::manual_async_fn, clippy::manual_bits, clippy::manual_is_ascii_check, clippy::manual_is_finite, clippy::manual_is_infinite, clippy::manual_map, clippy::manual_next_back, clippy::manual_non_exhaustive, clippy::manual_range_contains, clippy::manual_saturating_arithmetic, clippy::manual_while_let_some, clippy::map_clone, clippy::map_collect_result_unit, clippy::match_like_matches_macro, clippy::match_overlapping_arm, clippy::match_ref_pats, clippy::match_result_ok, clippy::mem_replace_option_with_none, clippy::mem_replace_with_default, clippy::missing_enforced_import_renames, clippy::missing_safety_doc, clippy::mixed_case_hex_literals, clippy::module_inception, clippy::must_use_unit, clippy::mut_mutex_lock, clippy::needless_borrow, clippy::needless_borrows_for_generic_args, clippy::needless_doctest_main, clippy::needless_else, clippy::needless_late_init, clippy::needless_parens_on_range_literals, clippy::needless_pub_self, clippy::needless_range_loop, clippy::needless_return, clippy::needless_return_with_question_mark, clippy::neg_multiply, clippy::new_ret_no_self, clippy::new_without_default, clippy::non_minimal_cfg, clippy::obfuscated_if_else, clippy::ok_expect, clippy::op_ref, clippy::option_map_or_err_ok, clippy::option_map_or_none, clippy::partialeq_to_none, clippy::print_literal, clippy::print_with_newline, clippy::println_empty_string, clippy::ptr_arg, clippy::ptr_eq, clippy::question_mark, clippy::redundant_closure, clippy::redundant_field_names, clippy::redundant_pattern, clippy::redundant_pattern_matching, clippy::redundant_static_lifetimes, clippy::result_map_or_into_option, clippy::result_unit_err, clippy::same_item_push, clippy::self_named_constructors, clippy::should_implement_trait, clippy::single_char_add_str, clippy::single_component_path_imports, clippy::single_match, clippy::string_extend_chars, clippy::tabs_in_doc_comments, clippy::to_digit_is_some, clippy::toplevel_ref_arg, clippy::trim_split_whitespace, clippy::unnecessary_fallible_conversions, clippy::unnecessary_fold, clippy::unnecessary_lazy_evaluations, clippy::unnecessary_mut_passed, clippy::unnecessary_owned_empty_strings, clippy::unsafe_removed_from_name, clippy::unused_enumerate_index, clippy::unused_unit, clippy::unusual_byte_groupings, clippy::unwrap_or_default, clippy::upper_case_acronyms, clippy::while_let_on_iterator, clippy::write_literal, clippy::write_with_newline, clippy::writeln_empty_string, clippy::wrong_self_convention, clippy::zero_ptr"##, + description: r##"lint group for: clippy::assertions_on_constants, clippy::assign_op_pattern, clippy::blocks_in_conditions, clippy::bool_assert_comparison, clippy::borrow_interior_mutable_const, clippy::builtin_type_shadow, clippy::bytes_nth, clippy::chars_last_cmp, clippy::chars_next_cmp, clippy::cmp_null, clippy::collapsible_else_if, clippy::collapsible_if, clippy::collapsible_match, clippy::comparison_chain, clippy::comparison_to_empty, clippy::declare_interior_mutable_const, clippy::default_instead_of_iter_empty, clippy::disallowed_macros, clippy::disallowed_methods, clippy::disallowed_names, clippy::disallowed_types, clippy::double_must_use, clippy::double_neg, clippy::duplicate_underscore_argument, clippy::enum_variant_names, clippy::err_expect, clippy::excessive_precision, clippy::field_reassign_with_default, clippy::filter_map_bool_then, clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation, clippy::for_kv_map, clippy::from_over_into, clippy::from_str_radix_10, clippy::get_first, clippy::if_same_then_else, clippy::implicit_saturating_add, clippy::implicit_saturating_sub, clippy::inconsistent_digit_grouping, clippy::infallible_destructuring_match, clippy::inherent_to_string, clippy::init_numbered_fields, clippy::into_iter_on_ref, clippy::is_digit_ascii_radix, clippy::items_after_test_module, clippy::iter_cloned_collect, clippy::iter_next_slice, clippy::iter_nth_zero, clippy::iter_skip_next, clippy::just_underscores_and_digits, clippy::len_without_is_empty, clippy::len_zero, clippy::let_and_return, clippy::let_unit_value, clippy::main_recursion, clippy::manual_async_fn, clippy::manual_bits, clippy::manual_is_ascii_check, clippy::manual_is_finite, clippy::manual_is_infinite, clippy::manual_map, clippy::manual_next_back, clippy::manual_non_exhaustive, clippy::manual_range_contains, clippy::manual_saturating_arithmetic, clippy::manual_while_let_some, clippy::map_clone, clippy::map_collect_result_unit, clippy::match_like_matches_macro, clippy::match_overlapping_arm, clippy::match_ref_pats, clippy::match_result_ok, clippy::mem_replace_option_with_none, clippy::mem_replace_with_default, clippy::missing_enforced_import_renames, clippy::missing_safety_doc, clippy::mixed_case_hex_literals, clippy::module_inception, clippy::must_use_unit, clippy::mut_mutex_lock, clippy::needless_borrow, clippy::needless_borrows_for_generic_args, clippy::needless_doctest_main, clippy::needless_else, clippy::needless_late_init, clippy::needless_parens_on_range_literals, clippy::needless_pub_self, clippy::needless_range_loop, clippy::needless_return, clippy::needless_return_with_question_mark, clippy::neg_multiply, clippy::new_ret_no_self, clippy::new_without_default, clippy::non_minimal_cfg, clippy::obfuscated_if_else, clippy::ok_expect, clippy::op_ref, clippy::option_map_or_err_ok, clippy::option_map_or_none, clippy::partialeq_to_none, clippy::print_literal, clippy::print_with_newline, clippy::println_empty_string, clippy::ptr_arg, clippy::ptr_eq, clippy::question_mark, clippy::redundant_closure, clippy::redundant_field_names, clippy::redundant_pattern, clippy::redundant_pattern_matching, clippy::redundant_static_lifetimes, clippy::result_map_or_into_option, clippy::result_unit_err, clippy::same_item_push, clippy::self_named_constructors, clippy::should_implement_trait, clippy::single_char_add_str, clippy::single_component_path_imports, clippy::single_match, clippy::string_extend_chars, clippy::tabs_in_doc_comments, clippy::to_digit_is_some, clippy::to_string_trait_impl, clippy::toplevel_ref_arg, clippy::trim_split_whitespace, clippy::unnecessary_fallible_conversions, clippy::unnecessary_fold, clippy::unnecessary_lazy_evaluations, clippy::unnecessary_mut_passed, clippy::unnecessary_owned_empty_strings, clippy::unsafe_removed_from_name, clippy::unused_enumerate_index, clippy::unused_unit, clippy::unusual_byte_groupings, clippy::unwrap_or_default, clippy::upper_case_acronyms, clippy::while_let_on_iterator, clippy::write_literal, clippy::write_with_newline, clippy::writeln_empty_string, clippy::wrong_self_convention, clippy::zero_ptr"##, }, children: &[ "clippy::assertions_on_constants", @@ -14053,6 +14248,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::string_extend_chars", "clippy::tabs_in_doc_comments", "clippy::to_digit_is_some", + "clippy::to_string_trait_impl", "clippy::toplevel_ref_arg", "clippy::trim_split_whitespace", "clippy::unnecessary_fallible_conversions", @@ -14077,7 +14273,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::suspicious", - description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion"##, + description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::incompatible_msrv, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_open_options, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion, clippy::unnecessary_result_map_or_else"##, }, children: &[ "clippy::almost_complete_range", @@ -14099,6 +14295,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::forget_non_drop", "clippy::four_forward_slashes", "clippy::from_raw_with_void_ptr", + "clippy::incompatible_msrv", "clippy::ineffective_open_options", "clippy::iter_out_of_bounds", "clippy::join_absolute_paths", @@ -14128,12 +14325,14 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::suspicious_else_formatting", "clippy::suspicious_map", "clippy::suspicious_op_assign_impl", + "clippy::suspicious_open_options", "clippy::suspicious_to_owned", "clippy::suspicious_unary_op_formatting", "clippy::swap_ptr_to_ref", "clippy::test_attr_in_doctest", "clippy::type_id_on_box", "clippy::unconditional_recursion", + "clippy::unnecessary_result_map_or_else", ], }, ]; diff --git a/crates/ide/src/folding_ranges.rs b/crates/ide/src/folding_ranges.rs index b863e144f0aca..2bc0721123178 100755 --- a/crates/ide/src/folding_ranges.rs +++ b/crates/ide/src/folding_ranges.rs @@ -494,7 +494,7 @@ fn main() { 2, 3, ], - strustS => StructS { + structS => StructS { a: 31, }, } diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index 4513732902db7..d6c3bd1892693 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs @@ -622,7 +622,7 @@ where struct Converter { current: Option, - current_leafs: Vec>, + current_leaves: Vec>, preorder: PreorderWithTokens, range: TextRange, punct_offset: Option<(SyntaxToken, TextSize)>, @@ -650,7 +650,7 @@ impl Converter { append, remove, call_site, - current_leafs: vec![], + current_leaves: vec![], }; let first = this.next_token(); this.current = first; @@ -665,7 +665,7 @@ impl Converter { self.preorder.skip_subtree(); if let Some(mut v) = self.append.remove(&n.into()) { v.reverse(); - self.current_leafs.extend(v); + self.current_leaves.extend(v); return None; } } @@ -673,7 +673,7 @@ impl Converter { WalkEvent::Leave(ele) => { if let Some(mut v) = self.append.remove(&ele) { v.reverse(); - self.current_leafs.extend(v); + self.current_leaves.extend(v); return None; } } @@ -758,8 +758,8 @@ where } } - if let Some(leaf) = self.current_leafs.pop() { - if self.current_leafs.is_empty() { + if let Some(leaf) = self.current_leaves.pop() { + if self.current_leaves.is_empty() { self.current = self.next_token(); } return Some((SynToken::Leaf(leaf), TextRange::empty(TextSize::new(0)))); diff --git a/crates/proc-macro-api/src/version.rs b/crates/proc-macro-api/src/version.rs index 5ff1f36c545e6..5f81c0a96d967 100644 --- a/crates/proc-macro-api/src/version.rs +++ b/crates/proc-macro-api/src/version.rs @@ -106,9 +106,9 @@ fn read_section<'a>(dylib_binary: &'a [u8], section_name: &str) -> io::Result<&' /// pub fn read_version(dylib_path: &AbsPath) -> io::Result { let dylib_file = File::open(dylib_path)?; - let dylib_mmaped = unsafe { Mmap::map(&dylib_file) }?; + let dylib_mmapped = unsafe { Mmap::map(&dylib_file) }?; - let dot_rustc = read_section(&dylib_mmaped, ".rustc")?; + let dot_rustc = read_section(&dylib_mmapped, ".rustc")?; // check if magic is valid if &dot_rustc[0..4] != b"rust" { diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index b5e3842dd2e66..bc558c202472e 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -245,7 +245,7 @@ As proper cursor positioning is raison d'être for `onEnter`, it uses `SnippetTe * How to deal with synchronicity of the request? One option is to require the client to block until the server returns the response. - Another option is to do a OT-style merging of edits from client and server. + Another option is to do a operational transforms style merging of edits from client and server. A third option is to do a record-replay: client applies heuristic on enter immediately, then applies all user's keypresses. When the server is ready with the response, the client rollbacks all the changes and applies the recorded actions on top of the correct response. * How to deal with multiple carets? diff --git a/docs/dev/style.md b/docs/dev/style.md index 786127639ce75..4c5299bde3e91 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md @@ -99,14 +99,7 @@ Including a description and GIF suitable for the changelog means less work for t ## Clippy -We don't enforce Clippy. -A number of default lints have high false positive rate. -Selectively patching false-positives with `allow(clippy)` is probably worse than entirely disabling a problematic lint. -There's a `cargo lint` command which runs a subset of low-FPR lints. -Careful tweaking of `lint` is welcome. -Of course, applying Clippy suggestions is welcome as long as they indeed improve the code. - -**Rationale:** see [rust-lang/clippy#5537](https://github.com/rust-lang/rust-clippy/issues/5537). +We use Clippy to improve the code, but if some lints annoy you, allow them in the [Cargo.toml](../../Cargo.toml) [workspace.lints.clippy] section. # Code From 70d61418598135b3a26a07c0cfdfb448965f3897 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Fri, 2 Feb 2024 18:23:11 +0800 Subject: [PATCH 214/246] internal: update .typos.tmol --- .typos.toml | 38 +++++++------------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/.typos.toml b/.typos.toml index b46fd902ac970..e638a3e648d68 100644 --- a/.typos.toml +++ b/.typos.toml @@ -1,49 +1,25 @@ [default.extend-identifiers] -makro = "makro" -VisibilityExplicity = "VisibilityExplicity" -impl_froms = "impl_froms" AnserStyle = "AnserStyle" -explicity = "explicity" -syntaxically = "syntaxically" datas = "datas" +impl_froms = "impl_froms" selfs = "selfs" -TOOD = "TOOD" -strustS = "strustS" -new_function_with_generics_and_wheres = "new_function_with_generics_and_wheres" -Defaul = "Defaul" -nto = "nto" -nknown = "nknown" -ded = "ded" -truct = "truct" -inpu = "inpu" -Convertable = "Convertable" -substitude = "substitude" -nner = "nner" -Contro = "Contro" -numbe = "numbe" -MyUnio = "MyUnio" [default.extend-words] anser = "anser" ba = "ba" -fromed = "fromed" fo = "fo" -trivias = "trivias" -mmaped = "mmaped" -mis = "mis" ket = "ket" -foor = "foor" -FPR = "FPR" -mak = "mak" -OT = "OT" +makro = "makro" raison = "raison" -strat = "strat" -unaccessable = "unaccessable" +trivias = "trivias" +TOOD = "TOOD" [default] extend-ignore-re = [ # ignore string which contains $x (x is a num), which use widely in test - ".*\\$\\d.*" + ".*\\$\\d.*", + # ignore generated content like `boxed....nner()`, `Defaul...efault` + "\\w*\\.{3,4}\\w*", ] [files] From a52a4d9ba444b240e913db4effd9faf81c58b242 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Fri, 2 Feb 2024 18:32:20 +0800 Subject: [PATCH 215/246] internal: update typo-check CI setting --- .github/workflows/ci.yaml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index da61627704749..07fa85a61cbd0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -207,24 +207,25 @@ jobs: working-directory: ./editors/code if: needs.changes.outputs.typescript == 'true' - typos-check: - name: Typos Check + typo-check: + name: Typo Check runs-on: ubuntu-latest timeout-minutes: 10 env: FORCE_COLOR: 1 + TYPOS_VERSION: v1.18.0 steps: - - uses: actions/checkout@v4 - - run: curl -LsSf https://github.com/crate-ci/typos/releases/download/v1.17.2/typos-v1.17.2-x86_64-unknown-linux-musl.tar.gz | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin + - name: download typos + run: curl -LsSf https://github.com/crate-ci/typos/releases/download/$TYPOS_VERSION/typos-$TYPOS_VERSION-x86_64-unknown-linux-musl.tar.gz | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - - name: do typos check with typos-cli + - name: check for typos run: typos end-success: name: bors build finished if: github.event.pusher.name == 'bors' && success() runs-on: ubuntu-latest - needs: [rust, rust-cross, typescript, typos-check] + needs: [rust, rust-cross, typescript, typo-check] steps: - name: Mark the job as successful run: exit 0 @@ -233,7 +234,7 @@ jobs: name: bors build finished if: github.event.pusher.name == 'bors' && !success() runs-on: ubuntu-latest - needs: [rust, rust-cross, typescript, typos-check] + needs: [rust, rust-cross, typescript, typo-check] steps: - name: Mark the job as a failure run: exit 1 From 61d1ebe50be6343a3d5ee22db486163ff47e9ff1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Feb 2024 20:12:37 +0100 Subject: [PATCH 216/246] fix typo Co-authored-by: teor --- library/core/src/cmp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 9c18d5573e627..fcb15b7ef65d8 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -87,7 +87,7 @@ use self::Ordering::*; /// *not* do `impl PartialEq for ForeignType`. /// /// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local -/// types `T`, you may assue that no other crate will add `impl`s that allow comparing `T == U`. In +/// types `T`, you may assume that no other crate will add `impl`s that allow comparing `T == U`. In /// other words, if other crates add `impl`s that allow building longer transitive chains `U1 == ... /// == T == V1 == ...`, then all the types that appear to the right of `T` must be types that the /// crate defining `T` already knows about. This rules out transitive chains where downstream crates @@ -967,7 +967,7 @@ pub macro Ord($item:item) { /// *not* do `impl PartialOrd for ForeignType`. /// /// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local -/// types `T`, you may assue that no other crate will add `impl`s that allow comparing `T < U`. In +/// types `T`, you may assume that no other crate will add `impl`s that allow comparing `T < U`. In /// other words, if other crates add `impl`s that allow building longer transitive chains `U1 < ... /// < T < V1 < ...`, then all the types that appear to the right of `T` must be types that the crate /// defining `T` already knows about. This rules out transitive chains where downstream crates can From 30e7b87e2620441c489b0b755ae83e0024821b29 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 2 Feb 2024 21:27:50 +0100 Subject: [PATCH 217/246] miri: normalize struct tail in ABI compat check --- .../src/interpret/terminator.rs | 6 +++++- .../issue-miri-3282-struct-tail-normalize.rs | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/tools/miri/tests/pass/issues/issue-miri-3282-struct-tail-normalize.rs diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 7b993279f18e8..b7ffb4a16fc31 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -373,7 +373,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let (Some(caller), Some(callee)) = (pointee_ty(caller.ty)?, pointee_ty(callee.ty)?) { // This is okay if they have the same metadata type. let meta_ty = |ty: Ty<'tcx>| { - let (meta, only_if_sized) = ty.ptr_metadata_ty(*self.tcx, |ty| ty); + // Even if `ty` is normalized, the search for the unsized tail will project + // to fields, which can yield non-normalized types. So we need to provide a + // normalization function. + let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty); + let (meta, only_if_sized) = ty.ptr_metadata_ty(*self.tcx, normalize); assert!( !only_if_sized, "there should be no more 'maybe has that metadata' types during interpretation" diff --git a/src/tools/miri/tests/pass/issues/issue-miri-3282-struct-tail-normalize.rs b/src/tools/miri/tests/pass/issues/issue-miri-3282-struct-tail-normalize.rs new file mode 100644 index 0000000000000..2a31df83843e6 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-miri-3282-struct-tail-normalize.rs @@ -0,0 +1,20 @@ +// regression test for an ICE: https://github.com/rust-lang/miri/issues/3282 + +trait Id { + type Assoc: ?Sized; +} + +impl Id for T { + type Assoc = T; +} + +#[repr(transparent)] +struct Foo { + field: ::Assoc, +} + +fn main() { + let x = unsafe { std::mem::transmute::)>(|_| ()) }; + let foo: &Foo = unsafe { &*("uwu" as *const str as *const Foo) }; + x(foo); +} From 54c4f9489642068e7e75094316deac9a36b25a2f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Feb 2024 15:03:23 +1100 Subject: [PATCH 218/246] Make some fatal errors more concise. --- compiler/rustc_interface/src/interface.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 5ca8809099675..e364d6624bec8 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -54,11 +54,10 @@ pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec) -> Cfg { ($reason: expr) => { #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] - dcx.struct_fatal(format!( + dcx.fatal(format!( concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s - )) - .emit(); + )); }; } @@ -117,11 +116,10 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { ($reason:expr) => { #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] - dcx.struct_fatal(format!( + dcx.fatal(format!( concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), s )) - .emit() }; } From 585367f15f9fe7f4b169f6a157d087c0586c4ee1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Feb 2024 15:09:44 +1100 Subject: [PATCH 219/246] Remove an out-of-date comment. `DiagnosticBuilderInner` was removed some time ago. --- compiler/rustc_errors/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 901fe3fb79930..668c10bc4b6df 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -102,7 +102,6 @@ pub type PResult<'a, T> = Result>; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. -// (See also the comment on `DiagnosticBuilderInner`'s `diagnostic` field.) #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16); #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] From a9a2e1565abbeae741d6d715224194caf500099b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Feb 2024 19:17:39 +1100 Subject: [PATCH 220/246] `Diagnostic` cleanups - `emitted_at` isn't used outside the crate. - `code` and `messages` are public fields, so there's no point have trivial getters/setters for them. - `suggestions` is public, so the comment about "functionality on `Diagnostic`" isn't needed. --- compiler/rustc_codegen_llvm/src/errors.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 18 +----------------- compiler/rustc_errors/src/lib.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 1 - compiler/rustc_hir_typeck/src/pat.rs | 6 +++--- .../infer/error_reporting/note_and_explain.rs | 4 ++-- .../src/traits/error_reporting/suggestions.rs | 2 +- 7 files changed, 9 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index d82ff6656f4d3..e839d278bea7c 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -102,7 +102,7 @@ pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>); impl IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_> { fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let diag: DiagnosticBuilder<'_, G> = self.0.into_diagnostic(dcx, level); - let (message, _) = diag.messages().first().expect("`LlvmError` with no message"); + let (message, _) = diag.messages.first().expect("`LlvmError` with no message"); let message = dcx.eagerly_translate_to_string(message.clone(), diag.args()); DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 6deaaef780d41..789889973e2dc 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -116,7 +116,7 @@ pub struct Diagnostic { /// With `-Ztrack_diagnostics` enabled, /// we print where in rustc this error was emitted. - pub emitted_at: DiagnosticLocation, + pub(crate) emitted_at: DiagnosticLocation, } #[derive(Clone, Debug, Encodable, Decodable)] @@ -206,9 +206,6 @@ impl StringPart { } } -// Note: most of these methods are setters that return `&mut Self`. The small -// number of simple getter functions all have `get_` prefixes to distinguish -// them from the setters. impl Diagnostic { #[track_caller] pub fn new>(level: Level, message: M) -> Self { @@ -889,15 +886,6 @@ impl Diagnostic { self } - pub fn clear_code(&mut self) -> &mut Self { - self.code = None; - self - } - - pub fn get_code(&self) -> Option { - self.code - } - pub fn primary_message(&mut self, msg: impl Into) -> &mut Self { self.messages[0] = (msg.into(), Style::NoStyle); self @@ -923,10 +911,6 @@ impl Diagnostic { self.args = args; } - pub fn messages(&self) -> &[(DiagnosticMessage, Style)] { - &self.messages - } - /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by /// combining it with the primary message of the diagnostic (if translatable, otherwise it just /// passes the user's string along). diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 668c10bc4b6df..61fe00408635d 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1422,7 +1422,7 @@ impl DiagCtxtInner { &mut out, "delayed span bug: {}\n{}\n", bug.inner - .messages() + .messages .iter() .filter_map(|(msg, _)| msg.as_str()) .collect::(), diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 3674a760cbf9d..5cdcc1bb860b2 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -590,7 +590,6 @@ fn infer_placeholder_type<'a>( // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type. // We are typeck and have the real type, so remove that and suggest the actual type. - // FIXME(eddyb) this looks like it should be functionality on `Diagnostic`. if let Ok(suggestions) = &mut err.suggestions { suggestions.clear(); } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index b7f28ef958aa8..fcf4b59e93fcd 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -576,7 +576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if (lhs, rhs).references_error() { err.downgrade_to_delayed_bug(); } - if self.tcx.sess.teach(err.get_code().unwrap()) { + if self.tcx.sess.teach(err.code.unwrap()) { err.note( "In a match expression, only numbers and characters can be matched \ against a range. This is because the compiler checks that the range \ @@ -847,7 +847,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { type_str ); err.span_label(span, format!("type `{type_str}` cannot be dereferenced")); - if self.tcx.sess.teach(err.get_code().unwrap()) { + if self.tcx.sess.teach(err.code.unwrap()) { err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ); } return Err(err.emit()); @@ -1669,7 +1669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - if tcx.sess.teach(err.get_code().unwrap()) { + if tcx.sess.teach(err.code.unwrap()) { err.note( "This error indicates that a struct pattern attempted to \ extract a nonexistent field from a struct. Struct fields \ diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 0e7c641e0e0b8..0452d4fe6c806 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -195,7 +195,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } diag.help("type parameters must be constrained to match other types"); - if tcx.sess.teach(diag.get_code().unwrap()) { + if tcx.sess.teach(diag.code.unwrap()) { diag.help( "given a type parameter `T` and a method `foo`: ``` @@ -678,7 +678,7 @@ impl Trait for X { https://doc.rust-lang.org/book/ch19-03-advanced-traits.html", ); } - if tcx.sess.teach(diag.get_code().unwrap()) { + if tcx.sess.teach(diag.code.unwrap()) { diag.help( "given an associated type `T` and a method `foo`: ``` diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 5bab57ca56cb4..2dec27a6126b3 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2717,7 +2717,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let (trait_name, trait_verb) = if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") }; - err.clear_code(); + err.code = None; err.primary_message(format!( "{future_or_coroutine} cannot be {trait_verb} between threads safely" )); From 8ba25d0989f8d96cbcb4365fc61b469575e22d63 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Feb 2024 19:18:25 +1100 Subject: [PATCH 221/246] `SilentEmitter::fatal_note` doesn't need to be optional. --- compiler/rustc_errors/src/emitter.rs | 14 ++++++-------- compiler/rustc_interface/src/interface.rs | 8 ++++---- compiler/rustc_session/src/parse.rs | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 9f76c1dd248b0..4be5ed923e5e0 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -558,7 +558,7 @@ impl Emitter for HumanEmitter { /// failures of rustc, as witnessed e.g. in issue #89358. pub struct SilentEmitter { pub fatal_dcx: DiagCtxt, - pub fatal_note: Option, + pub fatal_note: String, } impl Translate for SilentEmitter { @@ -576,13 +576,11 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, d: &Diagnostic) { - if d.level == Level::Fatal { - let mut d = d.clone(); - if let Some(ref note) = self.fatal_note { - d.note(note.clone()); - } - self.fatal_dcx.emit_diagnostic(d); + fn emit_diagnostic(&mut self, diag: &Diagnostic) { + if diag.level == Level::Fatal { + let mut diag = diag.clone(); + diag.note(self.fatal_note.clone()); + self.fatal_dcx.emit_diagnostic(diag); } } } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index e364d6624bec8..8a4705e0056e1 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -45,9 +45,9 @@ pub struct Compiler { pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec) -> Cfg { cfgs.into_iter() .map(|s| { - let sess = ParseSess::with_silent_emitter(Some(format!( + let sess = ParseSess::with_silent_emitter(format!( "this error occurred on the command line: `--cfg={s}`" - ))); + )); let filename = FileName::cfg_spec_source_code(&s); macro_rules! error { @@ -107,9 +107,9 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() }; for s in specs { - let sess = ParseSess::with_silent_emitter(Some(format!( + let sess = ParseSess::with_silent_emitter(format!( "this error occurred on the command line: `--check-cfg={s}`" - ))); + )); let filename = FileName::cfg_spec_source_code(&s); macro_rules! error { diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 1cfaa49401dac..8adb0cbcc9d76 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -258,7 +258,7 @@ impl ParseSess { } } - pub fn with_silent_emitter(fatal_note: Option) -> Self { + pub fn with_silent_emitter(fatal_note: String) -> Self { let fallback_bundle = fallback_fluent_bundle(Vec::new(), false); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let fatal_dcx = DiagCtxt::with_tty_emitter(None, fallback_bundle).disable_warnings(); From df322fc29ffc984d488bbaf3a58e95c4002d4b7e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Feb 2024 09:19:22 +1100 Subject: [PATCH 222/246] Remove some unnecessary `clone` calls. --- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_errors/src/lib.rs | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 06edb79453727..eeb251320a781 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1817,7 +1817,7 @@ impl Emitter for SharedEmitter { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { msgs: diag.messages.clone(), args: args.clone(), - code: diag.code.clone(), + code: diag.code, lvl: diag.level(), }))); for child in &diag.children { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 61fe00408635d..ac18902866da1 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1252,7 +1252,7 @@ impl DiagCtxtInner { // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by // a stable one by the `LintLevelsBuilder`. if let Some(LintExpectationId::Unstable { .. }) = diagnostic.level.get_expectation_id() { - self.unstable_expect_diagnostics.push(diagnostic.clone()); + self.unstable_expect_diagnostics.push(diagnostic); return None; } @@ -1267,16 +1267,14 @@ impl DiagCtxtInner { DelayedBug(DelayedBugKind::Normal) => { let backtrace = std::backtrace::Backtrace::capture(); self.span_delayed_bugs - .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace)); - + .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); #[allow(deprecated)] return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); } DelayedBug(DelayedBugKind::GoodPath) => { let backtrace = std::backtrace::Backtrace::capture(); self.good_path_delayed_bugs - .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace)); - + .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); return None; } _ => {} From 6fdaf3ef7fb5ea72345520a1219ea5cc77d0f71c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Feb 2024 10:14:14 +1100 Subject: [PATCH 223/246] Use `DiagnosticArgName` in a few more places. --- compiler/rustc_codegen_ssa/src/back/write.rs | 3 +-- compiler/rustc_const_eval/src/const_eval/error.rs | 9 ++++----- compiler/rustc_errors/src/diagnostic.rs | 2 +- compiler/rustc_middle/src/error.rs | 7 +++---- compiler/rustc_middle/src/mir/interpret/error.rs | 6 ++++-- compiler/rustc_middle/src/mir/mod.rs | 4 +++- compiler/rustc_middle/src/mir/terminator.rs | 2 +- compiler/rustc_mir_transform/src/const_prop.rs | 2 +- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index eeb251320a781..4211f875dd01a 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -39,7 +39,6 @@ use rustc_target::spec::{MergeFunctions, SanitizerSet}; use crate::errors::ErrorCreatingRemarkDir; use std::any::Any; -use std::borrow::Cow; use std::fs; use std::io; use std::marker::PhantomData; @@ -1812,7 +1811,7 @@ impl Translate for SharedEmitter { impl Emitter for SharedEmitter { fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { - let args: FxHashMap, DiagnosticArgValue> = + let args: FxHashMap = diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect(); drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { msgs: diag.messages.clone(), diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index dabf78ef90e5f..1ebc82ad6d4b2 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -1,6 +1,8 @@ use std::mem; -use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, IntoDiagnostic, IntoDiagnosticArg}; +use rustc_errors::{ + DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage, IntoDiagnostic, IntoDiagnosticArg, +}; use rustc_hir::CRATE_HIR_ID; use rustc_middle::mir::AssertKind; use rustc_middle::query::TyCtxtAt; @@ -32,10 +34,7 @@ impl MachineStopType for ConstEvalErrKind { AssertFailure(x) => x.diagnostic_message(), } } - fn add_args( - self: Box, - adder: &mut dyn FnMut(std::borrow::Cow<'static, str>, DiagnosticArgValue), - ) { + fn add_args(self: Box, adder: &mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue)) { use ConstEvalErrKind::*; match *self { ConstAccessesStatic | ModifiedGlobal => {} diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 789889973e2dc..5579b50e85a90 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -900,7 +900,7 @@ impl Diagnostic { pub fn arg( &mut self, - name: impl Into>, + name: impl Into, arg: impl IntoDiagnosticArg, ) -> &mut Self { self.args.insert(name.into(), arg.into_diagnostic_arg()); diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 211da80020297..3ebbcd650302f 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -1,7 +1,6 @@ -use std::borrow::Cow; use std::fmt; -use rustc_errors::{codes::*, DiagnosticArgValue, DiagnosticMessage}; +use rustc_errors::{codes::*, DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage}; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -95,14 +94,14 @@ pub(super) struct ConstNotUsedTraitAlias { pub struct CustomSubdiagnostic<'a> { pub msg: fn() -> DiagnosticMessage, - pub add_args: Box, DiagnosticArgValue)) + 'a>, + pub add_args: Box, } impl<'a> CustomSubdiagnostic<'a> { pub fn label(x: fn() -> DiagnosticMessage) -> Self { Self::label_and_then(x, |_| {}) } - pub fn label_and_then, DiagnosticArgValue)) + 'a>( + pub fn label_and_then( msg: fn() -> DiagnosticMessage, f: F, ) -> Self { diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 95574aee499f2..0f69ab93452f7 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -5,7 +5,9 @@ use crate::mir::{ConstAlloc, ConstValue}; use crate::ty::{layout, tls, Ty, TyCtxt, ValTree}; use rustc_data_structures::sync::Lock; -use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg}; +use rustc_errors::{ + DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, +}; use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; use rustc_span::{def_id::DefId, Span, DUMMY_SP}; @@ -485,7 +487,7 @@ pub trait MachineStopType: Any + fmt::Debug + Send { fn diagnostic_message(&self) -> DiagnosticMessage; /// Add diagnostic arguments by passing name and value pairs to `adder`, which are passed to /// fluent for formatting the translated diagnostic message. - fn add_args(self: Box, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue)); + fn add_args(self: Box, adder: &mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue)); } impl dyn MachineStopType { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 37c5bba46a7d8..c9e69253701c5 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -14,7 +14,9 @@ use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex}; use crate::ty::{GenericArg, GenericArgsRef}; use rustc_data_structures::captures::Captures; -use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg}; +use rustc_errors::{ + DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, +}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::{self, CoroutineDesugaring, CoroutineKind, ImplicitSelfKind}; diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 0fe33e441f430..91b7952bec5e8 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -292,7 +292,7 @@ impl AssertKind { } } - pub fn add_args(self, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue)) + pub fn add_args(self, adder: &mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue)) where O: fmt::Debug, { diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index c49f92f4f859f..eba62aae60f75 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -34,7 +34,7 @@ pub(crate) macro throw_machine_stop_str($($tt:tt)*) {{ fn add_args( self: Box, - _: &mut dyn FnMut(std::borrow::Cow<'static, str>, rustc_errors::DiagnosticArgValue), + _: &mut dyn FnMut(rustc_errors::DiagnosticArgName, rustc_errors::DiagnosticArgValue), ) {} } throw_machine_stop!(Zst) From cd4c5cd8b8ca96ba1a5a48d287140a85e3984a8b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Feb 2024 10:15:03 +1100 Subject: [PATCH 224/246] Improve a local variable name. --- compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 0a6b758efa564..5eb85d59feef9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -198,12 +198,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { let span = self.body.local_decls[local].source_info.span; mut_error = Some(span); - if let Some((buffer, c)) = self.get_buffered_mut_error(span) { + if let Some((buffered_err, c)) = self.get_buffered_mut_error(span) { // We've encountered a second (or more) attempt to mutably borrow an // immutable binding, so the likely problem is with the binding // declaration, not the use. We collect these in a single diagnostic // and make the binding the primary span of the error. - err = buffer; + err = buffered_err; count = c + 1; if count == 2 { err.replace_span_with(span, false); From b506cce5792d543cf5ffa828f539c950b9739b2c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Feb 2024 10:15:53 +1100 Subject: [PATCH 225/246] Fix an incorrect comment. --- compiler/rustc_parse/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 49e036c380133..d5fa11086872f 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -39,7 +39,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } // uses a HOF to parse anything, and includes file and // `source_str`. -/// A variant of 'panictry!' that works on a `Vec` instead of a single +/// A variant of 'panictry!' that works on a `Vec` instead of a single /// `DiagnosticBuilder`. macro_rules! panictry_buffer { ($e:expr) => {{ From 0621cd46f2ee2711cf2f808521629d223fda8d54 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Feb 2024 14:30:37 +1100 Subject: [PATCH 226/246] Simplify future breakage control flow. `emit_future_breakage` calls `self.dcx().take_future_breakage_diagnostics()` and then passes the result to `self.dcx().emit_future_breakage_report(diags)`. This commit removes the first of these and lets `emit_future_breakage_report` do the taking. It also inlines and removes what is left of `emit_future_breakage`, which has a single call site. --- compiler/rustc_errors/src/lib.rs | 12 ++++++------ compiler/rustc_session/src/session.rs | 14 ++------------ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ac18902866da1..699691c5dabc3 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1038,10 +1038,6 @@ impl DiagCtxt { } } - pub fn take_future_breakage_diagnostics(&self) -> Vec { - std::mem::take(&mut self.inner.borrow_mut().future_breakage_diagnostics) - } - pub fn abort_if_errors(&self) { let mut inner = self.inner.borrow_mut(); inner.emit_stashed_diagnostics(); @@ -1149,8 +1145,12 @@ impl DiagCtxt { self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type); } - pub fn emit_future_breakage_report(&self, diags: Vec) { - self.inner.borrow_mut().emitter.emit_future_breakage_report(diags) + pub fn emit_future_breakage_report(&self) { + let mut inner = self.inner.borrow_mut(); + let diags = std::mem::take(&mut inner.future_breakage_diagnostics); + if !diags.is_empty() { + inner.emitter.emit_future_breakage_report(diags); + } } pub fn emit_unused_externs( diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 3a0ae74dd9215..f6af5a4f87e07 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -288,19 +288,9 @@ impl Session { pub fn finish_diagnostics(&self, registry: &Registry) { self.check_miri_unleashed_features(); self.dcx().print_error_count(registry); - self.emit_future_breakage(); - } - - fn emit_future_breakage(&self) { - if !self.opts.json_future_incompat { - return; - } - - let diags = self.dcx().take_future_breakage_diagnostics(); - if diags.is_empty() { - return; + if self.opts.json_future_incompat { + self.dcx().emit_future_breakage_report(); } - self.dcx().emit_future_breakage_report(diags); } /// Returns true if the crate is a testing one. From be648028547291dfe64938a0c059640a629ea0b2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 3 Feb 2024 09:02:36 +1100 Subject: [PATCH 227/246] Use `StringPart` more. --- compiler/rustc_errors/src/diagnostic.rs | 55 +++++++++---------- compiler/rustc_errors/src/lib.rs | 2 +- .../error_reporting/type_err_ctxt_ext.rs | 24 ++++---- 3 files changed, 38 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 5579b50e85a90..8ad4925cff288 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -165,10 +165,10 @@ impl DiagnosticStyledString { DiagnosticStyledString(vec![]) } pub fn push_normal>(&mut self, t: S) { - self.0.push(StringPart::normal(t.into())); + self.0.push(StringPart::normal(t)); } pub fn push_highlighted>(&mut self, t: S) { - self.0.push(StringPart::highlighted(t.into())); + self.0.push(StringPart::highlighted(t)); } pub fn push>(&mut self, t: S, highlight: bool) { if highlight { @@ -178,11 +178,11 @@ impl DiagnosticStyledString { } } pub fn normal>(t: S) -> DiagnosticStyledString { - DiagnosticStyledString(vec![StringPart::normal(t.into())]) + DiagnosticStyledString(vec![StringPart::normal(t)]) } pub fn highlighted>(t: S) -> DiagnosticStyledString { - DiagnosticStyledString(vec![StringPart::highlighted(t.into())]) + DiagnosticStyledString(vec![StringPart::highlighted(t)]) } pub fn content(&self) -> String { @@ -197,12 +197,12 @@ pub struct StringPart { } impl StringPart { - fn normal(content: String) -> StringPart { - StringPart { content, style: Style::NoStyle } + pub fn normal>(content: S) -> StringPart { + StringPart { content: content.into(), style: Style::NoStyle } } - fn highlighted(content: String) -> StringPart { - StringPart { content, style: Style::Highlight } + pub fn highlighted>(content: S) -> StringPart { + StringPart { content: content.into(), style: Style::Highlight } } } @@ -391,13 +391,16 @@ impl Diagnostic { } else { (0, found_label.len() - expected_label.len()) }; - let mut msg: Vec<_> = - vec![(format!("{}{} `", " ".repeat(expected_padding), expected_label), Style::NoStyle)]; - msg.extend(expected.0.into_iter().map(|p| (p.content, p.style))); - msg.push((format!("`{expected_extra}\n"), Style::NoStyle)); - msg.push((format!("{}{} `", " ".repeat(found_padding), found_label), Style::NoStyle)); - msg.extend(found.0.into_iter().map(|p| (p.content, p.style))); - msg.push((format!("`{found_extra}"), Style::NoStyle)); + let mut msg = vec![StringPart::normal(format!( + "{}{} `", + " ".repeat(expected_padding), + expected_label + ))]; + msg.extend(expected.0.into_iter()); + msg.push(StringPart::normal(format!("`{expected_extra}\n"))); + msg.push(StringPart::normal(format!("{}{} `", " ".repeat(found_padding), found_label))); + msg.extend(found.0.into_iter()); + msg.push(StringPart::normal(format!("`{found_extra}"))); // For now, just attach these as notes. self.highlighted_note(msg); @@ -406,9 +409,9 @@ impl Diagnostic { pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self { self.highlighted_note(vec![ - (format!("`{name}` from trait: `"), Style::NoStyle), - (signature, Style::Highlight), - ("`".to_string(), Style::NoStyle), + StringPart::normal(format!("`{name}` from trait: `")), + StringPart::highlighted(signature), + StringPart::normal("`"), ]); self } @@ -420,10 +423,7 @@ impl Diagnostic { self } - fn highlighted_note>( - &mut self, - msg: Vec<(M, Style)>, - ) -> &mut Self { + fn highlighted_note(&mut self, msg: Vec) -> &mut Self { self.sub_with_highlights(Level::Note, msg, MultiSpan::new()); self } @@ -492,7 +492,7 @@ impl Diagnostic { } /// Add a help message attached to this diagnostic with a customizable highlighted message. - pub fn highlighted_help(&mut self, msg: Vec<(String, Style)>) -> &mut Self { + pub fn highlighted_help(&mut self, msg: Vec) -> &mut Self { self.sub_with_highlights(Level::Help, msg, MultiSpan::new()); self } @@ -941,15 +941,10 @@ impl Diagnostic { /// Convenience function for internal use, clients should use one of the /// public methods above. - fn sub_with_highlights>( - &mut self, - level: Level, - messages: Vec<(M, Style)>, - span: MultiSpan, - ) { + fn sub_with_highlights(&mut self, level: Level, messages: Vec, span: MultiSpan) { let messages = messages .into_iter() - .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.0), m.1)) + .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.content), m.style)) .collect(); let sub = SubDiagnostic { level, messages, span }; self.children.push(sub); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 699691c5dabc3..b2bd4d8eb956e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -34,7 +34,7 @@ extern crate self as rustc_errors; pub use codes::*; pub use diagnostic::{ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgName, - DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, + DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, StringPart, SubDiagnostic, }; pub use diagnostic_builder::{ BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort, IntoDiagnostic, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index dee3e14f3c918..d9c5de17af885 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -20,7 +20,7 @@ use crate::traits::{ use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::{ codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, MultiSpan, StashKey, Style, + ErrorGuaranteed, MultiSpan, StashKey, StringPart, }; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, Res}; @@ -2059,11 +2059,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()), }); err.highlighted_help(vec![ - (format!("the trait `{}` ", cand.print_trait_sugared()), Style::NoStyle), - ("is".to_string(), Style::Highlight), - (" implemented for `".to_string(), Style::NoStyle), - (cand.self_ty().to_string(), Style::Highlight), - ("`".to_string(), Style::NoStyle), + StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())), + StringPart::highlighted("is"), + StringPart::normal(" implemented for `"), + StringPart::highlighted(cand.self_ty().to_string()), + StringPart::normal("`"), ]); if let [TypeError::Sorts(exp_found)] = &terrs[..] { @@ -2095,12 +2095,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { _ => (" implemented for `", ""), }; err.highlighted_help(vec![ - (format!("the trait `{}` ", cand.print_trait_sugared()), Style::NoStyle), - ("is".to_string(), Style::Highlight), - (desc.to_string(), Style::NoStyle), - (cand.self_ty().to_string(), Style::Highlight), - ("`".to_string(), Style::NoStyle), - (mention_castable.to_string(), Style::NoStyle), + StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())), + StringPart::highlighted("is"), + StringPart::normal(desc), + StringPart::highlighted(cand.self_ty().to_string()), + StringPart::normal("`"), + StringPart::normal(mention_castable), ]); return true; } From ef37dcb7dbb444751b825adb55f2246b4fa3a52b Mon Sep 17 00:00:00 2001 From: trevyn <230691+trevyn@users.noreply.github.com> Date: Fri, 2 Feb 2024 15:16:05 -0800 Subject: [PATCH 228/246] Remove unnecessary `.to_string()`/`.as_str()`s --- compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs | 2 +- .../rustc_borrowck/src/diagnostics/mutability_errors.rs | 2 +- compiler/rustc_hir_analysis/src/astconv/errors.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_hir_typeck/src/method/suggest.rs | 6 +++--- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/generics.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 4 ++-- .../src/traits/error_reporting/suggestions.rs | 6 +++--- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2e83072b8d132..c77479d66604e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2440,7 +2440,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "consider consuming the `{ty}` when turning it into an \ `Iterator`", ), - "into_iter".to_string(), + "into_iter", Applicability::MaybeIncorrect, ); } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 0a6b758efa564..aa2503a29ab95 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -924,7 +924,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.span_suggestion_verbose( expr.span.shrink_to_lo(), "use a mutable iterator instead", - "mut ".to_string(), + "mut ", Applicability::MachineApplicable, ); } diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 407517b15ef5e..e67a44d96ad43 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -247,7 +247,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.span_suggestion_verbose( assoc_name.span, fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg, - suggested_name.to_string(), + suggested_name, Applicability::MaybeIncorrect, ); } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 2bbef11fa2450..1adde8c21b8e2 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1000,7 +1000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion_verbose( lhs.span.shrink_to_hi(), "you might have meant to write a semicolon here", - ";".to_string(), + ";", Applicability::MachineApplicable, ); return true; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 6c9501e93fa11..904961d9eba26 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1116,9 +1116,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name.span, format!( "you might have meant to use `{}`", - inherent_method.name.as_str() + inherent_method.name ), - inherent_method.name.as_str(), + inherent_method.name, Applicability::MaybeIncorrect, ); break 'outer; @@ -2019,7 +2019,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diag.span_suggestion_verbose( sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(), "you may have meant to call an instance method", - ".".to_string(), + ".", Applicability::MaybeIncorrect, ); } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9f748e2a3feb1..e36a648e2032e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3288,7 +3288,7 @@ impl<'a> Parser<'a> { } else { Applicability::MaybeIncorrect }; - err.span_suggestion_verbose(sugg_sp, msg, "=> ".to_string(), applicability); + err.span_suggestion_verbose(sugg_sp, msg, "=> ", applicability); } } err diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 48cf04f7790d0..e059e7074910a 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -148,7 +148,7 @@ impl<'a> Parser<'a> { .with_span_suggestion_verbose( mistyped_const_ident.span, "use the `const` keyword", - kw::Const.as_str(), + kw::Const, Applicability::MachineApplicable, ) .emit(); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 9a77643f9510f..8050b34956ce9 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1453,7 +1453,7 @@ impl<'a> Parser<'a> { err.span_suggestion_verbose( prev_span, "perhaps you meant to use `struct` here", - "struct".to_string(), + "struct", Applicability::MaybeIncorrect, ); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a4c041f1ff247..c2228edb97458 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -699,7 +699,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err.span_suggestion_verbose( span.shrink_to_lo(), msg, - "self.".to_string(), + "self.", Applicability::MachineApplicable, ); } @@ -710,7 +710,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err.span_suggestion_verbose( span.shrink_to_lo(), format!("you might have meant to {}", candidate.action()), - "Self::".to_string(), + "Self::", Applicability::MachineApplicable, ); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 5bab57ca56cb4..a49c446aa0fb2 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1288,7 +1288,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.span_suggestion_verbose( obligation.cause.span.shrink_to_hi(), "consider using clone here", - ".clone()".to_string(), + ".clone()", Applicability::MaybeIncorrect, ); return true; @@ -3245,7 +3245,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.span_suggestion_verbose( span, "you can use `impl Trait` as the argument type", - "impl ".to_string(), + "impl ", Applicability::MaybeIncorrect, ); let sugg = if !needs_parens { @@ -5203,7 +5203,7 @@ fn point_at_assoc_type_restriction( err.span_suggestion_verbose( path.span, "replace the associated type with the type specified in this `impl`", - tcx.type_of(new.def_id).skip_binder().to_string(), + tcx.type_of(new.def_id).skip_binder(), Applicability::MachineApplicable, ); } From a27e45a71bd9743cebfbac74ccd3d0f50cc1a190 Mon Sep 17 00:00:00 2001 From: Conrad Ludgate Date: Sat, 3 Feb 2024 11:30:26 +0000 Subject: [PATCH 229/246] fix #120603 by adding a check in default_read_buf --- library/std/src/io/mod.rs | 7 ++++++- library/std/src/io/tests.rs | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 8fca66fa17c5e..d84b0766f363f 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -578,8 +578,13 @@ where F: FnOnce(&mut [u8]) -> Result, { let n = read(cursor.ensure_init().init_mut())?; + assert!( + n <= cursor.capacity(), + "read should not return more bytes than there is capacity for in the read buffer" + ); unsafe { - // SAFETY: we initialised using `ensure_init` so there is no uninit data to advance to. + // SAFETY: we initialised using `ensure_init` so there is no uninit data to advance to + // and we have checked that the read amount is not over capacity (see #120603) cursor.advance(n); } Ok(()) diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index bda5b721adc63..c0179f7f22783 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -652,3 +652,19 @@ fn bench_take_read_buf(b: &mut test::Bencher) { [255; 128].take(64).read_buf(buf.unfilled()).unwrap(); }); } + +// Issue #120603 +#[test] +#[should_panic = "read should not return more bytes than there is capacity for in the read buffer"] +fn read_buf_broken_read() { + struct MalformedRead; + + impl Read for MalformedRead { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + // broken length calculation + Ok(buf.len() + 1) + } + } + + BufReader::new(MalformedRead).read(&mut [0; 4]).unwrap(); +} From 4c694db25270243597657ec73ec9912f2ddfb0cc Mon Sep 17 00:00:00 2001 From: Conrad Ludgate Date: Sat, 3 Feb 2024 11:44:13 +0000 Subject: [PATCH 230/246] add another test to make sure it still works with full reads --- library/std/src/io/tests.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index c0179f7f22783..33e9d8efed511 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -1,6 +1,6 @@ use super::{repeat, BorrowedBuf, Cursor, SeekFrom}; use crate::cmp::{self, min}; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, IoSlice, IoSliceMut, DEFAULT_BUF_SIZE}; use crate::io::{BufRead, BufReader, Read, Seek, Write}; use crate::mem::MaybeUninit; use crate::ops::Deref; @@ -666,5 +666,18 @@ fn read_buf_broken_read() { } } - BufReader::new(MalformedRead).read(&mut [0; 4]).unwrap(); + let _ = BufReader::new(MalformedRead).fill_buf(); +} + +#[test] +fn read_buf_full_read() { + struct FullRead; + + impl Read for FullRead { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + Ok(buf.len()) + } + } + + assert_eq!(BufReader::new(FullRead).fill_buf().unwrap().len(), DEFAULT_BUF_SIZE); } From c5eca333fc8ad2b3f7d45d3a0af59d1cf83df23c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 3 Feb 2024 15:50:14 +0300 Subject: [PATCH 231/246] hir: Remove the generic type parameter from `MaybeOwned` It's only ever used with a reference to `OwnerInfo` as an argument. --- compiler/rustc_ast_lowering/src/item.rs | 7 ++----- compiler/rustc_ast_lowering/src/lib.rs | 4 ++-- compiler/rustc_hir/src/hir.rs | 25 +++++++----------------- compiler/rustc_middle/src/hir/mod.rs | 9 ++++----- compiler/rustc_middle/src/query/erase.rs | 4 ++-- 5 files changed, 17 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index dd3f7289a60b2..6b772c1295f55 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -25,7 +25,7 @@ pub(super) struct ItemLowerer<'a, 'hir> { pub(super) tcx: TyCtxt<'hir>, pub(super) resolver: &'a mut ResolverAstLowering, pub(super) ast_index: &'a IndexSlice>, - pub(super) owners: &'a mut IndexVec>>, + pub(super) owners: &'a mut IndexVec>, } /// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span @@ -64,10 +64,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } } - pub(super) fn lower_node( - &mut self, - def_id: LocalDefId, - ) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> { + pub(super) fn lower_node(&mut self, def_id: LocalDefId) -> hir::MaybeOwner<'hir> { let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); if let hir::MaybeOwner::Phantom = owner { let node = self.ast_index[def_id]; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3621844efc8d2..f26b1331ef388 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -99,7 +99,7 @@ struct LoweringContext<'a, 'hir> { /// Attributes inside the owner being lowered. attrs: SortedMap, /// Collect items that were created by lowering the current owner. - children: Vec<(LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>)>, + children: Vec<(LocalDefId, hir::MaybeOwner<'hir>)>, coroutine_kind: Option, @@ -415,7 +415,7 @@ fn index_crate<'a>( /// This hash will then be part of the crate_hash which is stored in the metadata. fn compute_hir_hash( tcx: TyCtxt<'_>, - owners: &IndexSlice>>, + owners: &IndexSlice>, ) -> Fingerprint { let mut hir_body_nodes: Vec<_> = owners .iter_enumerated() diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 681e228a0f2ff..de1b28acb1267 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -894,34 +894,23 @@ impl<'tcx> OwnerInfo<'tcx> { } #[derive(Copy, Clone, Debug, HashStable_Generic)] -pub enum MaybeOwner { - Owner(T), +pub enum MaybeOwner<'tcx> { + Owner(&'tcx OwnerInfo<'tcx>), NonOwner(HirId), /// Used as a placeholder for unused LocalDefId. Phantom, } -impl MaybeOwner { - pub fn as_owner(self) -> Option { +impl<'tcx> MaybeOwner<'tcx> { + pub fn as_owner(self) -> Option<&'tcx OwnerInfo<'tcx>> { match self { MaybeOwner::Owner(i) => Some(i), MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => None, } } - pub fn map(self, f: impl FnOnce(T) -> U) -> MaybeOwner { - match self { - MaybeOwner::Owner(i) => MaybeOwner::Owner(f(i)), - MaybeOwner::NonOwner(hir_id) => MaybeOwner::NonOwner(hir_id), - MaybeOwner::Phantom => MaybeOwner::Phantom, - } - } - - pub fn unwrap(self) -> T { - match self { - MaybeOwner::Owner(i) => i, - MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => panic!("Not a HIR owner"), - } + pub fn unwrap(self) -> &'tcx OwnerInfo<'tcx> { + self.as_owner().unwrap_or_else(|| panic!("Not a HIR owner")) } } @@ -933,7 +922,7 @@ impl MaybeOwner { /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #[derive(Debug)] pub struct Crate<'hir> { - pub owners: IndexVec>>, + pub owners: IndexVec>, // Only present when incr. comp. is enabled. pub opt_hir_hash: Option, } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index b54e438f6144d..94191df30a5e6 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -127,12 +127,11 @@ pub fn provide(providers: &mut Providers) { providers.hir_crate_items = map::hir_crate_items; providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; - providers.opt_local_def_id_to_hir_id = |tcx, id| { - let owner = tcx.hir_crate(()).owners[id].map(|_| ()); - Some(match owner { - MaybeOwner::Owner(_) => HirId::make_owner(id), - MaybeOwner::Phantom => bug!("No HirId for {:?}", id), + providers.opt_local_def_id_to_hir_id = |tcx, def_id| { + Some(match tcx.hir_crate(()).owners[def_id] { + MaybeOwner::Owner(_) => HirId::make_owner(def_id), MaybeOwner::NonOwner(hir_id) => hir_id, + MaybeOwner::Phantom => bug!("No HirId for {:?}", def_id), }) }; providers.opt_hir_owner_nodes = diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 1b01df6a18714..a272a51f32747 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -185,8 +185,8 @@ impl EraseType for Option>> { type Result = [u8; size_of::>>>()]; } -impl EraseType for rustc_hir::MaybeOwner<&'_ T> { - type Result = [u8; size_of::>()]; +impl EraseType for rustc_hir::MaybeOwner<'_> { + type Result = [u8; size_of::>()]; } impl EraseType for ty::EarlyBinder { From a605b9605e9ffe3acf96032dde0ebf607ace99fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sat, 3 Feb 2024 19:16:32 +0200 Subject: [PATCH 232/246] Bump release runners to MacOS 12 --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6a3cdfe3a3c7f..9077a9ac21eb6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -43,10 +43,10 @@ jobs: - os: ubuntu-20.04 target: arm-unknown-linux-gnueabihf code-target: linux-armhf - - os: macos-11 + - os: macos-12 target: x86_64-apple-darwin code-target: darwin-x64 - - os: macos-11 + - os: macos-12 target: aarch64-apple-darwin code-target: darwin-arm64 From 8ef369be882b81233071623d334d8d2488083894 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 3 Feb 2024 13:14:34 -0500 Subject: [PATCH 233/246] Bump to 1.78 --- src/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version b/src/version index 79e15fd49370a..54227249d1ff9 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.77.0 +1.78.0 From 8f1573a5853898dbb8196b287c670e79d4c4705b Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 15 Jan 2024 15:51:53 -0500 Subject: [PATCH 234/246] Release notes for 1.76 --- RELEASES.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 3fb74b52292c1..038a83cde84d6 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,96 @@ +Version 1.76.0 (2024-02-08) +========================== + + + +Language +-------- +- [Document Rust ABI compatibility between various types](https://github.com/rust-lang/rust/pull/115476/) +- [Also: guarantee that char and u32 are ABI-compatible](https://github.com/rust-lang/rust/pull/118032/) +- [Warn against ambiguous wide pointer comparisons](https://github.com/rust-lang/rust/pull/117758/) + + + +Compiler +-------- +- [Lint pinned `#[must_use]` pointers (in particular, `Box` where `T` is `#[must_use]`) in `unused_must_use`.](https://github.com/rust-lang/rust/pull/118054/) +- [Soundness fix: fix computing the offset of an unsized field in a packed struct](https://github.com/rust-lang/rust/pull/118540/) +- [Soundness fix: fix dynamic size/align computation logic for packed types with dyn Trait tail](https://github.com/rust-lang/rust/pull/118538/) +- [Add `$message_type` field to distinguish json diagnostic outputs](https://github.com/rust-lang/rust/pull/115691/) +- [Enable Rust to use the EHCont security feature of Windows](https://github.com/rust-lang/rust/pull/118013/) +- [Add tier 3 {x86_64,i686}-win7-windows-msvc targets](https://github.com/rust-lang/rust/pull/118150/) +- [Add tier 3 aarch64-apple-watchos target](https://github.com/rust-lang/rust/pull/119074/) +- [Add tier 3 arm64e-apple-ios & arm64e-apple-darwin targets](https://github.com/rust-lang/rust/pull/115526/) + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + + + +Libraries +--------- +- [Add a column number to `dbg!()`](https://github.com/rust-lang/rust/pull/114962/) +- [Add `std::hash::{DefaultHasher, RandomState}` exports](https://github.com/rust-lang/rust/pull/115694/) +- [Fix rounding issue with exponents in fmt](https://github.com/rust-lang/rust/pull/116301/) +- [Add T: ?Sized to `RwLockReadGuard` and `RwLockWriteGuard`'s Debug impls.](https://github.com/rust-lang/rust/pull/117138/) +- [Windows: Allow `File::create` to work on hidden files](https://github.com/rust-lang/rust/pull/116438/) + + + +Stabilized APIs +--------------- + +- [`Arc::unwrap_or_clone`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.unwrap_or_clone) +- [`Rc::unwrap_or_clone`](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.unwrap_or_clone) +- [`Result::inspect`](https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.inspect) +- [`Result::inspect_err`](https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.inspect_err) +- [`Option::inspect`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.inspect) +- [`type_name_of_val`](https://doc.rust-lang.org/stable/std/any/fn.type_name_of_val.html) +- [`std::hash::{DefaultHasher, RandomState}`](https://doc.rust-lang.org/stable/std/hash/index.html#structs) + These were previously available only through `std::collections::hash_map`. +- [`ptr::{from_ref, from_mut}`](https://doc.rust-lang.org/stable/std/ptr/fn.from_ref.html) +- [`ptr::addr_eq`](https://doc.rust-lang.org/stable/std/ptr/fn.addr_eq.html) + + + +Cargo +----- + +See [Cargo release notes](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-176-2024-02-08). + + + +Rustdoc +------- + +- [Don't merge cfg and doc(cfg) attributes for re-exports](https://github.com/rust-lang/rust/pull/113091/) +- [rustdoc: allow resizing the sidebar / hiding the top bar](https://github.com/rust-lang/rust/pull/115660/) +- [rustdoc-search: add support for traits and associated types](https://github.com/rust-lang/rust/pull/116085/) +- [rustdoc: Add highlighting for comments in items declaration](https://github.com/rust-lang/rust/pull/117869/) + + + +Compatibility Notes +------------------- +- [Add allow-by-default lint for unit bindings](https://github.com/rust-lang/rust/pull/112380/) + This is expected to be upgraded to a warning by default in a future Rust + release. Some macros emit bindings with type `()` with user-provided spans, + which means that this lint will warn for user code. +- [Remove x86_64-sun-solaris target.](https://github.com/rust-lang/rust/pull/118091/) +- [Remove asmjs-unknown-emscripten target](https://github.com/rust-lang/rust/pull/117338/) +- [Report errors in jobserver inherited through environment variables](https://github.com/rust-lang/rust/pull/113730/) + This [may warn](https://github.com/rust-lang/rust/issues/120515) on benign problems too. +- [Update the minimum external LLVM to 16.](https://github.com/rust-lang/rust/pull/117947/) +- [Improve `print_tts`](https://github.com/rust-lang/rust/pull/114571/) + This change can break some naive manual parsing of token trees in proc macro + code which expect a particular structure after `.to_string()`, rather than just arbitrary Rust code. +- [Make `IMPLIED_BOUNDS_ENTAILMENT` into a hard error from a lint](https://github.com/rust-lang/rust/pull/117984/) +- [Vec's allocation behavior was changed when collecting some iterators](https://github.com/rust-lang/rust/pull/110353) + Allocation behavior is currently not specified, nevertheless changes can be surprising. + See [`impl FromIterator for Vec`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#impl-FromIterator%3CT%3E-for-Vec%3CT%3E) + for more details. +- [Properly reject `default` on free const items](https://github.com/rust-lang/rust/pull/117818/) + Version 1.75.0 (2023-12-28) ========================== From 4f773af1cc17621e7c52afba6be2db21b2f3aba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 3 Feb 2024 17:34:25 +0100 Subject: [PATCH 235/246] Check for presence of field in typeck results before visiting it Co-authored-by: Michael Goulet --- compiler/rustc_passes/src/dead.rs | 6 +++++- .../field-access-after-const-eval-fail-in-ty.rs | 5 +++++ ...ld-access-after-const-eval-fail-in-ty.stderr | 17 +++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.rs create mode 100644 tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 9be286744351f..d19987cb33cf2 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -464,7 +464,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { self.lookup_and_handle_method(expr.hir_id); } hir::ExprKind::Field(ref lhs, ..) => { - self.handle_field_access(lhs, expr.hir_id); + if self.typeck_results().opt_field_index(expr.hir_id).is_some() { + self.handle_field_access(lhs, expr.hir_id); + } else { + self.tcx.dcx().span_delayed_bug(expr.span, "couldn't resolve index for field"); + } } hir::ExprKind::Struct(qpath, fields, _) => { let res = self.typeck_results().qpath_res(qpath, expr.hir_id); diff --git a/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.rs b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.rs new file mode 100644 index 0000000000000..3f1f208459d17 --- /dev/null +++ b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.rs @@ -0,0 +1,5 @@ +// Regression test for issue #120615. + +fn main() { + [(); loop {}].field; //~ ERROR constant evaluation is taking a long time +} diff --git a/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr new file mode 100644 index 0000000000000..9d62bbc2187f7 --- /dev/null +++ b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr @@ -0,0 +1,17 @@ +error: constant evaluation is taking a long time + --> $DIR/field-access-after-const-eval-fail-in-ty.rs:4:10 + | +LL | [(); loop {}].field; + | ^^^^^^^ + | + = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. + If your compilation actually takes a long time, you can safely allow the lint. +help: the constant being evaluated + --> $DIR/field-access-after-const-eval-fail-in-ty.rs:4:10 + | +LL | [(); loop {}].field; + | ^^^^^^^ + = note: `#[deny(long_running_const_eval)]` on by default + +error: aborting due to 1 previous error + From dff2114b46804855a93749ea7e8eeefca40ad4a2 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 3 Feb 2024 19:29:16 -0500 Subject: [PATCH 236/246] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 7bb7b539558dc..cdf84b69d0416 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 7bb7b539558dc88bea44cee4168b6269bf8177b0 +Subproject commit cdf84b69d0416c57ac9dc3459af80dfb4883d27a From 98ad126214821e64611e1b1e4ea9ee7b39578370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sun, 4 Feb 2024 11:07:35 +0200 Subject: [PATCH 237/246] Try to fix in-tree build --- src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs | 2 +- src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs | 2 +- src/tools/rust-analyzer/crates/hir-ty/src/utils.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 b67bb6c8661dd..5bfe7bf010f1c 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 @@ -2,7 +2,7 @@ use base_db::CrateId; use hir_def::layout::TargetDataLayout; -use ra_ap_rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors}; +use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors}; use triomphe::Arc; use crate::db::HirDatabase; 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 84ee60b56b23a..50c4d00660b7e 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 @@ -17,7 +17,7 @@ use hir_def::{ use hir_expand::{mod_path::ModPath, HirFileIdExt, InFile}; use intern::Interned; use la_arena::ArenaMap; -use ra_ap_rustc_abi::TargetDataLayout; +use rustc_abi::TargetDataLayout; use rustc_hash::{FxHashMap, FxHashSet}; use stdx::never; use syntax::{SyntaxNodePtr, TextRange}; 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 c0ca9d713ca31..c150314138ade 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -24,7 +24,7 @@ use hir_def::{ }; use hir_expand::name::Name; use intern::Interned; -use ra_ap_rustc_abi::TargetDataLayout; +use rustc_abi::TargetDataLayout; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; use stdx::never; From cb4e69ad67cd795ffcff18494c41d2f13c26904f Mon Sep 17 00:00:00 2001 From: klensy Date: Sun, 4 Feb 2024 15:11:16 +0300 Subject: [PATCH 238/246] rustdoc: trait.impl, type.impl: sort impls to make it not depend on serialization order --- src/librustdoc/html/render/write_shared.rs | 31 +++++++++++++++------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 6408e97df500d..fbd45b2b48ef9 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -593,11 +593,17 @@ else if (window.initSearch) window.initSearch(searchIndex); ret }) .collect::>(); - let impls = format!( - r#""{}":{}"#, - krate.name(cx.tcx()), - serde_json::to_string(&impls).expect("failed serde conversion"), - ); + + // FIXME: this fixes only rustdoc part of instability of trait impls + // for js files, see #120371 + // Manually collect to string and sort to make list not depend on order + let mut impls = impls + .iter() + .map(|i| serde_json::to_string(i).expect("failed serde conversion")) + .collect::>(); + impls.sort(); + + let impls = format!(r#""{}":[{}]"#, krate.name(cx.tcx()), impls.join(",")); let mut mydst = dst.clone(); for part in &aliased_type.target_fqp[..aliased_type.target_fqp.len() - 1] { @@ -702,11 +708,16 @@ else if (window.initSearch) window.initSearch(searchIndex); continue; } - let implementors = format!( - r#""{}":{}"#, - krate.name(cx.tcx()), - serde_json::to_string(&implementors).expect("failed serde conversion"), - ); + // FIXME: this fixes only rustdoc part of instability of trait impls + // for js files, see #120371 + // Manually collect to string and sort to make list not depend on order + let mut implementors = implementors + .iter() + .map(|i| serde_json::to_string(i).expect("failed serde conversion")) + .collect::>(); + implementors.sort(); + + let implementors = format!(r#""{}":[{}]"#, krate.name(cx.tcx()), implementors.join(",")); let mut mydst = dst.clone(); for part in &remote_path[..remote_path.len() - 1] { From fe420dc46ecf988eb13c34526feea18fd8daef6b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 22 Jan 2024 13:56:37 +1100 Subject: [PATCH 239/246] coverage: Test for closure body that is a single bang-macro --- tests/coverage/macro_in_closure.cov-map | 16 ++++++++++++++++ tests/coverage/macro_in_closure.coverage | 18 ++++++++++++++++++ tests/coverage/macro_in_closure.rs | 17 +++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 tests/coverage/macro_in_closure.cov-map create mode 100644 tests/coverage/macro_in_closure.coverage create mode 100644 tests/coverage/macro_in_closure.rs diff --git a/tests/coverage/macro_in_closure.cov-map b/tests/coverage/macro_in_closure.cov-map new file mode 100644 index 0000000000000..2feaab717b5cb --- /dev/null +++ b/tests/coverage/macro_in_closure.cov-map @@ -0,0 +1,16 @@ +Function name: macro_in_closure::NO_BLOCK::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 1c, 00, 2d] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 7, 28) to (start + 0, 45) + +Function name: macro_in_closure::WITH_BLOCK::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 1e, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 9, 30) to (start + 2, 2) + diff --git a/tests/coverage/macro_in_closure.coverage b/tests/coverage/macro_in_closure.coverage new file mode 100644 index 0000000000000..7f6f873439dff --- /dev/null +++ b/tests/coverage/macro_in_closure.coverage @@ -0,0 +1,18 @@ + LL| |#![feature(coverage_attribute)] + LL| |// edition: 2021 + LL| | + LL| |// If a closure body consists entirely of a single bang-macro invocation, the + LL| |// body span ends up inside the macro-expansion, so we need to un-expand it + LL| |// back to the declaration site. + LL| 1|static NO_BLOCK: fn() = || println!("hello"); + LL| | + LL| 1|static WITH_BLOCK: fn() = || { + LL| 1| println!("hello"); + LL| 1|}; + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | NO_BLOCK(); + LL| | WITH_BLOCK(); + LL| |} + diff --git a/tests/coverage/macro_in_closure.rs b/tests/coverage/macro_in_closure.rs new file mode 100644 index 0000000000000..6948c9079c09c --- /dev/null +++ b/tests/coverage/macro_in_closure.rs @@ -0,0 +1,17 @@ +#![feature(coverage_attribute)] +// edition: 2021 + +// If a closure body consists entirely of a single bang-macro invocation, the +// body span ends up inside the macro-expansion, so we need to un-expand it +// back to the declaration site. +static NO_BLOCK: fn() = || println!("hello"); + +static WITH_BLOCK: fn() = || { + println!("hello"); +}; + +#[coverage(off)] +fn main() { + NO_BLOCK(); + WITH_BLOCK(); +} From 8dd2b37462a2017207d4ecb01d3123881d8ec2f2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 20 Jan 2024 18:23:49 +1100 Subject: [PATCH 240/246] coverage: Add a test for `#[coverage(..)]` on closures --- tests/coverage/coverage_attr_closure.cov-map | 34 +++++++++++++++ tests/coverage/coverage_attr_closure.coverage | 43 +++++++++++++++++++ tests/coverage/coverage_attr_closure.rs | 42 ++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 tests/coverage/coverage_attr_closure.cov-map create mode 100644 tests/coverage/coverage_attr_closure.coverage create mode 100644 tests/coverage/coverage_attr_closure.rs diff --git a/tests/coverage/coverage_attr_closure.cov-map b/tests/coverage/coverage_attr_closure.cov-map new file mode 100644 index 0000000000000..2208b28fd4149 --- /dev/null +++ b/tests/coverage/coverage_attr_closure.cov-map @@ -0,0 +1,34 @@ +Function name: coverage_attr_closure::GLOBAL_CLOSURE_ON::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 06, 0f, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 6, 15) to (start + 2, 2) + +Function name: coverage_attr_closure::contains_closures_off::{closure#0} (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 1d, 13, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 29, 19) to (start + 2, 6) + +Function name: coverage_attr_closure::contains_closures_on +Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 02, 05, 01, 04, 06, 02, 05, 01, 04, 06, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 5) +- Code(Counter(0)) at (prev + 4, 6) to (start + 2, 5) +- Code(Counter(0)) at (prev + 4, 6) to (start + 1, 2) + +Function name: coverage_attr_closure::contains_closures_on::{closure#0} (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 13, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 17, 19) to (start + 2, 6) + diff --git a/tests/coverage/coverage_attr_closure.coverage b/tests/coverage/coverage_attr_closure.coverage new file mode 100644 index 0000000000000..32c75b40d83c0 --- /dev/null +++ b/tests/coverage/coverage_attr_closure.coverage @@ -0,0 +1,43 @@ + LL| |#![feature(coverage_attribute, stmt_expr_attributes)] + LL| |#![allow(dead_code)] + LL| |// edition: 2021 + LL| | + LL| |static GLOBAL_CLOSURE_ON: fn(&str) = #[coverage(on)] + LL| 0||input: &str| { + LL| 0| println!("{input}"); + LL| 0|}; + LL| |static GLOBAL_CLOSURE_OFF: fn(&str) = #[coverage(off)] + LL| ||input: &str| { + LL| | println!("{input}"); + LL| |}; + LL| | + LL| |#[coverage(on)] + LL| 1|fn contains_closures_on() { + LL| 1| let _local_closure_on = #[coverage(on)] + LL| 1| |input: &str| { + LL| 0| println!("{input}"); + LL| 1| }; + LL| 1| let _local_closure_off = #[coverage(off)] + LL| 1| |input: &str| { + LL| | println!("{input}"); + LL| 1| }; + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn contains_closures_off() { + LL| | let _local_closure_on = #[coverage(on)] + LL| 0| |input: &str| { + LL| 0| println!("{input}"); + LL| 0| }; + LL| | let _local_closure_off = #[coverage(off)] + LL| | |input: &str| { + LL| | println!("{input}"); + LL| | }; + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | contains_closures_on(); + LL| | contains_closures_off(); + LL| |} + diff --git a/tests/coverage/coverage_attr_closure.rs b/tests/coverage/coverage_attr_closure.rs new file mode 100644 index 0000000000000..1904c89c9204d --- /dev/null +++ b/tests/coverage/coverage_attr_closure.rs @@ -0,0 +1,42 @@ +#![feature(coverage_attribute, stmt_expr_attributes)] +#![allow(dead_code)] +// edition: 2021 + +static GLOBAL_CLOSURE_ON: fn(&str) = #[coverage(on)] +|input: &str| { + println!("{input}"); +}; +static GLOBAL_CLOSURE_OFF: fn(&str) = #[coverage(off)] +|input: &str| { + println!("{input}"); +}; + +#[coverage(on)] +fn contains_closures_on() { + let _local_closure_on = #[coverage(on)] + |input: &str| { + println!("{input}"); + }; + let _local_closure_off = #[coverage(off)] + |input: &str| { + println!("{input}"); + }; +} + +#[coverage(off)] +fn contains_closures_off() { + let _local_closure_on = #[coverage(on)] + |input: &str| { + println!("{input}"); + }; + let _local_closure_off = #[coverage(off)] + |input: &str| { + println!("{input}"); + }; +} + +#[coverage(off)] +fn main() { + contains_closures_on(); + contains_closures_off(); +} From dd6d7f27e46ae68ee183d8b41eb481b39cb881c6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 22 Jan 2024 12:49:58 +1100 Subject: [PATCH 241/246] coverage: Make unexpansion of closure bodies more precise This improves the coverage instrumentation of closures declared in macros, as seen in `closure_macro.rs` and `closure_macro_async.rs`. --- .../rustc_mir_transform/src/coverage/mod.rs | 30 ++++++++----------- tests/coverage/closure_macro.cov-map | 25 +++++++++++----- tests/coverage/closure_macro.coverage | 17 +++++------ tests/coverage/closure_macro.rs | 3 +- tests/coverage/closure_macro_async.cov-map | 17 ++++++++--- tests/coverage/closure_macro_async.coverage | 16 +++++----- tests/coverage/closure_macro_async.rs | 2 +- 7 files changed, 60 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 5fb72fcf0cf3e..b8bce7c3fb6c7 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -408,7 +408,18 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir let hir_body = tcx.hir().body(fn_body_id); let is_async_fn = hir_node.fn_sig().is_some_and(|fn_sig| fn_sig.header.is_async()); - let body_span = get_body_span(tcx, hir_body, def_id); + + let mut body_span = hir_body.value.span; + + use rustc_hir::{Closure, Expr, ExprKind, Node}; + // Unexpand a closure's body span back to the context of its declaration. + // This helps with closure bodies that consist of just a single bang-macro, + // and also with closure bodies produced by async desugaring. + if let Node::Expr(&Expr { kind: ExprKind::Closure(&Closure { fn_decl_span, .. }), .. }) = + hir_node + { + body_span = body_span.find_ancestor_in_same_ctxt(fn_decl_span).unwrap_or(body_span); + } // The actual signature span is only used if it has the same context and // filename as the body, and precedes the body. @@ -432,23 +443,6 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir ExtractedHirInfo { function_source_hash, is_async_fn, fn_sig_span, body_span } } -fn get_body_span<'tcx>( - tcx: TyCtxt<'tcx>, - hir_body: &rustc_hir::Body<'tcx>, - def_id: LocalDefId, -) -> Span { - let mut body_span = hir_body.value.span; - - if tcx.is_closure_or_coroutine(def_id.to_def_id()) { - // If the current function is a closure, and its "body" span was created - // by macro expansion or compiler desugaring, try to walk backwards to - // the pre-expansion call site or body. - body_span = body_span.source_callsite(); - } - - body_span -} - fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 { // FIXME(cjgillot) Stop hashing HIR manually here. let owner = hir_body.id().hir_id.owner; diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index 323d6e3c8aa52..571e5564b659c 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -1,20 +1,20 @@ Function name: closure_macro::load_configuration_files -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) Function name: closure_macro::main -Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 22, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 34, 1) to (start + 1, 33) +- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) @@ -27,10 +27,19 @@ Number of file 0 mappings: 7 = (c1 + (c0 - c1)) Function name: closure_macro::main::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 12, 00, 54] +Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 10, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 36, 18) to (start + 0, 84) +Number of expressions: 3 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) +- expression 2 operands: lhs = Counter(2), rhs = Zero +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 16, 28) to (start + 3, 33) +- Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) +- Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) + = (c0 - c1) +- Code(Zero) at (prev + 0, 23) to (start + 0, 30) +- Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) + = (c1 + (c2 + Zero)) diff --git a/tests/coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage index ab152a91356a0..716d75cb8d754 100644 --- a/tests/coverage/closure_macro.coverage +++ b/tests/coverage/closure_macro.coverage @@ -1,4 +1,3 @@ - LL| |#![feature(coverage_attribute)] LL| |// edition: 2018 LL| | LL| |macro_rules! bail { @@ -14,16 +13,16 @@ LL| | LL| |macro_rules! on_error { LL| | ($value:expr, $error_message:expr) => { - LL| | $value.or_else(|e| { - LL| | // FIXME(85000): no coverage in closure macros - LL| | let message = format!($error_message, e); - LL| | if message.len() > 0 { - LL| | println!("{}", message); - LL| | Ok(String::from("ok")) + LL| 0| $value.or_else(|e| { + LL| 0| // This closure, which is declared in a macro, should be instrumented. + LL| 0| let message = format!($error_message, e); + LL| 0| if message.len() > 0 { + LL| 0| println!("{}", message); + LL| 0| Ok(String::from("ok")) LL| | } else { - LL| | bail!("error"); + LL| 0| bail!("error"); LL| | } - LL| | }) + LL| 0| }) LL| | }; LL| |} LL| | diff --git a/tests/coverage/closure_macro.rs b/tests/coverage/closure_macro.rs index 38a81ea434b9b..6fe1212de8d0b 100644 --- a/tests/coverage/closure_macro.rs +++ b/tests/coverage/closure_macro.rs @@ -1,4 +1,3 @@ -#![feature(coverage_attribute)] // edition: 2018 macro_rules! bail { @@ -15,7 +14,7 @@ macro_rules! bail { macro_rules! on_error { ($value:expr, $error_message:expr) => { $value.or_else(|e| { - // FIXME(85000): no coverage in closure macros + // This closure, which is declared in a macro, should be instrumented. let message = format!($error_message, e); if message.len() > 0 { println!("{}", message); diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 5f5e064427890..49ec767eab33e 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -35,10 +35,19 @@ Number of file 0 mappings: 7 = (c1 + (c0 - c1)) Function name: closure_macro_async::test::{closure#0}::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 12, 00, 54] +Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 12, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 37, 18) to (start + 0, 84) +Number of expressions: 3 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) +- expression 2 operands: lhs = Counter(2), rhs = Zero +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 18, 28) to (start + 3, 33) +- Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) +- Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) + = (c0 - c1) +- Code(Zero) at (prev + 0, 23) to (start + 0, 30) +- Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) + = (c1 + (c2 + Zero)) diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage index d67c2ed524b38..1032e027cd97d 100644 --- a/tests/coverage/closure_macro_async.coverage +++ b/tests/coverage/closure_macro_async.coverage @@ -15,16 +15,16 @@ LL| | LL| |macro_rules! on_error { LL| | ($value:expr, $error_message:expr) => { - LL| | $value.or_else(|e| { - LL| | // FIXME(85000): no coverage in closure macros - LL| | let message = format!($error_message, e); - LL| | if message.len() > 0 { - LL| | println!("{}", message); - LL| | Ok(String::from("ok")) + LL| 0| $value.or_else(|e| { + LL| 0| // This closure, which is declared in a macro, should be instrumented. + LL| 0| let message = format!($error_message, e); + LL| 0| if message.len() > 0 { + LL| 0| println!("{}", message); + LL| 0| Ok(String::from("ok")) LL| | } else { - LL| | bail!("error"); + LL| 0| bail!("error"); LL| | } - LL| | }) + LL| 0| }) LL| | }; LL| |} LL| | diff --git a/tests/coverage/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs index 116cb72b0f375..db656fca19836 100644 --- a/tests/coverage/closure_macro_async.rs +++ b/tests/coverage/closure_macro_async.rs @@ -16,7 +16,7 @@ macro_rules! bail { macro_rules! on_error { ($value:expr, $error_message:expr) => { $value.or_else(|e| { - // FIXME(85000): no coverage in closure macros + // This closure, which is declared in a macro, should be instrumented. let message = format!($error_message, e); if message.len() > 0 { println!("{}", message); From fde1702db86a8de4849caca12787d74525d06344 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 22:07:21 +1100 Subject: [PATCH 242/246] coverage: Hoist special handling of async function spans This sidesteps the normal span refinement code in cases where we know that we are only dealing with the special signature span that represents having called an async function. --- .../rustc_mir_transform/src/coverage/spans.rs | 28 +++++++++++++------ .../src/coverage/spans/from_mir.rs | 28 +++++++------------ 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index dee6a3b7143f5..6db16262a70c0 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -3,7 +3,7 @@ use rustc_index::bit_set::BitSet; use rustc_middle::mir; use rustc_span::{BytePos, Span, DUMMY_SP}; -use super::graph::{BasicCoverageBlock, CoverageGraph}; +use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB}; use crate::coverage::ExtractedHirInfo; mod from_mir; @@ -46,13 +46,25 @@ pub(super) fn generate_coverage_spans( ) -> Option { let mut mappings = vec![]; - let sorted_spans = - from_mir::mir_to_initial_sorted_coverage_spans(mir_body, hir_info, basic_coverage_blocks); - let coverage_spans = SpansRefiner::refine_sorted_spans(basic_coverage_blocks, sorted_spans); - mappings.extend(coverage_spans.into_iter().map(|CoverageSpan { bcb, span, .. }| { - // Each span produced by the generator represents an ordinary code region. - BcbMapping { kind: BcbMappingKind::Code(bcb), span } - })); + if hir_info.is_async_fn { + // An async function desugars into a function that returns a future, + // with the user code wrapped in a closure. Any spans in the desugared + // outer function will be unhelpful, so just keep the signature span + // and ignore all of the spans in the MIR body. + let span = hir_info.fn_sig_span; + mappings.push(BcbMapping { kind: BcbMappingKind::Code(START_BCB), span }); + } else { + let sorted_spans = from_mir::mir_to_initial_sorted_coverage_spans( + mir_body, + hir_info, + basic_coverage_blocks, + ); + let coverage_spans = SpansRefiner::refine_sorted_spans(basic_coverage_blocks, sorted_spans); + mappings.extend(coverage_spans.into_iter().map(|CoverageSpan { bcb, span, .. }| { + // Each span produced by the generator represents an ordinary code region. + BcbMapping { kind: BcbMappingKind::Code(bcb), span } + })); + } if mappings.is_empty() { return None; 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 8d8e8e6132743..63371a39f5a8c 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -23,25 +23,17 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( hir_info: &ExtractedHirInfo, basic_coverage_blocks: &CoverageGraph, ) -> Vec { - let &ExtractedHirInfo { is_async_fn, fn_sig_span, body_span, .. } = hir_info; - - let mut initial_spans = vec![SpanFromMir::for_fn_sig(fn_sig_span)]; - - if is_async_fn { - // An async function desugars into a function that returns a future, - // with the user code wrapped in a closure. Any spans in the desugared - // outer function will be unhelpful, so just keep the signature span - // and ignore all of the spans in the MIR body. - } else { - for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() { - initial_spans.extend(bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data)); - } + let &ExtractedHirInfo { fn_sig_span, body_span, .. } = hir_info; - // If no spans were extracted from the body, discard the signature span. - // FIXME: This preserves existing behavior; consider getting rid of it. - if initial_spans.len() == 1 { - initial_spans.clear(); - } + let mut initial_spans = vec![]; + + for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() { + initial_spans.extend(bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data)); + } + + // Only add the signature span if we found at least one span in the body. + if !initial_spans.is_empty() { + initial_spans.push(SpanFromMir::for_fn_sig(fn_sig_span)); } initial_spans.sort_by(|a, b| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb)); From a246b6be1dcd4a8ea0ac468921af7e8022686849 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 22 Jan 2024 17:04:13 +1100 Subject: [PATCH 243/246] coverage: Make `fn_sig_span` optional, and note its quirks --- .../rustc_mir_transform/src/coverage/mod.rs | 17 +++++++++-------- .../rustc_mir_transform/src/coverage/spans.rs | 5 +++-- .../src/coverage/spans/from_mir.rs | 6 +++++- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index b8bce7c3fb6c7..3aa41250fd37b 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -394,7 +394,9 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { struct ExtractedHirInfo { function_source_hash: u64, is_async_fn: bool, - fn_sig_span: Span, + /// The span of the function's signature, extended to the start of `body_span`. + /// Must have the same context and filename as the body span. + fn_sig_span_extended: Option, body_span: Span, } @@ -407,7 +409,8 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir hir::map::associated_body(hir_node).expect("HIR node is a function with body"); let hir_body = tcx.hir().body(fn_body_id); - let is_async_fn = hir_node.fn_sig().is_some_and(|fn_sig| fn_sig.header.is_async()); + let maybe_fn_sig = hir_node.fn_sig(); + let is_async_fn = maybe_fn_sig.is_some_and(|fn_sig| fn_sig.header.is_async()); let mut body_span = hir_body.value.span; @@ -423,8 +426,8 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir // The actual signature span is only used if it has the same context and // filename as the body, and precedes the body. - let maybe_fn_sig_span = hir_node.fn_sig().map(|fn_sig| fn_sig.span); - let fn_sig_span = maybe_fn_sig_span + let fn_sig_span_extended = maybe_fn_sig + .map(|fn_sig| fn_sig.span) .filter(|&fn_sig_span| { let source_map = tcx.sess.source_map(); let file_idx = |span: Span| source_map.lookup_source_file_idx(span.lo()); @@ -434,13 +437,11 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir && file_idx(fn_sig_span) == file_idx(body_span) }) // If so, extend it to the start of the body span. - .map(|fn_sig_span| fn_sig_span.with_hi(body_span.lo())) - // Otherwise, create a dummy signature span at the start of the body. - .unwrap_or_else(|| body_span.shrink_to_lo()); + .map(|fn_sig_span| fn_sig_span.with_hi(body_span.lo())); let function_source_hash = hash_mir_source(tcx, hir_body); - ExtractedHirInfo { function_source_hash, is_async_fn, fn_sig_span, body_span } + ExtractedHirInfo { function_source_hash, is_async_fn, fn_sig_span_extended, body_span } } fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 { diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 6db16262a70c0..d3d0c7bcc9501 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -51,8 +51,9 @@ pub(super) fn generate_coverage_spans( // with the user code wrapped in a closure. Any spans in the desugared // outer function will be unhelpful, so just keep the signature span // and ignore all of the spans in the MIR body. - let span = hir_info.fn_sig_span; - mappings.push(BcbMapping { kind: BcbMappingKind::Code(START_BCB), span }); + if let Some(span) = hir_info.fn_sig_span_extended { + mappings.push(BcbMapping { kind: BcbMappingKind::Code(START_BCB), span }); + } } else { let sorted_spans = from_mir::mir_to_initial_sorted_coverage_spans( mir_body, 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 63371a39f5a8c..5b4d58836b486 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -23,7 +23,7 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( hir_info: &ExtractedHirInfo, basic_coverage_blocks: &CoverageGraph, ) -> Vec { - let &ExtractedHirInfo { fn_sig_span, body_span, .. } = hir_info; + let &ExtractedHirInfo { body_span, .. } = hir_info; let mut initial_spans = vec![]; @@ -33,6 +33,10 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( // Only add the signature span if we found at least one span in the body. if !initial_spans.is_empty() { + // If there is no usable signature span, add a fake one (before refinement) + // to avoid an ugly gap between the body start and the first real span. + // FIXME: Find a more principled way to solve this problem. + let fn_sig_span = hir_info.fn_sig_span_extended.unwrap_or_else(|| body_span.shrink_to_lo()); initial_spans.push(SpanFromMir::for_fn_sig(fn_sig_span)); } From 8266657338994c5dc26f571a3776c2afa6ca150d Mon Sep 17 00:00:00 2001 From: r0cky Date: Mon, 5 Feb 2024 08:07:55 +0800 Subject: [PATCH 244/246] Remove unused struct --- library/std/src/sys/pal/sgx/net.rs | 3 --- library/std/src/sys/pal/teeos/net.rs | 3 --- library/std/src/sys/pal/xous/net/mod.rs | 3 --- 3 files changed, 9 deletions(-) diff --git a/library/std/src/sys/pal/sgx/net.rs b/library/std/src/sys/pal/sgx/net.rs index 03620a08f2c03..c4d5da1627cb2 100644 --- a/library/std/src/sys/pal/sgx/net.rs +++ b/library/std/src/sys/pal/sgx/net.rs @@ -542,7 +542,4 @@ pub mod netc { pub sin6_flowinfo: u32, pub sin6_scope_id: u32, } - - #[derive(Copy, Clone)] - pub struct sockaddr {} } diff --git a/library/std/src/sys/pal/teeos/net.rs b/library/std/src/sys/pal/teeos/net.rs index 0df681dbfa552..fed95205027a7 100644 --- a/library/std/src/sys/pal/teeos/net.rs +++ b/library/std/src/sys/pal/teeos/net.rs @@ -364,9 +364,6 @@ pub mod netc { pub sin6_flowinfo: u32, pub sin6_scope_id: u32, } - - #[derive(Copy, Clone)] - pub struct sockaddr {} } pub type Socket = UdpSocket; diff --git a/library/std/src/sys/pal/xous/net/mod.rs b/library/std/src/sys/pal/xous/net/mod.rs index b5a3da136a6b0..dd8b765aa74ae 100644 --- a/library/std/src/sys/pal/xous/net/mod.rs +++ b/library/std/src/sys/pal/xous/net/mod.rs @@ -78,7 +78,4 @@ pub mod netc { pub sin6_flowinfo: u32, pub sin6_scope_id: u32, } - - #[derive(Copy, Clone)] - pub struct sockaddr {} } From 35dad14dfb63d77cf4a2077f1e8e9cff5a02a92b Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Mon, 5 Feb 2024 13:18:32 +0800 Subject: [PATCH 245/246] target: default to the medium code model on LoongArch targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Rust LoongArch targets have been using the default LLVM code model so far, which is "small" in LLVM-speak and "normal" in LoongArch-speak. As described in the "Code Model" section of LoongArch ELF psABI spec v20231219 [1], one can only make function calls as far as ±128MiB with the "normal" code model; this is insufficient for very large software containing Rust components that needs to be linked into the big text section, such as Chromium. Because: * we do not want to ask users to recompile std if they are to build such software, * objects compiled with larger code models can be linked with those with smaller code models without problems, and * the "medium" code model is comparable to the "small"/"normal" one performance-wise (same data access pattern; each function call becomes 2-insn long and indirect, but this may be relaxed back into the direct 1-insn form in a future LLVM version), but is able to perform function calls within ±128GiB, it is better to just switch the targets to the "medium" code model, which is also "medium" in LLVM-speak. [1]: https://github.com/loongson/la-abi-specs/blob/v2.30/laelf.adoc#code-models --- .../src/spec/targets/loongarch64_unknown_linux_gnu.rs | 3 ++- .../rustc_target/src/spec/targets/loongarch64_unknown_none.rs | 2 +- .../src/spec/targets/loongarch64_unknown_none_softfloat.rs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs index 0f05e7c475a83..cb24e740c86f2 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{base, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -7,6 +7,7 @@ pub fn target() -> Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), arch: "loongarch64".into(), options: TargetOptions { + code_model: Some(CodeModel::Medium), cpu: "generic".into(), features: "+f,+d".into(), llvm_abiname: "lp64d".into(), diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs index 3b1ea8e206f1c..f448017a2a58d 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs @@ -16,7 +16,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, - code_model: Some(CodeModel::Small), + code_model: Some(CodeModel::Medium), ..Default::default() }, } diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs index ab9300ef9c723..d636c9599a7be 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs @@ -17,7 +17,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, - code_model: Some(CodeModel::Small), + code_model: Some(CodeModel::Medium), ..Default::default() }, } From eaa2da5d921225266d714d8d28b87cc8d131bcae Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Tue, 6 Feb 2024 05:10:11 +0000 Subject: [PATCH 246/246] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index e36763cc7ab31..f3e10689ff1d4 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -80deabd0987201e1b8d060400f50e03309a0105e +f3b9d47a46c6d237665801155aa3e26c5f49958b